├── frida_scripts ├── .gitignore ├── tsconfig.json ├── agent │ ├── logger.ts │ ├── util.ts │ ├── helper.ts │ └── index.ts ├── README.md ├── package.json ├── _agent.js └── package-lock.json ├── .gitignore ├── images ├── Snipaste_2022-01-16_22-55-59.png ├── Snipaste_2022-01-16_22-58-05.png ├── Snipaste_2022-01-16_23-12-27.png ├── Snipaste_2022-05-14_17-11-53.png ├── Snipaste_2022-05-14_17-15-31.png ├── Snipaste_2022-05-21_18-25-27.png ├── Snipaste_2022-05-21_19-16-15.png ├── Snipaste_2022-05-21_19-49-58.png ├── Snipaste_2022-05-21_20-17-12.png ├── Snipaste_2022-05-21_20-21-20.png ├── Snipaste_2022-05-21_20-38-11.png ├── Snipaste_2022-05-21_20-39-20.png ├── Snipaste_2022-05-21_20-41-05.png ├── Snipaste_2022-05-21_20-46-41.png ├── Snipaste_2022-05-21_20-55-12.png ├── Snipaste_2022-05-21_21-02-06.png ├── Snipaste_2022-05-21_21-12-09.png ├── Snipaste_2022-05-21_21-24-24.png ├── Snipaste_2022-05-21_21-25-51.png ├── Snipaste_2022-05-21_21-33-24.png ├── Snipaste_2022-05-21_21-59-35.png ├── Snipaste_2022-05-21_22-26-07.png ├── Snipaste_2022-05-21_22-28-30.png ├── Snipaste_2022-05-21_22-30-25.png ├── Snipaste_2022-05-21_22-32-29.png ├── Snipaste_2022-05-21_22-36-52.png ├── Snipaste_2022-05-21_22-48-36.png ├── Snipaste_2022-05-21_22-49-13.png ├── Snipaste_2022-05-21_22-51-33.png ├── Snipaste_2022-05-21_23-03-53.png ├── Snipaste_2022-05-21_23-06-55.png ├── Snipaste_2022-05-21_23-13-06.png ├── Snipaste_2022-05-21_23-15-33.png ├── Snipaste_2022-05-21_23-30-06.png └── Snipaste_2022-05-21_23-50-43.png ├── README.md └── 纯frida实现smali追踪.md /frida_scripts/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.so 2 | *.id0 3 | *.id1 4 | *.id2 5 | *.nam 6 | *.til -------------------------------------------------------------------------------- /images/Snipaste_2022-01-16_22-55-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-01-16_22-55-59.png -------------------------------------------------------------------------------- /images/Snipaste_2022-01-16_22-58-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-01-16_22-58-05.png -------------------------------------------------------------------------------- /images/Snipaste_2022-01-16_23-12-27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-01-16_23-12-27.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-14_17-11-53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-14_17-11-53.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-14_17-15-31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-14_17-15-31.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_18-25-27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_18-25-27.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_19-16-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_19-16-15.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_19-49-58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_19-49-58.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_20-17-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_20-17-12.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_20-21-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_20-21-20.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_20-38-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_20-38-11.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_20-39-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_20-39-20.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_20-41-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_20-41-05.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_20-46-41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_20-46-41.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_20-55-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_20-55-12.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_21-02-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_21-02-06.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_21-12-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_21-12-09.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_21-24-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_21-24-24.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_21-25-51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_21-25-51.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_21-33-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_21-33-24.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_21-59-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_21-59-35.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_22-26-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_22-26-07.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_22-28-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_22-28-30.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_22-30-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_22-30-25.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_22-32-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_22-32-29.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_22-36-52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_22-36-52.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_22-48-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_22-48-36.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_22-49-13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_22-49-13.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_22-51-33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_22-51-33.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_23-03-53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_23-03-53.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_23-06-55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_23-06-55.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_23-13-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_23-13-06.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_23-15-33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_23-15-33.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_23-30-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_23-30-06.png -------------------------------------------------------------------------------- /images/Snipaste_2022-05-21_23-50-43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SeeFlowerX/frida-smali-trace/HEAD/images/Snipaste_2022-05-21_23-50-43.png -------------------------------------------------------------------------------- /frida_scripts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "lib": ["es2020"], 5 | "allowJs": true, 6 | "noEmit": true, 7 | "strict": true, 8 | "esModuleInterop": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /frida_scripts/agent/logger.ts: -------------------------------------------------------------------------------- 1 | import { rpc_mode } from "./index"; 2 | 3 | export function log(message: string): void { 4 | if(rpc_mode){ 5 | send({"type": "log", info: message}); 6 | } 7 | else{ 8 | console.log(message); 9 | } 10 | } -------------------------------------------------------------------------------- /frida_scripts/README.md: -------------------------------------------------------------------------------- 1 | ### How to compile & load 2 | 3 | ```sh 4 | $ git clone git://github.com/oleavr/frida-agent-example.git 5 | $ cd frida-agent-example/ 6 | $ npm install 7 | $ frida -U -f com.example.android --no-pause -l _agent.js 8 | ``` 9 | 10 | ### Development workflow 11 | 12 | To continuously recompile on change, keep this running in a terminal: 13 | 14 | ```sh 15 | $ npm run watch 16 | ``` 17 | 18 | And use an editor like Visual Studio Code for code completion and instant 19 | type-checking feedback. 20 | -------------------------------------------------------------------------------- /frida_scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frida-agent-example", 3 | "version": "1.0.0", 4 | "description": "Example Frida agent written in TypeScript", 5 | "private": true, 6 | "main": "agent/index.ts", 7 | "scripts": { 8 | "prepare": "npm run build", 9 | "build": "frida-compile agent/index.ts -o _agent.js -c", 10 | "watch": "frida-compile agent/index.ts -o _agent.js -w" 11 | }, 12 | "devDependencies": { 13 | "@types/frida-gum": "^17.1.0", 14 | "@types/node": "^16.4.8", 15 | "frida-compile": "^10.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /frida_scripts/agent/util.ts: -------------------------------------------------------------------------------- 1 | import { GetObsoleteDexCache_func, PrettyMethod } from "./helper"; 2 | import { log } from "./logger"; 3 | 4 | export class SwitchImplContext { 5 | 6 | pointer: NativePointer; 7 | thread_ptr: NativePointer; 8 | accessor: CodeItemDataAccessor; 9 | shadow_frame: ShadowFrame; 10 | 11 | constructor (pointer: NativePointer){ 12 | this.pointer = pointer; 13 | this.thread_ptr = this.pointer.readPointer(); 14 | this.accessor = new CodeItemDataAccessor(this.pointer.add(Process.pointerSize).readPointer()); 15 | this.shadow_frame = new ShadowFrame(this.pointer.add(Process.pointerSize * 2).readPointer()); 16 | } 17 | 18 | } 19 | 20 | 21 | export class CodeItemDataAccessor { 22 | 23 | pointer: NativePointer; 24 | insns: NativePointer; 25 | 26 | constructor (pointer: NativePointer){ 27 | this.pointer = pointer; 28 | this.insns = this.pointer.add(Process.pointerSize).readPointer(); 29 | } 30 | 31 | Insns(): NativePointer { 32 | return this.insns; 33 | } 34 | 35 | } 36 | 37 | export class ShadowFrame { 38 | 39 | pointer: NativePointer; 40 | method: ArtMethod; 41 | 42 | constructor (pointer: NativePointer){ 43 | this.pointer = pointer; 44 | this.method = new ArtMethod(this.pointer.add(Process.pointerSize).readPointer()); 45 | } 46 | 47 | toString(): string{ 48 | return this.pointer.toString(); 49 | } 50 | 51 | GetDexPC(): number { 52 | let dex_pc_ptr_ = this.pointer.add(Process.pointerSize * 3).readPointer(); 53 | if (!dex_pc_ptr_.equals(ptr(0x0))){ 54 | let dex_instructions_ = this.pointer.add(Process.pointerSize * 4).readPointer(); 55 | return Number(dex_pc_ptr_.sub(dex_instructions_).toString()); 56 | } 57 | else{ 58 | return this.pointer.add(Process.pointerSize * 6 + 4).readU32(); 59 | } 60 | 61 | } 62 | 63 | } 64 | 65 | export class ArtMethod { 66 | 67 | pointer: NativePointer; 68 | 69 | constructor (pointer: NativePointer){ 70 | this.pointer = pointer; 71 | } 72 | 73 | toString(): string { 74 | return this.pointer.toString(); 75 | } 76 | 77 | PrettyMethod(): string | null { 78 | return PrettyMethod(this.pointer); 79 | } 80 | 81 | GetObsoleteDexCache(): NativePointer{ 82 | // mirror_ptr ??? 83 | return GetObsoleteDexCache_func(this.pointer); 84 | // return ptr(0x0); 85 | } 86 | 87 | GetDexFile(): NativePointer { 88 | let access_flags = this.pointer.add(0x4).readU32(); 89 | // IsObsolete() => (GetAccessFlags() & kAccObsoleteMethod) != 0; 90 | if ((access_flags & 0x40000) != 0){ 91 | log(`flag => ${access_flags}`); 92 | return this.GetObsoleteDexCache(); 93 | } 94 | else{ 95 | let declaring_class_ptr = ptr(this.pointer.readU32()); 96 | let dex_cache_ptr = ptr(declaring_class_ptr.add(0x10).readU32()); 97 | let dex_file_ptr = dex_cache_ptr.add(0x10).readPointer(); 98 | return dex_file_ptr; 99 | } 100 | } 101 | 102 | } -------------------------------------------------------------------------------- /frida_scripts/agent/helper.ts: -------------------------------------------------------------------------------- 1 | import { log } from "./logger"; 2 | 3 | export function get_PrettyMethod(){ 4 | // let PrettyMethod_ptr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod12PrettyMethodEPS0_b"); 5 | let PrettyMethod_ptr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod12PrettyMethodEb"); 6 | if (PrettyMethod_ptr == null){ 7 | log(`libart.so PrettyMethod_ptr is null`); 8 | return; 9 | } 10 | log(`PrettyMethod_ptr => ${PrettyMethod_ptr}`); 11 | let PrettyMethod_func = new NativeFunction(PrettyMethod_ptr, ["pointer", "pointer", "pointer"], ["pointer", "bool"]); 12 | return PrettyMethod_func; 13 | } 14 | 15 | export function get_GetObsoleteDexCache(){ 16 | let GetObsoleteDexCache_ptr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod19GetObsoleteDexCacheEv"); 17 | if (GetObsoleteDexCache_ptr == null){ 18 | log(`libart.so GetObsoleteDexCache_ptr is null`); 19 | return; 20 | } 21 | log(`GetObsoleteDexCache_ptr => ${GetObsoleteDexCache_ptr}`); 22 | let GetObsoleteDexCache_func = new NativeFunction(GetObsoleteDexCache_ptr, "pointer", ["pointer"]); 23 | return GetObsoleteDexCache_func; 24 | } 25 | 26 | export function get_DumpString(){ 27 | let DumpString_ptr = Module.findExportByName("libdexfile.so", "_ZNK3art11Instruction10DumpStringEPKNS_7DexFileE"); 28 | if (DumpString_ptr == null){ 29 | log(`libart.so DumpString_ptr is null`); 30 | return; 31 | } 32 | log(`DumpString_ptr => ${DumpString_ptr}`); 33 | let DumpString_func = new NativeFunction(DumpString_ptr, ["pointer", "pointer", "pointer"], ["pointer", "pointer"]); 34 | return DumpString_func; 35 | } 36 | 37 | export function PrettyMethod(art_method_ptr: NativePointer){ 38 | let results: NativePointer[] = PrettyMethod_func(art_method_ptr, 0); 39 | return readStdString(results); 40 | } 41 | 42 | export function PrettyInstruction(inst_ptr: NativePointer, dexfile_ptr: NativePointer){ 43 | let results: NativePointer[] = DumpString_func(inst_ptr, dexfile_ptr); 44 | return readStdString(results); 45 | } 46 | 47 | 48 | // export function readStdString(pointers: NativePointer[]) { 49 | // let str = Memory.alloc(Process.pointerSize * 3); 50 | // str.writePointer(pointers[0]); 51 | // str.add(Process.pointerSize * 1).writePointer(pointers[1]); 52 | // str.add(Process.pointerSize * 2).writePointer(pointers[2]); 53 | // let isTiny = (str.readU8() & 1) === 0; 54 | // if (isTiny) { 55 | // return str.add(1).readUtf8String(); 56 | // } 57 | // return str.add(2 * Process.pointerSize).readPointer().readUtf8String(); 58 | // } 59 | 60 | export function readStdString(pointers: NativePointer[]){ 61 | let str = Memory.alloc(Process.pointerSize * 3); 62 | str.writePointer(pointers[0]); 63 | let isTiny = (str.readU8() & 1) === 0; 64 | if (isTiny) { 65 | str.add(Process.pointerSize * 1).writePointer(pointers[1]); 66 | str.add(Process.pointerSize * 2).writePointer(pointers[2]); 67 | return str.add(1).readUtf8String(); 68 | } 69 | else{ 70 | return pointers[2].readUtf8String(); 71 | } 72 | } 73 | 74 | export let PrettyMethod_func: any = get_PrettyMethod(); 75 | export let DumpString_func: any = get_DumpString(); 76 | export let GetObsoleteDexCache_func: any = get_GetObsoleteDexCache(); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # frida-smali-trace 2 | 3 | 通过frida hook追踪所有smali指令执行情况 4 | 5 | 在Pixel4 Android 11下运行【64位】APP进行测试,版本号`RQ3A.210805.001.A1` 6 | 7 | 效果示意 8 | 9 | ![](./images/Snipaste_2022-05-21_23-30-06.png) 10 | 11 | 实现过程 12 | 13 | - [纯frida实现smali追踪](https://blog.seeflower.dev/archives/84/) 14 | 15 | # 使用 16 | 17 | ## 命令示意 18 | 19 | ```bash 20 | frida -U -n LibChecker -l _agent.js -o trace.log 21 | ``` 22 | 23 | 如果使用frida 15之前的版本,`-n`后面是包名 24 | 25 | ```bash 26 | frida -U -n com.absinthe.libchecker -l _agent.js -o trace.log 27 | ``` 28 | 29 | ## 准备工作 30 | 31 | 安装库,并进行编译测试 32 | 33 | ``` 34 | cd frida_scripts 35 | npm install 36 | npm run watch 37 | ``` 38 | 39 | 如果只是简单使用,那么后面都不用管 40 | 41 | --- 42 | 43 | 在正式使用此脚本之前,需要先找到关键位置,以及几个关键寄存器 44 | 45 | 从手机中提取libart.so 46 | 47 | ```bash 48 | adb pull /apex/com.android.art/lib64/libart.so 49 | ``` 50 | 51 | 用IDA打开libart.so,让IDA反汇编 52 | 53 | 将`index.ts`中的`hook_mterp`改为`false` 54 | 55 | 在`trace_interpreter_enrty`的`ExecuteSwitchImplCpp`日志打印中添加`${offset}` 56 | 57 | ![](./images/Snipaste_2022-05-21_23-50-43.png) 58 | 59 | 开启frida-server,运行命令注入脚本,具体APP请自行选择 60 | 61 | ![](./images/Snipaste_2022-05-21_22-26-07.png) 62 | 63 | 随便滑动、点击下APP,脚本会给出一个偏移位置,比如我这里是`0x169d48` 64 | 65 | IDA中按`G`,`粘贴`地址,`回车`跳转,就会进入到其中一个`ExecuteSwitchImplCpp`实现 66 | 67 | 按`F5`查看伪代码 68 | 69 | ![](./images/Snipaste_2022-05-21_22-28-30.png) 70 | 71 | 往下翻,找到第一个while处,按`TAB`键跳转到汇编窗口 72 | 73 | ![](./images/Snipaste_2022-05-21_22-30-25.png) 74 | 75 | 然后检查特征,关键特征是和`0xFF`相与,以及`BR`指令 76 | 77 | ![](./images/Snipaste_2022-05-21_22-32-29.png) 78 | 79 | 特征确定后,那么记录下此处的偏移,比如我这里是`0x169EB4` 80 | 81 | 和`0xFF`相与的是`opcode`,而`opcode`是从`inst(Instruction)`取的 82 | 83 | 根据这个规则,可以推测图中`X28`是`opcode`,`X26`是`inst` 84 | 85 | 现在回到函数开头,将`a1`命名为`ctx`,其偏移`16`也就是两个指针大小(64位下就是2 * 8 = 16)的取值就是`shadow_frame`,那么对应寄存器在后续也是`shadow_frame`,我这里是`x19` 86 | 87 | ![](./images/Snipaste_2022-05-21_22-36-52.png) 88 | 89 | 现在将`index.ts`中的`trace_interpreter_switch`注释取消掉,把上面分析得到的`0x169EB4`、`x19`、`x26`对应修改 90 | 91 | ```JavaScript 92 | // 参数二是 while 循环中 inst 赋值给 next 的偏移 93 | // 参数三是存 shadow_frame 的寄存器 94 | // 参数四是存 inst(Instruction) 的寄存器 95 | trace_interpreter_switch(libart, 0x169EB4, 'x19', 'x26'); 96 | ``` 97 | 98 | 然后将`hook_switch`和`hook_mterp`改为`false`,编译新的js,进行测试 99 | 100 | 如果没有问题,现在IDA搜索`ExecuteMterpImpl`,跳转到对应函数,按F5查看伪代码,应该长这样 101 | 102 | 第一个参数是`thread` 103 | 104 | ![](./images/Snipaste_2022-05-21_22-48-36.png) 105 | 106 | 按`TAB`查看汇编代码,看看`x0`给哪个寄存器了,我这里是`x22`,记录下来,那么`x22`就是`thread` 107 | 108 | ![](./images/Snipaste_2022-05-21_22-49-13.png) 109 | 110 | 然后直接在汇编窗口往下翻,找一个符号是`mterp_op_`开头的代码(除了`mterp_op_nop`) 111 | 112 | 然后找一个和`0xFF`相与的寄存器,再往几行前看下是哪个寄存器读取来的,比如我这和`0xFF`相与的是`x23`,`x23`是由`x20`读取来的,那么`x20`就是`inst` 113 | 114 | ![](./images/Snipaste_2022-05-21_22-51-33.png) 115 | 116 | 现在将`index.ts`中的`trace_interpreter_mterp_op`注释取消掉,把上面分析得到的`x22`、`x20`对应修改 117 | 118 | ```JavaScript 119 | // 参数二是存 thread 的寄存器 120 | // 参数三是存 inst(Instruction) 的寄存器 121 | trace_interpreter_mterp_op(libart, "x22", "x20"); 122 | ``` 123 | 124 | 编译新的js,进行测试 125 | 126 | 如果顺利,那么现在能够trace 64位APP的smali执行详情了 127 | 128 | 如果检查找后面的参数太麻烦,也可以注释掉`trace_interpreter_switch`和`trace_interpreter_mterp_op` 129 | 130 | 将`hook_switch`和`hook_mterp`改为`true`,这样只会做简单的trace 131 | 132 | --- 133 | 134 | 如果通过静态分析的方法无法确定寄存器,可以自行修改脚本,打印全部寄存器情况 135 | 136 | 比如要检查`switch`在`while`处的`shadow_frame`是哪个寄存器,修改代码如下 137 | 138 | ```JavaScript 139 | // main 140 | let hook_switch = true; 141 | let hook_mterp = false; 142 | trace_interpreter_enrty(libart, hook_switch, hook_mterp); 143 | // trace_interpreter_enrty ExecuteSwitchImplCpp 日志添加一个 ${shadow_frame} 144 | log(`[switch] ${Process.getCurrentThreadId()} ${shadow_frame} ${offset} ${method_name} ${inst_str}`); 145 | // trace_interpreter_switch 146 | log(`[${id}] [switch] ${JSON.stringify(ctx)}`); 147 | ``` 148 | 149 | `trace_interpreter_switch`只打印寄存器信息日志 150 | 151 | ![](./images/Snipaste_2022-05-21_23-03-53.png) 152 | 153 | 这样也能定位出`shadow_frame`存在哪个寄存器,确定后再修改`trace_interpreter_switch`具体参数,还原代码 154 | 155 | ![](./images/Snipaste_2022-05-21_23-06-55.png) 156 | 157 | 类似的,将关键代码修改如下,测试查看`thread`是在哪个寄存器 158 | 159 | ```JavaScript 160 | // main 161 | let hook_switch = false; 162 | let hook_mterp = true; 163 | trace_interpreter_enrty(libart, hook_switch, hook_mterp); 164 | // trace_interpreter_enrty ExecuteMterpImpl 日志添加一个 ${args[0]} 165 | log(`[mterp] ${Process.getCurrentThreadId()} ${args[0]} ${method_name} ${inst_str}`); 166 | // trace_interpreter_mterp_op 只打印一个指令的 避免过多输出 167 | if (symbol.name != "mterp_op_move") continue; 168 | // hook_mterp_op 169 | log(`[${id}] [mterp] ${JSON.stringify(ctx)}`); 170 | ``` 171 | 172 | ![](./images/Snipaste_2022-05-21_23-13-06.png) 173 | 174 | ![](./images/Snipaste_2022-05-21_23-15-33.png) 175 | 176 | --- 177 | 178 | 还有一个问题,需要确定`thread`中`managed_stack`的偏移 179 | 180 | 但是`managed_stack`在`Thread`中的偏移就比较麻烦了,主要是因为`Thread`比较复杂 181 | 182 | 经过一番查阅后,发现在`art::StackVisitor::WalkStack`里面有调用`GetManagedStack()` 183 | 184 | - `void art::StackVisitor::WalkStack<(art::StackVisitor::CountTransitions)0>(bool)` 185 | 186 | ![](./images/Snipaste_2022-05-21_21-24-24.png) 187 | 188 | 并且这个函数的符号还在,于是结合源代码,和IDA对比便能知道`GetManagedStack()`实际的偏移 189 | 190 | 注意这个偏移每个版本、手机的可能都不同,比如我这里是`184`也就是`0xB8` 191 | 192 | ![](./images/Snipaste_2022-05-21_21-25-51.png) 193 | 194 | 确定偏移之后记得修改`get_shadow_frame_ptr_by_thread_ptr`里面计算`managed_stack`的偏移 195 | 196 | --- 197 | 198 | 注意,由于hook指令详细情况的位置里入口可能太近,除了上面的测试过程,其他时候 199 | 200 | - 使用了 trace_interpreter_switch 则 hook_switch 应当为 false 201 | - 使用了 trace_interpreter_mterp_op 则 hook_mterp 应当为 false 202 | 203 | 如果感兴趣详细实现过程,请查看[纯frida实现smali追踪](./纯frida实现smali追踪.md) -------------------------------------------------------------------------------- /frida_scripts/agent/index.ts: -------------------------------------------------------------------------------- 1 | import { PrettyInstruction } from "./helper"; 2 | import { ShadowFrame, SwitchImplContext } from "./util"; 3 | 4 | import { log } from "./logger"; 5 | 6 | function enable_rpc_mode(flag: Boolean){ 7 | rpc_mode = flag; 8 | } 9 | 10 | function get_method_name(shadow_frame: ShadowFrame){ 11 | let method_key = shadow_frame.method.toString(); 12 | let method_name: any = method_name_cache[method_key]; 13 | if (!method_name){ 14 | method_name = shadow_frame.method.PrettyMethod(); 15 | if (method_name){ 16 | method_name_cache[method_key] = method_name; 17 | } 18 | } 19 | return method_name; 20 | } 21 | 22 | function trace_interpreter_enrty(libart: Module, hook_switch: boolean, hook_mterp: boolean){ 23 | libart.enumerateSymbols().forEach(function(symbol: ModuleSymbolDetails){ 24 | let name = symbol.name; 25 | let address = symbol.address; 26 | if(name.includes("ExecuteSwitchImplCpp") && hook_switch){ 27 | log(`start hook ${name}`); 28 | let offset = symbol.address.sub(libart.base); 29 | Interceptor.attach(address, { 30 | onEnter(args) { 31 | let ctx = new SwitchImplContext(args[0]); 32 | let shadow_frame = ctx.shadow_frame; 33 | let method_key = shadow_frame.method.toString(); 34 | let method_name: any = method_name_cache[method_key]; 35 | if (!method_name){ 36 | method_name = shadow_frame.method.PrettyMethod(); 37 | if (method_name){ 38 | method_name_cache[method_key] = method_name; 39 | } 40 | } 41 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 42 | let dex_pc = shadow_frame.GetDexPC(); 43 | // const Instruction* next = Instruction::At(insns + dex_pc); 44 | let inst_ptr = ctx.accessor.insns.add(dex_pc); 45 | let inst_str = PrettyInstruction(inst_ptr, dexfile_ptr); 46 | log(`[switch] ${Process.getCurrentThreadId()} ${method_name} ${inst_str}`); 47 | } 48 | }); 49 | } 50 | if(name.includes("ExecuteMterpImpl") && hook_mterp){ 51 | log(`start hook ${name}`); 52 | Interceptor.attach(address, { 53 | onEnter(args) { 54 | let inst_ptr = args[1]; 55 | let shadow_frame = new ShadowFrame(args[2]); 56 | let method_name = get_method_name(shadow_frame); 57 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 58 | let inst_str = PrettyInstruction(inst_ptr, dexfile_ptr); 59 | log(`[mterp] ${Process.getCurrentThreadId()} ${method_name} ${inst_str}`); 60 | // send({ 61 | // type: "Mterp", 62 | // info: { 63 | // tid: Process.getCurrentThreadId(), 64 | // function_name: function_name, 65 | // inst_string: inst_string 66 | // } 67 | // }) 68 | } 69 | }); 70 | } 71 | }) 72 | } 73 | 74 | function trace_interpreter_switch(libart: Module, offset: number, frame_reg: string, inst_reg: string) { 75 | Interceptor.attach(libart.base.add(offset), { 76 | onEnter(args) { 77 | let id = switch_count; 78 | switch_count += 1; 79 | let ctx = this.context as Arm64CpuContext; 80 | let shadow_frame = new ShadowFrame(ctx[frame_reg as keyof typeof ctx]); 81 | // 通过 thread 获取到当前的 shadow_frame 82 | // let thread_ptr = ctx.sp.add(0x210).sub(0x168).readPointer(); 83 | // let shadow_frame = get_shadow_frame_ptr_by_thread_ptr(thread_ptr); 84 | let method_name = get_method_name(shadow_frame); 85 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 86 | let inst_ptr = ctx[inst_reg as keyof typeof ctx]; 87 | let inst_str = PrettyInstruction(inst_ptr, dexfile_ptr); 88 | log(`[${id}] [switch] ${method_name} ${inst_str}`); 89 | } 90 | }); 91 | } 92 | 93 | function hook_mterp_op(address: NativePointer, offset: NativePointer, thread_reg: string, inst_reg: string) { 94 | Interceptor.attach(address, { 95 | onEnter(args) { 96 | let id = mterp_count; 97 | mterp_count += 1; 98 | let ctx = this.context as Arm64CpuContext; 99 | let thread_ptr = ctx[thread_reg as keyof typeof ctx]; 100 | let shadow_frame = get_shadow_frame_ptr_by_thread_ptr(thread_ptr); 101 | let method_name = get_method_name(shadow_frame); 102 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 103 | let inst_ptr = ctx[inst_reg as keyof typeof ctx]; 104 | let inst_str = PrettyInstruction(inst_ptr, dexfile_ptr); 105 | log(`[${id}] [mterp] ${Process.getCurrentThreadId()} ${method_name} ${inst_str}`); 106 | } 107 | }); 108 | } 109 | 110 | function trace_interpreter_mterp_op(libart: Module, thread_reg: string, inst_reg: string) { 111 | let op_count = 0; 112 | let symbols = libart.enumerateSymbols(); 113 | for (let index = 0; index < symbols.length; index++) { 114 | const symbol = symbols[index]; 115 | // 过滤不符合要求的符号 116 | if (!symbol.name.startsWith("mterp_op_")) continue; 117 | if (symbol.name.endsWith("_helper")) continue; 118 | if (symbol.name.endsWith("_quick")) continue; 119 | if (symbol.name.endsWith("_no_barrier")) continue; 120 | if (symbol.name.includes("unused")) continue; 121 | // nop 对应位置的指令太短 hook 会失败 跳过 122 | if (symbol.name == "mterp_op_nop") continue; 123 | op_count += 1; 124 | let hook_addr = symbol.address; 125 | // return 相关的指令起始就是一个BL frida hook 会失败 需要把hook点向后挪4字节 126 | if (symbol.name.startsWith("mterp_op_return")) { 127 | hook_addr = symbol.address.add(0x4); 128 | } 129 | let offset = hook_addr.sub(libart.base); 130 | log(`[mterp_op] ${symbol.name} ${symbol.address} ${hook_addr} ${offset}`); 131 | // 正式 hook 132 | hook_mterp_op(hook_addr, offset, thread_reg, inst_reg); 133 | } 134 | log(`[mterp_op] op_count ${op_count}`); 135 | } 136 | 137 | function find_managed_stack_offset(libart: Module) { 138 | // 特征 139 | // 会将某个寄存器偏移一个 pointer 取值到另一个寄存器 140 | // 被赋值的寄存器会通过 add 指令加上一个偏移得到 managed_stack 141 | // 这个地方的偏移就是需要的 142 | let managed_stack_offset: number = -1; 143 | let thread_reg: any = null; 144 | let symbols = libart.enumerateSymbols(); 145 | for (let index = 0; index < symbols.length; index++) { 146 | let symbol = symbols[index]; 147 | // void art::StackVisitor::WalkStack<(art::StackVisitor::CountTransitions)0>(bool) 148 | if (symbol.name != "_ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb") continue; 149 | let address = symbol.address; 150 | for (let index = 0; index < 30; index++) { 151 | if (managed_stack_offset != -1) break; 152 | let ins = Instruction.parse(address); 153 | if (ins.mnemonic == "b") break; 154 | let ins_str = ins.toString(); 155 | // log(`ins_str => ${ins_str}`); 156 | if (thread_reg == null){ 157 | let thread_reg_re = new RegExp(`ldr (\\w\\d+), \\[\\w\\d+, #${Process.pointerSize}\\]`, "g");; 158 | // 32 ldr r0, [r4, #4] 159 | // 64 ldr x8, [x0, #8] 160 | let results = thread_reg_re.exec(ins_str); 161 | if (results != null) { 162 | thread_reg = results[1]; 163 | log(`[WalkStack] find thread_reg => ${thread_reg}`); 164 | } 165 | } else { 166 | let managed_stack_offset_re = new RegExp(`add.+?, ${thread_reg}, #(.+)`, "g"); 167 | // 32 add.w sb, r0, #0xac 168 | // 64 add x23, x8, #0xb8 169 | let results = managed_stack_offset_re.exec(ins_str); 170 | if (results != null){ 171 | managed_stack_offset = Number(results[1]); 172 | log(`[WalkStack] find managed_stack_offset => ${managed_stack_offset}`); 173 | } 174 | } 175 | address = ins.next; 176 | } 177 | } 178 | return managed_stack_offset; 179 | } 180 | 181 | function get_shadow_frame_ptr_by_thread_ptr(thread_ptr: NativePointer) : ShadowFrame { 182 | // 0xB8 是 managed_stack 在 Thread 中的偏移 需要结合IDA分析 183 | // 如何定位这个偏移 184 | // void art::StackVisitor::WalkStack<(art::StackVisitor::CountTransitions)0>(bool) 185 | // _ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb 186 | // 找到这个函数 然后反编译 在开头找到一个 与 0xFFFFFFFFFFFFFFFELL 相与的变量 187 | // 然后回溯 可以发现它时由传入参数通过偏移取指针再偏移 这个就是 managed_stack 的偏移 188 | // http://aospxref.com/android-11.0.0_r21/xref/art/runtime/stack.cc#835 189 | // let managed_stack = thread_ptr.readPointer().add(0xB8); 190 | let managed_stack = thread_ptr.add(0xB8); 191 | // 0x10 是 top_shadow_frame_ 在 ManagedStack 中的偏移 结合源码或者IDA可以分析出来 192 | let cur_frame_ptr = managed_stack.add(0x10).readPointer(); 193 | return new ShadowFrame(cur_frame_ptr); 194 | } 195 | 196 | function main(){ 197 | let libart = Process.findModuleByName("libart.so"); 198 | if (libart == null) { 199 | log(`libart is null`); 200 | return; 201 | } 202 | 203 | let hook_switch = true; 204 | let hook_mterp = true; 205 | // 仅对 ExecuteSwitchImplCpp 和 ExecuteMterpImpl 调用时 hook 可以得到一些基本调用轨迹 且对APP运行影响很小 206 | trace_interpreter_enrty(libart, hook_switch, hook_mterp); 207 | 208 | // 对 ExecuteSwitchImplCpp 实际进行 opcode 判断跳转的位置进行 hook 这样可以得到一个函数内具体执行了什么 209 | // 通过静态分析可以知道 210 | // - x19 是 shadow_frame 211 | // - x26 是 inst 212 | // 调用了 trace_interpreter_switch 记得将 hook_switch 设为 false 避免重复 213 | // trace_interpreter_switch(libart, 0x169EB4, 'x19', 'x26'); 214 | 215 | // 进入 ExecuteMterpImpl 后的逻辑就是 216 | // - 计算opcode 跳转实际处理位置 执行处理 217 | // - 再立刻计算下一个opcode 马上跳转实际处理位置 218 | // - 直到执行结束 219 | // 对每个 opcode 实际处理的位置进行 hook 220 | // 通过静态分析和实际测试可以知道 221 | // - x22 是 self 也就是 thread 222 | // - x20 是 inst 223 | // trace_interpreter_mterp_op(libart, "x22", "x20"); 224 | 225 | } 226 | 227 | export let rpc_mode: Boolean = false; 228 | 229 | let method_name_cache: {[key: string]: string} = {}; 230 | let switch_count = 0; 231 | let mterp_count = 0; 232 | 233 | setImmediate(main); 234 | 235 | rpc.exports = { 236 | go: main, 237 | enablerpcmode: enable_rpc_mode, 238 | } 239 | 240 | // frida -U -n LibChecker -l _agent.js -o trace.log 241 | // frida -U -n com.absinthe.libchecker -l _agent.js -o trace.log 242 | // frida -U -f com.absinthe.libchecker -l _agent.js -o trace.log --no-pause -------------------------------------------------------------------------------- /纯frida实现smali追踪.md: -------------------------------------------------------------------------------- 1 | ## 前言 2 | 3 | **环境** 4 | 5 | - Pixel 4 6 | - Android 11 7 | 8 | 网上trace smali的文章有不少,大多都需要改源码编译ROM,比较麻烦,而且主要是在较低版本实现的 9 | 10 | 于是想写个能够直接frida一步到位的脚本,正好也学习了一些知识,在断断续续弄了一段时间后,终于达到一个相对满意的程度 11 | 12 | --- 13 | 14 | 本文是结合脱壳王课程中的【使用frida调试ART下的解释器】详细实践 15 | 16 | 目标是以尽可能通用的手段实现对smali执行记录,无需修改ROM,也不用强制APP运行在switch模式下 17 | 18 | --- 19 | 20 | ![](./images/Snipaste_2022-05-21_21-59-35.png) 21 | 22 | ## 实现过程 23 | 24 | ### 准备工作 25 | 26 | 提取手机中的`libart.so`,这里是用64位的,用IDA打开分析 27 | 28 | ```bash 29 | adb pull /apex/com.android.art/lib64/libart.so 30 | ``` 31 | 32 | 关于smali执行入口这些就不详细分析了,具体请查看下面的文章: 33 | 34 | - https://bbs.pediy.com/thread-263210.htm 35 | 36 | 也可检索下面几个关键词查更多的资料: 37 | 38 | - `TraceExecution` 39 | - `ExecuteSwitchImplCpp` 40 | - `ExecuteSwitchImpl` 41 | - `ExecuteMterpImpl` 42 | 43 | ### 如何打印函数和指令 44 | 45 | 分析`TraceExecution`的代码可以知道,要打印smali指令详细内容,其实只要这两句即可 46 | 47 | - `shadow_frame.GetMethod()->PrettyMethod()` 48 | - `inst->DumpString(shadow_frame.GetMethod()->GetDexFile())` 49 | 50 | ```c++ 51 | static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst, 52 | const uint32_t dex_pc) 53 | REQUIRES_SHARED(Locks::mutator_lock_) { 54 | if (kTraceExecutionEnabled) { 55 | #define TRACE_LOG std::cerr 56 | std::ostringstream oss; 57 | oss << shadow_frame.GetMethod()->PrettyMethod() 58 | << android::base::StringPrintf("\n0x%x: ", dex_pc) 59 | << inst->DumpString(shadow_frame.GetMethod()->GetDexFile()) << "\n"; 60 | for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) { 61 | uint32_t raw_value = shadow_frame.GetVReg(i); 62 | ObjPtr ref_value = shadow_frame.GetVRegReference(i); 63 | oss << android::base::StringPrintf(" vreg%u=0x%08X", i, raw_value); 64 | if (ref_value != nullptr) { 65 | if (ref_value->GetClass()->IsStringClass() && 66 | !ref_value->AsString()->IsValueNull()) { 67 | oss << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\""; 68 | } else { 69 | oss << "/" << ref_value->PrettyTypeOf(); 70 | } 71 | } 72 | } 73 | TRACE_LOG << oss.str() << "\n"; 74 | #undef TRACE_LOG 75 | } 76 | } 77 | ``` 78 | 79 | 在IDA中搜索`PrettyMethod`,导出符号是`_ZN3art9ArtMethod12PrettyMethodEPS0_b`,IDA显示是三个参数,但只需要传两个即可 80 | 81 | (这个应该是反编译的一种约定? 82 | 83 | 第二个参数是bool类型,用来决定是否输出参数部分,这里建议false 84 | 85 | ```c 86 | __int64 __fastcall art::ArtMethod::PrettyMethod(art::ArtMethod *__hidden this, art::ArtMethod *, bool) 87 | ``` 88 | 89 | ![](./images/Snipaste_2022-05-21_18-25-27.png) 90 | 91 | 可以看到里面又调用了一个`PrettyMethod`,符号是`_ZN3art9ArtMethod12PrettyMethodEb` 92 | 93 | - http://aospxref.com/android-11.0.0_r21/xref/art/runtime/art_method.cc#813 94 | 95 | 为了减少判断,这里选后面这个,代码如下: 96 | 97 | ```JavaScript 98 | function get_PrettyMethod(){ 99 | let PrettyMethod_ptr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod12PrettyMethodEb"); 100 | if (PrettyMethod_ptr == null){ 101 | log(`libart.so PrettyMethod_ptr is null`); 102 | return; 103 | } 104 | log(`PrettyMethod_ptr => ${PrettyMethod_ptr}`); 105 | let PrettyMethod_func = new NativeFunction(PrettyMethod_ptr, ["pointer", "pointer", "pointer"], ["pointer", "bool"]); 106 | return PrettyMethod_func; 107 | } 108 | ``` 109 | 110 | 返回结果是`std::string`,查找资料可知不管是大端还是小端,都是三个指针构成,所以返回类型写成`["pointer", "pointer", "pointer"]` 111 | 112 | 调用的时候第二个参数类型是bool,但实际应该传入一个数字,`1`为`true`,`0`为`false` 113 | 114 | frida如何读取`std::string`的具体字符串? 115 | 116 | 综合各路信息,脚本一般如下: 117 | 118 | ```JavaScript 119 | function readStdString(pointers: NativePointer[]) { 120 | let str = Memory.alloc(Process.pointerSize * 3); 121 | str.writePointer(pointers[0]); 122 | str.add(Process.pointerSize * 1).writePointer(pointers[1]); 123 | str.add(Process.pointerSize * 2).writePointer(pointers[2]); 124 | let isTiny = (str.readU8() & 1) === 0; 125 | if (isTiny) { 126 | return str.add(1).readUtf8String(); 127 | } 128 | return str.add(2 * Process.pointerSize).readPointer().readUtf8String(); 129 | } 130 | ``` 131 | 132 | 为了减少写数据操作,改进如下: 133 | 134 | ```JavaScript 135 | function readStdString(pointers: NativePointer[]){ 136 | let str = Memory.alloc(Process.pointerSize * 3); 137 | str.writePointer(pointers[0]); 138 | let isTiny = (str.readU8() & 1) === 0; 139 | if (isTiny) { 140 | str.add(Process.pointerSize * 1).writePointer(pointers[1]); 141 | str.add(Process.pointerSize * 2).writePointer(pointers[2]); 142 | return str.add(1).readUtf8String(); 143 | } 144 | else{ 145 | return pointers[2].readUtf8String(); 146 | } 147 | } 148 | ``` 149 | 150 | 于是打印函数签名如下: 151 | 152 | ```JavaScript 153 | function PrettyMethod(art_method_ptr: NativePointer){ 154 | let results: NativePointer[] = PrettyMethod_func(art_method_ptr, 0); 155 | return readStdString(results); 156 | } 157 | ``` 158 | 159 | 接下来是打印指令信息 160 | 161 | ```c++ 162 | inst->DumpString(shadow_frame.GetMethod()->GetDexFile()) 163 | ``` 164 | 165 | 根据代码可知,如果要调用系统函数打印,那么需要两个参数: 166 | 167 | - inst 即 Instruction 168 | - shadow_frame 即 ShadowFrame 169 | 170 | `DumpString`函数符号`_ZNK3art11Instruction10DumpStringEPKNS_7DexFileE`,位于`libdexfile.so` 171 | 172 | Q: 假设拿到了`shadow_frame`,那`shadow_frame.GetMethod()`该如何写呢? 173 | 174 | A: C/C++中这种访问私有成员的操作,在编译后会变成通过偏移取值,所以要分析对应的偏移是多少。 175 | 176 | - http://aosp.opersys.com/xref/android-11.0.0_r47/xref/art/runtime/interpreter/shadow_frame.h#426 177 | 178 | 具体C/C++中内存布局是怎样的,还请自行了解(我也不敢说懂...) 179 | 180 | 结合实际情况与IDA反汇编结果分析,得到64位下,`ShadowFrame`的大小占用如下(部分): 181 | 182 | ```c++ 183 | pointer ShadowFrame* link_; 184 | pointer ArtMethod* method_; 185 | pointer JValue* result_register_; 186 | pointer const uint16_t* dex_pc_ptr_; 187 | pointer const uint16_t* dex_instructions_; 188 | pointer LockCountData lock_count_data_; 189 | 4 const uint32_t number_of_vregs_; 190 | 4 uint32_t dex_pc_; 191 | 2 int16_t cached_hotness_countdown_; 192 | 2 int16_t hotness_countdown_; 193 | ``` 194 | 195 | - `pointer`指的是一个指针大小,在64位上那么就是8字节 196 | - `uint16_t*` 指的是该指针对应位置的对象,是`uint16_t`类型的,千万不要理解成指针是`uint16_t`大小;指针的大小由系统架构决定 197 | 198 | 那么`shadow_frame.GetMethod()`用frida写就是下面这样 199 | 200 | ```JavaScript 201 | let art_method_ptr = shadow_frame_ptr.add(Process.pointerSize).readPointer(); 202 | ``` 203 | 204 | 结合IDA反汇编结果分析,以及前人经验,`ArtMethod`的大小占用如下(部分): 205 | 206 | ```c++ 207 | 4 GcRoot declaring_class_; 208 | 4 std::atomic access_flags_; 209 | 4 uint32_t dex_code_item_offset_; 210 | 4 uint32_t dex_method_index_; 211 | 2 uint16_t method_index_; 212 | ``` 213 | 214 | 那么`GetDexFile()`具体怎么取的呢?结合源代码与IDA反汇编结果共同分析,计算如下 215 | 216 | ![](./images/Snipaste_2022-05-21_19-49-58.png) 217 | 218 | ```JavaScript 219 | GetDexFile(): NativePointer { 220 | let access_flags = this.pointer.add(0x4).readU32(); 221 | // IsObsolete() => (GetAccessFlags() & kAccObsoleteMethod) != 0; 222 | if ((access_flags & 0x40000) != 0){ 223 | log(`flag => ${access_flags}`); 224 | return this.GetObsoleteDexCache(); 225 | } 226 | else{ 227 | let declaring_class_ptr = ptr(this.pointer.readU32()); 228 | let dex_cache_ptr = ptr(declaring_class_ptr.add(0x10).readU32()); 229 | let dex_file_ptr = dex_cache_ptr.add(0x10).readPointer(); 230 | return dex_file_ptr; 231 | } 232 | } 233 | ``` 234 | 235 | 其中`GetObsoleteDexCache`好像还需要一个参数?不过实际使用中没有出现过进入需要`GetObsoleteDexCache()`的分支,暂时不管了... 236 | 237 | ```JavaScript 238 | // __int64 __fastcall art::ArtMethod::GetObsoleteDexCache(art::ArtMethod *__hidden this) 239 | function get_GetObsoleteDexCache(){ 240 | let GetObsoleteDexCache_ptr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod19GetObsoleteDexCacheEv"); 241 | if (GetObsoleteDexCache_ptr == null){ 242 | log(`libart.so GetObsoleteDexCache_ptr is null`); 243 | return; 244 | } 245 | log(`GetObsoleteDexCache_ptr => ${GetObsoleteDexCache_ptr}`); 246 | let GetObsoleteDexCache_func = new NativeFunction(GetObsoleteDexCache_ptr, "pointer", ["pointer"]); 247 | return GetObsoleteDexCache_func; 248 | } 249 | ``` 250 | 251 | 看到上面的代码可能会有疑问,`ArtMethod`里面`declaring_class_`的类型不是`GcRoot`吗 252 | 253 | 怎么是4字节?呜呜呜我对C++也不熟,但根据IDA反汇编的结果来看确实是4字节,而且在网上查到的其他结构信息也是uint32_t 254 | 255 | 根据分析,`GetDexFile()`的调用过程如下: 256 | 257 | - 先获取`ArtMethod`的`declaring_class_`,类型是`Class` 258 | - http://aosp.opersys.com/xref/android-11.0.0_r47/xref/art/runtime/mirror/class.h#82 259 | - 再取`dex_cache_`,类型是`DexCache` 260 | - http://aosp.opersys.com/xref/android-11.0.0_r47/xref/art/runtime/mirror/dex_cache.h#133 261 | - 最后取`dex_file_` 262 | 263 | 相关的类成员结构如下(部分): 264 | 265 | ```c++ 266 | // art/runtime/mirror/class.h 267 | HeapReference class_loader_; 268 | HeapReference component_type_; 269 | HeapReference dex_cache_; 270 | HeapReference ext_data_; 271 | ``` 272 | 273 | ```c++ 274 | // runtime/mirror/dex_cache.h 275 | HeapReference class_loader_; 276 | HeapReference location_; 277 | uint64_t dex_file_; 278 | uint64_t preresolved_strings_; 279 | ``` 280 | 281 | 好了,现在`shadow_frame.GetMethod()->GetDexFile()`总算是完成了 282 | 283 | `DumpString`的第一个参数就是`Instruction`,也就是还需要拿到`inst` 284 | 285 | 根据`ExecuteSwitchImplCpp`的代码可以知道,需要下面这几步 286 | 287 | ```c++ 288 | uint32_t dex_pc = shadow_frame.GetDexPC(); 289 | const uint16_t* const insns = accessor.Insns(); 290 | const Instruction* next = Instruction::At(insns + dex_pc); 291 | ``` 292 | 293 | ![](./images/Snipaste_2022-05-21_20-17-12.png) 294 | 295 | `GetDexPC()`代码如下: 296 | 297 | ```c++ 298 | uint32_t GetDexPC() const { 299 | return (dex_pc_ptr_ == nullptr) ? dex_pc_ : dex_pc_ptr_ - dex_instructions_; 300 | } 301 | ``` 302 | 303 | 有了前面的经验,很快就能写出下面的frida代码,其中`this.pointer`是`ShadowFrame`指针 304 | 305 | ```JavaScript 306 | GetDexPC(): number { 307 | let dex_pc_ptr_ = this.pointer.add(Process.pointerSize * 3).readPointer(); 308 | if (!dex_pc_ptr_.equals(ptr(0x0))){ 309 | let dex_instructions_ = this.pointer.add(Process.pointerSize * 4).readPointer(); 310 | return Number(dex_pc_ptr_.sub(dex_instructions_).toString()); 311 | } 312 | else{ 313 | return this.pointer.add(Process.pointerSize * 6 + 4).readU32(); 314 | } 315 | } 316 | ``` 317 | 318 | ![](./images/Snipaste_2022-05-21_20-21-20.png) 319 | 320 | 其实对于刚进入`ExecuteSwitchImplCpp`时,`dex_pc`一定是`0`(应该没错) 321 | 322 | 所以`Instruction::At(insns + dex_pc)`最终其实就是取`insns`指针,不过为了通用一些,还是实现具体点 323 | 324 | 而`accessor.Insns()`也是类似的,先从`SwitchImplContext`取`accessor`,再取`insns_`偏移即可 325 | 326 | 现在再传入调用`DumpString`即可打印smali指令 327 | 328 | ### 在何处打印指令 329 | 330 | 根据已有信息可知,解释模式下必定经过`ExecuteSwitchImplCpp`,汇编模式下必定经过`ExecuteMterpImpl` 331 | 332 | `ExecuteSwitchImplCpp`是一个函数模板,其调用来自于`ExecuteSwitchImpl` 333 | 334 | ```c++ 335 | template 336 | ALWAYS_INLINE JValue ExecuteSwitchImpl(Thread* self, const CodeItemDataAccessor& accessor, 337 | ShadowFrame& shadow_frame, JValue result_register, 338 | bool interpret_one_instruction) 339 | REQUIRES_SHARED(Locks::mutator_lock_) { 340 | SwitchImplContext ctx { 341 | .self = self, 342 | .accessor = accessor, 343 | .shadow_frame = shadow_frame, 344 | .result_register = result_register, 345 | .interpret_one_instruction = interpret_one_instruction, 346 | .result = JValue(), 347 | }; 348 | void* impl = reinterpret_cast(&ExecuteSwitchImplCpp); 349 | const uint16_t* dex_pc = ctx.accessor.Insns(); 350 | ExecuteSwitchImplAsm(&ctx, impl, dex_pc); 351 | return ctx.result; 352 | } 353 | ``` 354 | 355 | - http://aosp.opersys.com/xref/android-11.0.0_r47/xref/art/runtime/arch/arm64/quick_entrypoints_arm64.S 356 | 357 | 根据源代码可知`ExecuteSwitchImplCpp`参数是`SwitchImplContext` 358 | 359 | - http://aosp.opersys.com/xref/android-11.0.0_r47/xref/art/runtime/interpreter/interpreter_switch_impl-inl.h#1938 360 | 361 | ![](./images/Snipaste_2022-05-21_19-16-15.png) 362 | 363 | 于是可以遍历`libart.so`的所有符号,找到带有`ExecuteSwitchImplCpp`关键字的符号,进行hook 364 | 365 | 然后解析`SwitchImplContext`参数,拿到`shadow_frame`和`inst`即可 366 | 367 | `shadow_frame`可以直接通过`SwitchImplContext`拿到 368 | 369 | 而汇编模式的入口函数`ExecuteMterpImpl`则直接有`inst`和`shadow_frame`,那更加简单了 370 | 371 | 那么hook代码如下: 372 | 373 | ```JavaScript 374 | function trace_interpreter_enrty(libart: Module, hook_switch: boolean, hook_mterp: boolean){ 375 | libart.enumerateSymbols().forEach(function(symbol: ModuleSymbolDetails){ 376 | let name = symbol.name; 377 | let address = symbol.address; 378 | if(name.includes("ExecuteSwitchImplCpp") && hook_switch){ 379 | log(`start hook ${name}`); 380 | Interceptor.attach(address, { 381 | onEnter(args) { 382 | let ctx = new SwitchImplContext(args[0]); 383 | let shadow_frame = ctx.shadow_frame; 384 | let method_key = shadow_frame.method.toString(); 385 | let method_name: any = method_name_cache[method_key]; 386 | if (!method_name){ 387 | method_name = shadow_frame.method.PrettyMethod(); 388 | if (method_name){ 389 | method_name_cache[method_key] = method_name; 390 | } 391 | } 392 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 393 | let dex_pc = shadow_frame.GetDexPC(); 394 | // const Instruction* next = Instruction::At(insns + dex_pc); 395 | let inst_ptr = ctx.accessor.insns.add(dex_pc); 396 | let inst_str = PrettyInstruction(inst_ptr, dexfile_ptr); 397 | log(`[switch] ${Process.getCurrentThreadId()} ${method_name} ${inst_str}`); 398 | } 399 | }); 400 | } 401 | if(name.includes("ExecuteMterpImpl") && hook_mterp){ 402 | log(`start hook ${name}`); 403 | Interceptor.attach(address, { 404 | onEnter(args) { 405 | let inst_ptr = args[1]; 406 | let shadow_frame = new ShadowFrame(args[2]); 407 | let method_name = get_method_name(shadow_frame); 408 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 409 | let inst_str = PrettyInstruction(inst_ptr, dexfile_ptr); 410 | log(`[mterp] ${Process.getCurrentThreadId()} thread ${args[0]} ${method_name} ${inst_str}`); 411 | } 412 | }); 413 | } 414 | }) 415 | } 416 | ``` 417 | 418 | 至此已经初步实现了smali指令trace了,为设么说是【初步】呢? 419 | 420 | 因为这两个函数仅仅是入口,也就是说进入一个函数后,函数内具体要执行的指令这个位置是打印不出来的 421 | 422 | 所以到这里只能追踪一部分代码的执行情况,不过只看执行流程的话已经差不多够了 423 | 424 | 要具体到每一条指令做了什么,那需要找到具体位置,比如switch模式下会判断每条指令的opcode,然后跳转到具体分支执行 425 | 426 | 而mterp模式下,进入`ExecuteMterpImpl`后,会计算出要执行指令的opcode,然后通过`BR`指令直接跳转执行 427 | 428 | 执行后立刻计算下一个opcode,再跳转对应的汇编位置,直到全部指令执行完成 429 | 430 | ### 详细打印switch模式下执行的指令 431 | 432 | 结合源代码,很快啊,就分析出来最佳hook位置是这刚进入while循环的地方 433 | 434 | ![](./images/Snipaste_2022-05-21_20-38-11.png) 435 | 436 | ![](./images/Snipaste_2022-05-21_20-39-20.png) 437 | 438 | ![](./images/Snipaste_2022-05-21_20-41-05.png) 439 | 440 | 但是新的问题又出现了,怎么拿到`shadow_frame`和`inst`呢? 441 | 442 | `inst`好说,因为while这里赋值的就是`inst`,直接取对应寄存器即可 443 | 444 | `shadow_frame`就不好说了,我决定将这个位置所有的寄存器都打印下,然后把前面hook的`ExecuteSwitchImplCpp`拿到的`shadow_frame`打印出来,找找规律 445 | 446 | 毕竟是挨着的,理论上应该是相同的(应该没错) 447 | 448 | 反复确认,这个寄存器就是`x19`,然后看了下汇编,原来早函数开始的位置就给x19了,后面也没有改变过 449 | 450 | 如果是新的`shadow_frame`,那应该新调用`ExecuteSwitchImplCpp`? 451 | 452 | ![](./images/Snipaste_2022-05-21_20-46-41.png) 453 | 454 | 对了,`ExecuteSwitchImplCpp`是函数模板,编译的时候`do_access_check`和`transaction_active`都是确定值 455 | 456 | - `template` 457 | 458 | 所以实际上解释模式只会调用四个中的一个,打印一下调用的哪个,然后只需要找到这一个的switch判断位置即可 459 | 460 | 于是hook代码编写如下: 461 | 462 | ```JavaScript 463 | // trace_interpreter_switch(libart, 0x169EB4, 'x19', 'x26'); 464 | function trace_interpreter_switch(libart: Module, offset: number, frame_reg: string, inst_reg: string) { 465 | Interceptor.attach(libart.base.add(offset), { 466 | onEnter(args) { 467 | let id = switch_count; 468 | switch_count += 1; 469 | let ctx = this.context as Arm64CpuContext; 470 | let shadow_frame = new ShadowFrame(ctx[frame_reg as keyof typeof ctx]); 471 | // 通过 thread 获取到当前的 shadow_frame 472 | // let thread_ptr = ctx.sp.add(0x210).sub(0x168).readPointer(); 473 | // let shadow_frame = get_shadow_frame_ptr_by_thread_ptr(thread_ptr); 474 | let method_name = get_method_name(shadow_frame); 475 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 476 | let inst_ptr = ctx[inst_reg as keyof typeof ctx]; 477 | let inst_str = PrettyInstruction(inst_ptr, dexfile_ptr); 478 | log(`[${id}] [switch] ${method_name} ${inst_str}`); 479 | } 480 | }); 481 | } 482 | ``` 483 | 484 | 这里`get_shadow_frame_ptr_by_thread_ptr`是什么? 485 | 486 | 这是因为在`mterp`模式下确实拿不到`shadow_frame`,后来翻阅源代码后,发现可以通过`thread`拿到当前的`shadow_frame` 487 | 488 | 具体下一个小节说明,这里除了通过测试来确定哪个寄存器是`shadow_frame`,还可以结合反汇编代码分析 489 | 490 | 可以知道`thread`被放到栈帧中了,于是也可以通过`sp`拿到`thread`指针,再去获取`shadow_frame` 491 | 492 | ### 详细打印mterp模式下执行的指令 493 | 494 | 先看`ExecuteMterpImpl`,啊这...显然它会跳转到其他位置进行具体的指令执行 495 | 496 | ![](./images/Snipaste_2022-05-21_20-55-12.png) 497 | 498 | 而寄存器`x20`显然就是`inst`,这里的`shadow_frame`根据汇编也能找到具体寄存器 499 | 500 | 但是这里并没有执行指令,本质上和开始做`ExecuteMterpImpl`的hook效果是一样的 501 | 502 | 要具体追踪执行了什么指令,那么得到每个opcode的处理位置去hook 503 | 504 | 怎么确定位置呢,冰冰老师的方案是根据指令特征,在内存中直接搜索对应的指令,然后去hook对应的位置 505 | 506 | 每一次计算opcode以及跳转都是下面的指令 507 | 508 | ```bash 509 | .text:000000000012A0D4 97 02 40 79 LDRH W23, [X20] 510 | .text:000000000012A0D8 F0 1E 40 92 AND X16, X23, #0xFF 511 | .text:000000000012A0DC 10 1F 10 8B ADD X16, X24, X16,LSL#7 512 | .text:000000000012A0E0 00 02 1F D6 BR X16 513 | ``` 514 | 515 | 不过我发现mterp相关的opcode处理位置的符号是被保留了的(高版本,Android 10和Android 11上是这样的) 516 | 517 | ![](./images/Snipaste_2022-05-21_21-02-06.png) 518 | 519 | 很快啊,就能写出下面的代码,直接找到符号,然后执行hook,经过实践有几个注意点: 520 | 521 | - `_helper`和`_quick`结尾的实际上是某些opcode处理的分支,不需要hook 522 | - `mterp_op_return_void_no_barrier`也不是`return`指令的具体处理位置,只是处理分支,跳过hook 523 | - `unused`没有任何处理,跳过hook(预留的指令) 524 | - `mterp_op_nop`的指令很短,使用frida hook不了,会出现异常,需要跳过hook 525 | 526 | ```bash 527 | .text:000000000012A100 mterp_op_nop ; DATA XREF: .got:mterp_op_nop_ptr↓o 528 | .text:000000000012A100 LDRH W23, [X20,#2]! 529 | .text:000000000012A104 AND X16, X23, #0xFF 530 | .text:000000000012A108 ADD X16, X24, X16,LSL#7 531 | .text:000000000012A10C BR X16 532 | .text:000000000012A10C ; End of function mterp_op_nop 533 | ``` 534 | 535 | - `mterp_op_return`起始的处理函数,它们的第一个指令是BL,经过验证frida hook会出错,需要把hook位置加4 536 | 537 | ![](./images/Snipaste_2022-05-21_21-12-09.png) 538 | 539 | 那么可以编写hook代码如下: 540 | 541 | ```JavaScript 542 | function trace_interpreter_mterp_op(libart: Module, thread_reg: string, inst_reg: string) { 543 | let op_count = 0; 544 | let symbols = libart.enumerateSymbols(); 545 | for (let index = 0; index < symbols.length; index++) { 546 | const symbol = symbols[index]; 547 | // 过滤不符合要求的符号 548 | if (!symbol.name.startsWith("mterp_op_")) continue; 549 | if (symbol.name.endsWith("_helper")) continue; 550 | if (symbol.name.endsWith("_quick")) continue; 551 | if (symbol.name.endsWith("_no_barrier")) continue; 552 | if (symbol.name.includes("unused")) continue; 553 | // nop 对应位置的指令太短 hook 会失败 跳过 554 | if (symbol.name == "mterp_op_nop") continue; 555 | op_count += 1; 556 | let hook_addr = symbol.address; 557 | // return 相关的指令起始就是一个BL frida hook 会失败 需要把hook点向后挪4字节 558 | if (symbol.name.startsWith("mterp_op_return")) { 559 | hook_addr = symbol.address.add(0x4); 560 | } 561 | let offset = hook_addr.sub(libart.base); 562 | log(`[mterp_op] ${symbol.name} ${symbol.address} ${hook_addr} ${offset}`); 563 | // 正式 hook 564 | hook_mterp_op(hook_addr, offset, thread_reg, inst_reg); 565 | } 566 | log(`[mterp_op] op_count ${op_count}`); 567 | } 568 | ``` 569 | 570 | 在每个opcode对应的hook位置,我们都能确定`inst`是哪个寄存器(并且是固定的),因为每次都需要取下一条opcode,所以必须用到`inst` 571 | 572 | 再次出现前面的问题,怎么拿到`shadow_frame`,这回我尝试对比每个寄存器,发现并不存在一个寄存器始终存放`shadow_frame` 573 | 574 | 并且根据汇编代码也没有发现`shadow_frame`被放入栈帧中 575 | 576 | 好在通过阅读源代码,发现一个名为`GetCurrentShadowFrame`的函数 577 | 578 | 取的是类`StackVisitor`的`cur_shadow_frame_`成员 579 | 580 | 经过进一步分析,发现可以通过下面两步得到`cur_shadow_frame_` 581 | 582 | ```c++ 583 | const ManagedStack* current_fragment = thread_->GetManagedStack(); 584 | ShadowFrame* cur_shadow_frame_ = current_fragment->GetTopShadowFrame(); 585 | ``` 586 | 587 | `cur_shadow_frame_`的偏移比较好计算,就是偏移两个指针大小就行,如下 588 | 589 | ```c++ 590 | // runtime/stack.h StackVisitor 类 591 | Thread* const thread_; 592 | const StackWalkKind walk_kind_; 593 | ShadowFrame* cur_shadow_frame_; 594 | ArtMethod** cur_quick_frame_; 595 | uintptr_t cur_quick_frame_pc_; 596 | ``` 597 | 598 | 但是`managed_stack`在`Thread`中的偏移就比较麻烦了,主要是因为`Thread`比较复杂 599 | 600 | 经过一番查阅后,发现在`art::StackVisitor::WalkStack`里面有调用`GetManagedStack()` 601 | 602 | - `void art::StackVisitor::WalkStack<(art::StackVisitor::CountTransitions)0>(bool)` 603 | 604 | ![](./images/Snipaste_2022-05-21_21-24-24.png) 605 | 606 | 并且这个函数的符号还在,于是结合源代码,和IDA对比便能知道`GetManagedStack()`实际的偏移 607 | 608 | 注意这个偏移每个版本、手机的可能都不同,比如我这里是`184`也就是`0xB8` 609 | 610 | ![](./images/Snipaste_2022-05-21_21-25-51.png) 611 | 612 | 于是编写hook代码如下,用于通过`thread`计算`shadow_frame` 613 | 614 | ```JavaScript 615 | function get_shadow_frame_ptr_by_thread_ptr(thread_ptr: NativePointer) : ShadowFrame { 616 | // 0xB8 是 managed_stack 在 Thread 中的偏移 需要结合IDA分析 617 | // 如何定位这个偏移 618 | // void art::StackVisitor::WalkStack<(art::StackVisitor::CountTransitions)0>(bool) 619 | // _ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb 620 | // 找到这个函数 然后反编译 在开头找到一个 与 0xFFFFFFFFFFFFFFFELL 相与的变量 621 | // 然后回溯 可以发现它时由传入参数通过偏移取指针再偏移 这个就是 managed_stack 的偏移 622 | // http://aospxref.com/android-11.0.0_r21/xref/art/runtime/stack.cc#835 623 | let managed_stack = thread_ptr.add(0xB8); 624 | // 0x10 是 top_shadow_frame_ 在 ManagedStack 中的偏移 结合源码或者IDA可以分析出来 625 | let cur_frame_ptr = managed_stack.add(0x10).readPointer(); 626 | return new ShadowFrame(cur_frame_ptr); 627 | } 628 | ``` 629 | 630 | Q: 那么thread就一定能从寄存器获取到吗? 631 | 632 | A: 经过验证,确实有一个寄存器在任何opcode操作位置执行的时候,其值为`thread` 633 | 634 | 我这里确定这个寄存器是`x22`,于是编写具体的hook代码如下 635 | 636 | ```JavaScript 637 | function hook_mterp_op(address: NativePointer, offset: NativePointer, thread_reg: string, inst_reg: string) { 638 | Interceptor.attach(address, { 639 | onEnter(args) { 640 | let id = mterp_count; 641 | mterp_count += 1; 642 | let ctx = this.context as Arm64CpuContext; 643 | let thread_ptr = ctx[thread_reg as keyof typeof ctx]; 644 | let shadow_frame = get_shadow_frame_ptr_by_thread_ptr(thread_ptr); 645 | let method_name = get_method_name(shadow_frame); 646 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 647 | let inst_ptr = ctx[inst_reg as keyof typeof ctx]; 648 | let inst_str = PrettyInstruction(inst_ptr, dexfile_ptr); 649 | log(`[${id}] [mterp] ${Process.getCurrentThreadId()} ${method_name} ${inst_str}`); 650 | } 651 | }); 652 | } 653 | ``` 654 | 655 | `ExecuteMterpImpl`第一个参数就是`thread`,再去看汇编,可以看到`X0`给了`X22`,而经过打印验证,`X22`确实也没有改变(除非是不同的线程) 656 | 657 | ![](./images/Snipaste_2022-05-21_21-33-24.png) 658 | 659 | ### 完整的hook脚本需要准备什么 660 | 661 | 经过一系列发分析,验证,现在要打印switch模式和mterp模式下smali指令的详细执行情况 662 | 663 | 最佳方案是: 664 | 665 | - switch模式,找到哪个`ExecuteSwitchImplCpp`实现是当前系统调用的,然后根据 666 | 667 | 1. while特征 668 | 2. 取指针后和`0xFF`相与 669 | 3. BR跳转 670 | 671 | 这三个特征,定位到源代码中`ExecuteSwitchImplCpp`下面这个位置,然后在这里进行hook 672 | 673 | ```c++ 674 | while (true) { 675 | const Instruction* const inst = next; 676 | dex_pc = inst->GetDexPc(insns); 677 | // ... 678 | } 679 | ``` 680 | 681 | 随后通过IDA分析,或者打印`ExecuteSwitchImplCpp`入口处的`shadow_frame`,对比找到不变的寄存器,并确认是`shadow_frame` 682 | 683 | 然后就能详细打印switch模式下执行的具体指令了 684 | 685 | - mterp模式,IDA静态分析`ExecuteMterpImpl`入口赋值,以及hook打印寄存器验证,确定`thread`是哪个寄存器 686 | 687 | 然后hook上mterp模式下每个opcode对应的处理位置,就能详细打印mterp模式下执行的具体指令了 688 | 689 | ## 补充事项 690 | 691 | - 可能有的系统版本`ExecuteSwitchImplCpp`中进行switch判断,跳转opcode处理的分支的指令比较短,这个时候使用frida hook可能导致一些指令异常... 692 | - 这种情况建议手写一个inlinehook,尽可能减少指令占用,这样也许能成(我尝试了,但没有成功) 693 | - 参考资料: 694 | - https://github.com/GToad/Android_Inline_Hook_ARM64 695 | - https://gtoad.github.io/2018/09/20/Android-Native-Hook-Practice-Arm64/ 696 | - https://github.com/AeonLucid/frida-syscall-interceptor 697 | - https://bbs.pediy.com/thread-268086.htm 698 | - 或者分析一下,具体每个case位置,看看能不能像mterp模式那种方法处理(mterp模式下只有nop的处理指令比较短,所以hook没啥问题) 699 | - 系统有的时候使用switch模式执行代码,但大部分时候是mterp模式 700 | 701 | - 可能有些部分我的理解有误,不一定正确,如果你发现了请指正(好像switch模式详细指令打印好像有重复) 702 | 703 | ## 链接 704 | 705 | - https://bbs.pediy.com/thread-263210.htm 706 | - http://aospxref.com/android-11.0.0_r21/xref/art/runtime/interpreter/interpreter.cc#247 707 | - http://aospxref.com/android-11.0.0_r21/xref/art/runtime/interpreter/interpreter_switch_impl-inl.h#1938 708 | - http://aospxref.com/android-11.0.0_r21/xref/art/runtime/interpreter/mterp/arm64/main.S#402 -------------------------------------------------------------------------------- /frida_scripts/_agent.js: -------------------------------------------------------------------------------- 1 | (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i ${PrettyMethod_ptr}`); 14 | let PrettyMethod_func = new NativeFunction(PrettyMethod_ptr, ["pointer", "pointer", "pointer"], ["pointer", "bool"]); 15 | return PrettyMethod_func; 16 | } 17 | exports.get_PrettyMethod = get_PrettyMethod; 18 | function get_GetObsoleteDexCache() { 19 | let GetObsoleteDexCache_ptr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod19GetObsoleteDexCacheEv"); 20 | if (GetObsoleteDexCache_ptr == null) { 21 | logger_1.log(`libart.so GetObsoleteDexCache_ptr is null`); 22 | return; 23 | } 24 | logger_1.log(`GetObsoleteDexCache_ptr => ${GetObsoleteDexCache_ptr}`); 25 | let GetObsoleteDexCache_func = new NativeFunction(GetObsoleteDexCache_ptr, "pointer", ["pointer"]); 26 | return GetObsoleteDexCache_func; 27 | } 28 | exports.get_GetObsoleteDexCache = get_GetObsoleteDexCache; 29 | function get_DumpString() { 30 | let DumpString_ptr = Module.findExportByName("libdexfile.so", "_ZNK3art11Instruction10DumpStringEPKNS_7DexFileE"); 31 | if (DumpString_ptr == null) { 32 | logger_1.log(`libart.so DumpString_ptr is null`); 33 | return; 34 | } 35 | logger_1.log(`DumpString_ptr => ${DumpString_ptr}`); 36 | let DumpString_func = new NativeFunction(DumpString_ptr, ["pointer", "pointer", "pointer"], ["pointer", "pointer"]); 37 | return DumpString_func; 38 | } 39 | exports.get_DumpString = get_DumpString; 40 | function PrettyMethod(art_method_ptr) { 41 | let results = exports.PrettyMethod_func(art_method_ptr, 0); 42 | return readStdString(results); 43 | } 44 | exports.PrettyMethod = PrettyMethod; 45 | function PrettyInstruction(inst_ptr, dexfile_ptr) { 46 | let results = exports.DumpString_func(inst_ptr, dexfile_ptr); 47 | return readStdString(results); 48 | } 49 | exports.PrettyInstruction = PrettyInstruction; 50 | // export function readStdString(pointers: NativePointer[]) { 51 | // let str = Memory.alloc(Process.pointerSize * 3); 52 | // str.writePointer(pointers[0]); 53 | // str.add(Process.pointerSize * 1).writePointer(pointers[1]); 54 | // str.add(Process.pointerSize * 2).writePointer(pointers[2]); 55 | // let isTiny = (str.readU8() & 1) === 0; 56 | // if (isTiny) { 57 | // return str.add(1).readUtf8String(); 58 | // } 59 | // return str.add(2 * Process.pointerSize).readPointer().readUtf8String(); 60 | // } 61 | function readStdString(pointers) { 62 | let str = Memory.alloc(Process.pointerSize * 3); 63 | str.writePointer(pointers[0]); 64 | let isTiny = (str.readU8() & 1) === 0; 65 | if (isTiny) { 66 | str.add(Process.pointerSize * 1).writePointer(pointers[1]); 67 | str.add(Process.pointerSize * 2).writePointer(pointers[2]); 68 | return str.add(1).readUtf8String(); 69 | } 70 | else { 71 | return pointers[2].readUtf8String(); 72 | } 73 | } 74 | exports.readStdString = readStdString; 75 | exports.PrettyMethod_func = get_PrettyMethod(); 76 | exports.DumpString_func = get_DumpString(); 77 | exports.GetObsoleteDexCache_func = get_GetObsoleteDexCache(); 78 | },{"./logger":3}],2:[function(require,module,exports){ 79 | (function (setImmediate){(function (){ 80 | "use strict"; 81 | Object.defineProperty(exports, "__esModule", { value: true }); 82 | exports.rpc_mode = void 0; 83 | const helper_1 = require("./helper"); 84 | const util_1 = require("./util"); 85 | const logger_1 = require("./logger"); 86 | function enable_rpc_mode(flag) { 87 | exports.rpc_mode = flag; 88 | } 89 | function get_method_name(shadow_frame) { 90 | let method_key = shadow_frame.method.toString(); 91 | let method_name = method_name_cache[method_key]; 92 | if (!method_name) { 93 | method_name = shadow_frame.method.PrettyMethod(); 94 | if (method_name) { 95 | method_name_cache[method_key] = method_name; 96 | } 97 | } 98 | return method_name; 99 | } 100 | function trace_interpreter_enrty(libart, hook_switch, hook_mterp) { 101 | libart.enumerateSymbols().forEach(function (symbol) { 102 | let name = symbol.name; 103 | let address = symbol.address; 104 | if (name.includes("ExecuteSwitchImplCpp") && hook_switch) { 105 | logger_1.log(`start hook ${name}`); 106 | let offset = symbol.address.sub(libart.base); 107 | Interceptor.attach(address, { 108 | onEnter(args) { 109 | let ctx = new util_1.SwitchImplContext(args[0]); 110 | let shadow_frame = ctx.shadow_frame; 111 | let method_key = shadow_frame.method.toString(); 112 | let method_name = method_name_cache[method_key]; 113 | if (!method_name) { 114 | method_name = shadow_frame.method.PrettyMethod(); 115 | if (method_name) { 116 | method_name_cache[method_key] = method_name; 117 | } 118 | } 119 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 120 | let dex_pc = shadow_frame.GetDexPC(); 121 | // const Instruction* next = Instruction::At(insns + dex_pc); 122 | let inst_ptr = ctx.accessor.insns.add(dex_pc); 123 | let inst_str = helper_1.PrettyInstruction(inst_ptr, dexfile_ptr); 124 | logger_1.log(`[switch] ${Process.getCurrentThreadId()} ${method_name} ${inst_str}`); 125 | } 126 | }); 127 | } 128 | if (name.includes("ExecuteMterpImpl") && hook_mterp) { 129 | logger_1.log(`start hook ${name}`); 130 | Interceptor.attach(address, { 131 | onEnter(args) { 132 | let inst_ptr = args[1]; 133 | let shadow_frame = new util_1.ShadowFrame(args[2]); 134 | let method_name = get_method_name(shadow_frame); 135 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 136 | let inst_str = helper_1.PrettyInstruction(inst_ptr, dexfile_ptr); 137 | logger_1.log(`[mterp] ${Process.getCurrentThreadId()} ${method_name} ${inst_str}`); 138 | // send({ 139 | // type: "Mterp", 140 | // info: { 141 | // tid: Process.getCurrentThreadId(), 142 | // function_name: function_name, 143 | // inst_string: inst_string 144 | // } 145 | // }) 146 | } 147 | }); 148 | } 149 | }); 150 | } 151 | function trace_interpreter_switch(libart, offset, frame_reg, inst_reg) { 152 | Interceptor.attach(libart.base.add(offset), { 153 | onEnter(args) { 154 | let id = switch_count; 155 | switch_count += 1; 156 | let ctx = this.context; 157 | let shadow_frame = new util_1.ShadowFrame(ctx[frame_reg]); 158 | // 通过 thread 获取到当前的 shadow_frame 159 | // let thread_ptr = ctx.sp.add(0x210).sub(0x168).readPointer(); 160 | // let shadow_frame = get_shadow_frame_ptr_by_thread_ptr(thread_ptr); 161 | let method_name = get_method_name(shadow_frame); 162 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 163 | let inst_ptr = ctx[inst_reg]; 164 | let inst_str = helper_1.PrettyInstruction(inst_ptr, dexfile_ptr); 165 | logger_1.log(`[${id}] [switch] ${method_name} ${inst_str}`); 166 | } 167 | }); 168 | } 169 | function hook_mterp_op(address, offset, thread_reg, inst_reg) { 170 | Interceptor.attach(address, { 171 | onEnter(args) { 172 | let id = mterp_count; 173 | mterp_count += 1; 174 | let ctx = this.context; 175 | let thread_ptr = ctx[thread_reg]; 176 | let shadow_frame = get_shadow_frame_ptr_by_thread_ptr(thread_ptr); 177 | let method_name = get_method_name(shadow_frame); 178 | let dexfile_ptr = shadow_frame.method.GetDexFile(); 179 | let inst_ptr = ctx[inst_reg]; 180 | let inst_str = helper_1.PrettyInstruction(inst_ptr, dexfile_ptr); 181 | logger_1.log(`[${id}] [mterp] ${Process.getCurrentThreadId()} ${method_name} ${inst_str}`); 182 | } 183 | }); 184 | } 185 | function trace_interpreter_mterp_op(libart, thread_reg, inst_reg) { 186 | let op_count = 0; 187 | let symbols = libart.enumerateSymbols(); 188 | for (let index = 0; index < symbols.length; index++) { 189 | const symbol = symbols[index]; 190 | // 过滤不符合要求的符号 191 | if (!symbol.name.startsWith("mterp_op_")) 192 | continue; 193 | if (symbol.name.endsWith("_helper")) 194 | continue; 195 | if (symbol.name.endsWith("_quick")) 196 | continue; 197 | if (symbol.name.endsWith("_no_barrier")) 198 | continue; 199 | if (symbol.name.includes("unused")) 200 | continue; 201 | // nop 对应位置的指令太短 hook 会失败 跳过 202 | if (symbol.name == "mterp_op_nop") 203 | continue; 204 | op_count += 1; 205 | let hook_addr = symbol.address; 206 | // return 相关的指令起始就是一个BL frida hook 会失败 需要把hook点向后挪4字节 207 | if (symbol.name.startsWith("mterp_op_return")) { 208 | hook_addr = symbol.address.add(0x4); 209 | } 210 | let offset = hook_addr.sub(libart.base); 211 | logger_1.log(`[mterp_op] ${symbol.name} ${symbol.address} ${hook_addr} ${offset}`); 212 | // 正式 hook 213 | hook_mterp_op(hook_addr, offset, thread_reg, inst_reg); 214 | } 215 | logger_1.log(`[mterp_op] op_count ${op_count}`); 216 | } 217 | function get_shadow_frame_ptr_by_thread_ptr(thread_ptr) { 218 | // 0xB8 是 managed_stack 在 Thread 中的偏移 需要结合IDA分析 219 | // 如何定位这个偏移 220 | // void art::StackVisitor::WalkStack<(art::StackVisitor::CountTransitions)0>(bool) 221 | // _ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb 222 | // 找到这个函数 然后反编译 在开头找到一个 与 0xFFFFFFFFFFFFFFFELL 相与的变量 223 | // 然后回溯 可以发现它时由传入参数通过偏移取指针再偏移 这个就是 managed_stack 的偏移 224 | // http://aospxref.com/android-11.0.0_r21/xref/art/runtime/stack.cc#835 225 | // let managed_stack = thread_ptr.readPointer().add(0xB8); 226 | let managed_stack = thread_ptr.add(0xB8); 227 | // 0x10 是 top_shadow_frame_ 在 ManagedStack 中的偏移 结合源码或者IDA可以分析出来 228 | let cur_frame_ptr = managed_stack.add(0x10).readPointer(); 229 | return new util_1.ShadowFrame(cur_frame_ptr); 230 | } 231 | function main() { 232 | let libart = Process.findModuleByName("libart.so"); 233 | if (libart == null) { 234 | logger_1.log(`libart is null`); 235 | return; 236 | } 237 | let hook_switch = true; 238 | let hook_mterp = true; 239 | // 仅对 ExecuteSwitchImplCpp 和 ExecuteMterpImpl 调用时 hook 可以得到一些基本调用轨迹 且对APP运行影响很小 240 | trace_interpreter_enrty(libart, hook_switch, hook_mterp); 241 | // 对 ExecuteSwitchImplCpp 实际进行 opcode 判断跳转的位置进行 hook 这样可以得到一个函数内具体执行了什么 242 | // 通过静态分析可以知道 243 | // - x19 是 shadow_frame 244 | // - x26 是 inst 245 | // 调用了 trace_interpreter_switch 记得将 hook_switch 设为 false 避免重复 246 | // trace_interpreter_switch(libart, 0x169EB4, 'x19', 'x26'); 247 | // 进入 ExecuteMterpImpl 后的逻辑就是 248 | // - 计算opcode 跳转实际处理位置 执行处理 249 | // - 再立刻计算下一个opcode 马上跳转实际处理位置 250 | // - 直到执行结束 251 | // 对每个 opcode 实际处理的位置进行 hook 252 | // 通过静态分析和实际测试可以知道 253 | // - x22 是 self 也就是 thread 254 | // - x20 是 inst 255 | // trace_interpreter_mterp_op(libart, "x22", "x20"); 256 | } 257 | exports.rpc_mode = false; 258 | let method_name_cache = {}; 259 | let switch_count = 0; 260 | let mterp_count = 0; 261 | setImmediate(main); 262 | rpc.exports = { 263 | go: main, 264 | enablerpcmode: enable_rpc_mode, 265 | }; 266 | // frida -U -n LibChecker -l _agent.js -o trace.log 267 | // frida -U -n com.absinthe.libchecker -l _agent.js -o trace.log 268 | // frida -U -f com.absinthe.libchecker -l _agent.js -o trace.log --no-pause 269 | }).call(this)}).call(this,require("timers").setImmediate) 270 | 271 | },{"./helper":1,"./logger":3,"./util":4,"timers":6}],3:[function(require,module,exports){ 272 | "use strict"; 273 | Object.defineProperty(exports, "__esModule", { value: true }); 274 | exports.log = void 0; 275 | const index_1 = require("./index"); 276 | function log(message) { 277 | if (index_1.rpc_mode) { 278 | send({ "type": "log", info: message }); 279 | } 280 | else { 281 | console.log(message); 282 | } 283 | } 284 | exports.log = log; 285 | },{"./index":2}],4:[function(require,module,exports){ 286 | "use strict"; 287 | Object.defineProperty(exports, "__esModule", { value: true }); 288 | exports.ArtMethod = exports.ShadowFrame = exports.CodeItemDataAccessor = exports.SwitchImplContext = void 0; 289 | const helper_1 = require("./helper"); 290 | const logger_1 = require("./logger"); 291 | class SwitchImplContext { 292 | constructor(pointer) { 293 | this.pointer = pointer; 294 | this.thread_ptr = this.pointer.readPointer(); 295 | this.accessor = new CodeItemDataAccessor(this.pointer.add(Process.pointerSize).readPointer()); 296 | this.shadow_frame = new ShadowFrame(this.pointer.add(Process.pointerSize * 2).readPointer()); 297 | } 298 | } 299 | exports.SwitchImplContext = SwitchImplContext; 300 | class CodeItemDataAccessor { 301 | constructor(pointer) { 302 | this.pointer = pointer; 303 | this.insns = this.pointer.add(Process.pointerSize).readPointer(); 304 | } 305 | Insns() { 306 | return this.insns; 307 | } 308 | } 309 | exports.CodeItemDataAccessor = CodeItemDataAccessor; 310 | class ShadowFrame { 311 | constructor(pointer) { 312 | this.pointer = pointer; 313 | this.method = new ArtMethod(this.pointer.add(Process.pointerSize).readPointer()); 314 | } 315 | toString() { 316 | return this.pointer.toString(); 317 | } 318 | GetDexPC() { 319 | let dex_pc_ptr_ = this.pointer.add(Process.pointerSize * 3).readPointer(); 320 | if (!dex_pc_ptr_.equals(ptr(0x0))) { 321 | let dex_instructions_ = this.pointer.add(Process.pointerSize * 4).readPointer(); 322 | return Number(dex_pc_ptr_.sub(dex_instructions_).toString()); 323 | } 324 | else { 325 | return this.pointer.add(Process.pointerSize * 6 + 4).readU32(); 326 | } 327 | } 328 | } 329 | exports.ShadowFrame = ShadowFrame; 330 | class ArtMethod { 331 | constructor(pointer) { 332 | this.pointer = pointer; 333 | } 334 | toString() { 335 | return this.pointer.toString(); 336 | } 337 | PrettyMethod() { 338 | return helper_1.PrettyMethod(this.pointer); 339 | } 340 | GetObsoleteDexCache() { 341 | // mirror_ptr ??? 342 | return helper_1.GetObsoleteDexCache_func(this.pointer); 343 | // return ptr(0x0); 344 | } 345 | GetDexFile() { 346 | let access_flags = this.pointer.add(0x4).readU32(); 347 | // IsObsolete() => (GetAccessFlags() & kAccObsoleteMethod) != 0; 348 | if ((access_flags & 0x40000) != 0) { 349 | logger_1.log(`flag => ${access_flags}`); 350 | return this.GetObsoleteDexCache(); 351 | } 352 | else { 353 | let declaring_class_ptr = ptr(this.pointer.readU32()); 354 | let dex_cache_ptr = ptr(declaring_class_ptr.add(0x10).readU32()); 355 | let dex_file_ptr = dex_cache_ptr.add(0x10).readPointer(); 356 | return dex_file_ptr; 357 | } 358 | } 359 | } 360 | exports.ArtMethod = ArtMethod; 361 | },{"./helper":1,"./logger":3}],5:[function(require,module,exports){ 362 | // shim for using process in browser 363 | var process = module.exports = {}; 364 | 365 | // cached from whatever global is present so that test runners that stub it 366 | // don't break things. But we need to wrap it in a try catch in case it is 367 | // wrapped in strict mode code which doesn't define any globals. It's inside a 368 | // function because try/catches deoptimize in certain engines. 369 | 370 | var cachedSetTimeout; 371 | var cachedClearTimeout; 372 | 373 | function defaultSetTimout() { 374 | throw new Error('setTimeout has not been defined'); 375 | } 376 | function defaultClearTimeout () { 377 | throw new Error('clearTimeout has not been defined'); 378 | } 379 | (function () { 380 | try { 381 | if (typeof setTimeout === 'function') { 382 | cachedSetTimeout = setTimeout; 383 | } else { 384 | cachedSetTimeout = defaultSetTimout; 385 | } 386 | } catch (e) { 387 | cachedSetTimeout = defaultSetTimout; 388 | } 389 | try { 390 | if (typeof clearTimeout === 'function') { 391 | cachedClearTimeout = clearTimeout; 392 | } else { 393 | cachedClearTimeout = defaultClearTimeout; 394 | } 395 | } catch (e) { 396 | cachedClearTimeout = defaultClearTimeout; 397 | } 398 | } ()) 399 | function runTimeout(fun) { 400 | if (cachedSetTimeout === setTimeout) { 401 | //normal enviroments in sane situations 402 | return setTimeout(fun, 0); 403 | } 404 | // if setTimeout wasn't available but was latter defined 405 | if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { 406 | cachedSetTimeout = setTimeout; 407 | return setTimeout(fun, 0); 408 | } 409 | try { 410 | // when when somebody has screwed with setTimeout but no I.E. maddness 411 | return cachedSetTimeout(fun, 0); 412 | } catch(e){ 413 | try { 414 | // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 415 | return cachedSetTimeout.call(null, fun, 0); 416 | } catch(e){ 417 | // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error 418 | return cachedSetTimeout.call(this, fun, 0); 419 | } 420 | } 421 | 422 | 423 | } 424 | function runClearTimeout(marker) { 425 | if (cachedClearTimeout === clearTimeout) { 426 | //normal enviroments in sane situations 427 | return clearTimeout(marker); 428 | } 429 | // if clearTimeout wasn't available but was latter defined 430 | if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { 431 | cachedClearTimeout = clearTimeout; 432 | return clearTimeout(marker); 433 | } 434 | try { 435 | // when when somebody has screwed with setTimeout but no I.E. maddness 436 | return cachedClearTimeout(marker); 437 | } catch (e){ 438 | try { 439 | // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally 440 | return cachedClearTimeout.call(null, marker); 441 | } catch (e){ 442 | // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. 443 | // Some versions of I.E. have different rules for clearTimeout vs setTimeout 444 | return cachedClearTimeout.call(this, marker); 445 | } 446 | } 447 | 448 | 449 | 450 | } 451 | var queue = []; 452 | var draining = false; 453 | var currentQueue; 454 | var queueIndex = -1; 455 | 456 | function cleanUpNextTick() { 457 | if (!draining || !currentQueue) { 458 | return; 459 | } 460 | draining = false; 461 | if (currentQueue.length) { 462 | queue = currentQueue.concat(queue); 463 | } else { 464 | queueIndex = -1; 465 | } 466 | if (queue.length) { 467 | drainQueue(); 468 | } 469 | } 470 | 471 | function drainQueue() { 472 | if (draining) { 473 | return; 474 | } 475 | var timeout = runTimeout(cleanUpNextTick); 476 | draining = true; 477 | 478 | var len = queue.length; 479 | while(len) { 480 | currentQueue = queue; 481 | queue = []; 482 | while (++queueIndex < len) { 483 | if (currentQueue) { 484 | currentQueue[queueIndex].run(); 485 | } 486 | } 487 | queueIndex = -1; 488 | len = queue.length; 489 | } 490 | currentQueue = null; 491 | draining = false; 492 | runClearTimeout(timeout); 493 | } 494 | 495 | process.nextTick = function (fun) { 496 | var args = new Array(arguments.length - 1); 497 | if (arguments.length > 1) { 498 | for (var i = 1; i < arguments.length; i++) { 499 | args[i - 1] = arguments[i]; 500 | } 501 | } 502 | queue.push(new Item(fun, args)); 503 | if (queue.length === 1 && !draining) { 504 | runTimeout(drainQueue); 505 | } 506 | }; 507 | 508 | // v8 likes predictible objects 509 | function Item(fun, array) { 510 | this.fun = fun; 511 | this.array = array; 512 | } 513 | Item.prototype.run = function () { 514 | this.fun.apply(null, this.array); 515 | }; 516 | process.title = 'browser'; 517 | process.browser = true; 518 | process.env = {}; 519 | process.argv = []; 520 | process.version = ''; // empty string to avoid regexp issues 521 | process.versions = {}; 522 | 523 | function noop() {} 524 | 525 | process.on = noop; 526 | process.addListener = noop; 527 | process.once = noop; 528 | process.off = noop; 529 | process.removeListener = noop; 530 | process.removeAllListeners = noop; 531 | process.emit = noop; 532 | process.prependListener = noop; 533 | process.prependOnceListener = noop; 534 | 535 | process.listeners = function (name) { return [] } 536 | 537 | process.binding = function (name) { 538 | throw new Error('process.binding is not supported'); 539 | }; 540 | 541 | process.cwd = function () { return '/' }; 542 | process.chdir = function (dir) { 543 | throw new Error('process.chdir is not supported'); 544 | }; 545 | process.umask = function() { return 0; }; 546 | 547 | },{}],6:[function(require,module,exports){ 548 | (function (setImmediate,clearImmediate){(function (){ 549 | var nextTick = require('process/browser.js').nextTick; 550 | var apply = Function.prototype.apply; 551 | var slice = Array.prototype.slice; 552 | var immediateIds = {}; 553 | var nextImmediateId = 0; 554 | 555 | // DOM APIs, for completeness 556 | 557 | exports.setTimeout = function() { 558 | return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); 559 | }; 560 | exports.setInterval = function() { 561 | return new Timeout(apply.call(setInterval, window, arguments), clearInterval); 562 | }; 563 | exports.clearTimeout = 564 | exports.clearInterval = function(timeout) { timeout.close(); }; 565 | 566 | function Timeout(id, clearFn) { 567 | this._id = id; 568 | this._clearFn = clearFn; 569 | } 570 | Timeout.prototype.unref = Timeout.prototype.ref = function() {}; 571 | Timeout.prototype.close = function() { 572 | this._clearFn.call(window, this._id); 573 | }; 574 | 575 | // Does not start the time, just sets up the members needed. 576 | exports.enroll = function(item, msecs) { 577 | clearTimeout(item._idleTimeoutId); 578 | item._idleTimeout = msecs; 579 | }; 580 | 581 | exports.unenroll = function(item) { 582 | clearTimeout(item._idleTimeoutId); 583 | item._idleTimeout = -1; 584 | }; 585 | 586 | exports._unrefActive = exports.active = function(item) { 587 | clearTimeout(item._idleTimeoutId); 588 | 589 | var msecs = item._idleTimeout; 590 | if (msecs >= 0) { 591 | item._idleTimeoutId = setTimeout(function onTimeout() { 592 | if (item._onTimeout) 593 | item._onTimeout(); 594 | }, msecs); 595 | } 596 | }; 597 | 598 | // That's not how node.js implements it but the exposed api is the same. 599 | exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { 600 | var id = nextImmediateId++; 601 | var args = arguments.length < 2 ? false : slice.call(arguments, 1); 602 | 603 | immediateIds[id] = true; 604 | 605 | nextTick(function onNextTick() { 606 | if (immediateIds[id]) { 607 | // fn.call() is faster so we optimize for the common use-case 608 | // @see http://jsperf.com/call-apply-segu 609 | if (args) { 610 | fn.apply(null, args); 611 | } else { 612 | fn.call(null); 613 | } 614 | // Prevent ids from leaking 615 | exports.clearImmediate(id); 616 | } 617 | }); 618 | 619 | return id; 620 | }; 621 | 622 | exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { 623 | delete immediateIds[id]; 624 | }; 625 | }).call(this)}).call(this,require("timers").setImmediate,require("timers").clearImmediate) 626 | 627 | },{"process/browser.js":5,"timers":6}]},{},[2]) 628 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJhZ2VudC9oZWxwZXIudHMiLCJhZ2VudC9pbmRleC50cyIsImFnZW50L2xvZ2dlci50cyIsImFnZW50L3V0aWwudHMiLCJub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL3RpbWVycy1icm93c2VyaWZ5L21haW4uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7QUNBQSxxQ0FBK0I7QUFFL0IsU0FBZ0IsZ0JBQWdCO0lBQzVCLHlHQUF5RztJQUN6RyxJQUFJLGdCQUFnQixHQUFJLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsbUNBQW1DLENBQUMsQ0FBQztJQUNsRyxJQUFJLGdCQUFnQixJQUFJLElBQUksRUFBQztRQUN6QixZQUFHLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUMxQyxPQUFPO0tBQ1Y7SUFDRCxZQUFHLENBQUMsdUJBQXVCLGdCQUFnQixFQUFFLENBQUMsQ0FBQztJQUMvQyxJQUFJLGlCQUFpQixHQUFHLElBQUksY0FBYyxDQUFDLGdCQUFnQixFQUFFLENBQUMsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ3JILE9BQU8saUJBQWlCLENBQUM7QUFDN0IsQ0FBQztBQVZELDRDQVVDO0FBRUQsU0FBZ0IsdUJBQXVCO0lBQ25DLElBQUksdUJBQXVCLEdBQUksTUFBTSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSwwQ0FBMEMsQ0FBQyxDQUFDO0lBQ2hILElBQUksdUJBQXVCLElBQUksSUFBSSxFQUFDO1FBQ2hDLFlBQUcsQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDO1FBQ2pELE9BQU87S0FDVjtJQUNELFlBQUcsQ0FBQyw4QkFBOEIsdUJBQXVCLEVBQUUsQ0FBQyxDQUFDO0lBQzdELElBQUksd0JBQXdCLEdBQUcsSUFBSSxjQUFj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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3hMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIn0= 629 | -------------------------------------------------------------------------------- /frida_scripts/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frida-agent-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@frida/mold-source-map": { 8 | "version": "1.0.0", 9 | "resolved": "https://registry.npmjs.org/@frida/mold-source-map/-/mold-source-map-1.0.0.tgz", 10 | "integrity": "sha512-7nJ2ghCVTe5hxzSVN9bRxMeP/L8eAaViMGfKM7+Bc3sfv1UIJ49yrSlvy8wv8VTwNCTicUTXNlsvglvSKvhUZQ==", 11 | "dev": true, 12 | "requires": { 13 | "convert-source-map": "^1.1.0", 14 | "through": "^2.3.8" 15 | } 16 | }, 17 | "@frida/uglifyify": { 18 | "version": "7.0.1", 19 | "resolved": "https://registry.npmjs.org/@frida/uglifyify/-/uglifyify-7.0.1.tgz", 20 | "integrity": "sha512-i+80AKujltgBzl6Y8s6R4VwJrAG6KL5g0yX+aTsD4i74UbSE8JJg5YwIKh8Je80F+F9LlVg6GjLXMwupZ588Bw==", 21 | "dev": true, 22 | "requires": { 23 | "convert-source-map": "^1.6.0", 24 | "minimatch": "^3.0.4", 25 | "terser": "^5.3.1", 26 | "through": "^2.3.8" 27 | } 28 | }, 29 | "@types/frida-gum": { 30 | "version": "17.1.0", 31 | "resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-17.1.0.tgz", 32 | "integrity": "sha512-RXq0yw5Jp9BZqCIT8o4OaPJwt/nL4Ww60ny1MrzcO0Kiqw5L2QuftcB2eRRMdYQRn59hI4qzcdzilj5yklYz4w==", 33 | "dev": true 34 | }, 35 | "@types/node": { 36 | "version": "16.4.8", 37 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.8.tgz", 38 | "integrity": "sha512-VL7RZyCpfYEmbyd3/Eq5RNYhZt7yoL1JThZQ3KzimzhLya2Qa86U1ZZmioNWAAjiz99z1ED1xF9NUV2srvfVrA==", 39 | "dev": true 40 | }, 41 | "JSONStream": { 42 | "version": "1.3.5", 43 | "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", 44 | "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", 45 | "dev": true, 46 | "requires": { 47 | "jsonparse": "^1.2.0", 48 | "through": ">=2.2.7 <3" 49 | } 50 | }, 51 | "acorn": { 52 | "version": "7.4.1", 53 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 54 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", 55 | "dev": true 56 | }, 57 | "acorn-node": { 58 | "version": "1.8.2", 59 | "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", 60 | "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", 61 | "dev": true, 62 | "requires": { 63 | "acorn": "^7.0.0", 64 | "acorn-walk": "^7.0.0", 65 | "xtend": "^4.0.2" 66 | } 67 | }, 68 | "acorn-walk": { 69 | "version": "7.2.0", 70 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", 71 | "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", 72 | "dev": true 73 | }, 74 | "ansi-styles": { 75 | "version": "4.3.0", 76 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 77 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 78 | "dev": true, 79 | "requires": { 80 | "color-convert": "^2.0.1" 81 | } 82 | }, 83 | "any-promise": { 84 | "version": "1.3.0", 85 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 86 | "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", 87 | "dev": true 88 | }, 89 | "anymatch": { 90 | "version": "3.1.2", 91 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 92 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 93 | "dev": true, 94 | "requires": { 95 | "normalize-path": "^3.0.0", 96 | "picomatch": "^2.0.4" 97 | } 98 | }, 99 | "asn1.js": { 100 | "version": "5.4.1", 101 | "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", 102 | "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", 103 | "dev": true, 104 | "requires": { 105 | "bn.js": "^4.0.0", 106 | "inherits": "^2.0.1", 107 | "minimalistic-assert": "^1.0.0", 108 | "safer-buffer": "^2.1.0" 109 | }, 110 | "dependencies": { 111 | "bn.js": { 112 | "version": "4.12.0", 113 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 114 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 115 | "dev": true 116 | } 117 | } 118 | }, 119 | "assert": { 120 | "version": "1.5.0", 121 | "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", 122 | "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", 123 | "dev": true, 124 | "requires": { 125 | "object-assign": "^4.1.1", 126 | "util": "0.10.3" 127 | }, 128 | "dependencies": { 129 | "inherits": { 130 | "version": "2.0.1", 131 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 132 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", 133 | "dev": true 134 | }, 135 | "util": { 136 | "version": "0.10.3", 137 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", 138 | "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", 139 | "dev": true, 140 | "requires": { 141 | "inherits": "2.0.1" 142 | } 143 | } 144 | } 145 | }, 146 | "available-typed-arrays": { 147 | "version": "1.0.4", 148 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", 149 | "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==", 150 | "dev": true 151 | }, 152 | "balanced-match": { 153 | "version": "1.0.2", 154 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 155 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 156 | "dev": true 157 | }, 158 | "base64-js": { 159 | "version": "1.5.1", 160 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 161 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 162 | "dev": true 163 | }, 164 | "bignumber.js": { 165 | "version": "9.0.1", 166 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", 167 | "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", 168 | "dev": true 169 | }, 170 | "binary-extensions": { 171 | "version": "2.2.0", 172 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 173 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 174 | "dev": true 175 | }, 176 | "bn.js": { 177 | "version": "5.2.0", 178 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", 179 | "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", 180 | "dev": true 181 | }, 182 | "brace-expansion": { 183 | "version": "1.1.11", 184 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 185 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 186 | "dev": true, 187 | "requires": { 188 | "balanced-match": "^1.0.0", 189 | "concat-map": "0.0.1" 190 | } 191 | }, 192 | "braces": { 193 | "version": "3.0.2", 194 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 195 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 196 | "dev": true, 197 | "requires": { 198 | "fill-range": "^7.0.1" 199 | } 200 | }, 201 | "brorand": { 202 | "version": "1.1.0", 203 | "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", 204 | "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", 205 | "dev": true 206 | }, 207 | "browser-pack": { 208 | "version": "6.1.0", 209 | "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", 210 | "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", 211 | "dev": true, 212 | "requires": { 213 | "JSONStream": "^1.0.3", 214 | "combine-source-map": "~0.8.0", 215 | "defined": "^1.0.0", 216 | "safe-buffer": "^5.1.1", 217 | "through2": "^2.0.0", 218 | "umd": "^3.0.0" 219 | }, 220 | "dependencies": { 221 | "through2": { 222 | "version": "2.0.5", 223 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 224 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 225 | "dev": true, 226 | "requires": { 227 | "readable-stream": "~2.3.6", 228 | "xtend": "~4.0.1" 229 | } 230 | } 231 | } 232 | }, 233 | "browser-resolve": { 234 | "version": "2.0.0", 235 | "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", 236 | "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", 237 | "dev": true, 238 | "requires": { 239 | "resolve": "^1.17.0" 240 | } 241 | }, 242 | "browserify": { 243 | "version": "17.0.0", 244 | "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", 245 | "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", 246 | "dev": true, 247 | "requires": { 248 | "JSONStream": "^1.0.3", 249 | "assert": "^1.4.0", 250 | "browser-pack": "^6.0.1", 251 | "browser-resolve": "^2.0.0", 252 | "browserify-zlib": "~0.2.0", 253 | "buffer": "~5.2.1", 254 | "cached-path-relative": "^1.0.0", 255 | "concat-stream": "^1.6.0", 256 | "console-browserify": "^1.1.0", 257 | "constants-browserify": "~1.0.0", 258 | "crypto-browserify": "^3.0.0", 259 | "defined": "^1.0.0", 260 | "deps-sort": "^2.0.1", 261 | "domain-browser": "^1.2.0", 262 | "duplexer2": "~0.1.2", 263 | "events": "^3.0.0", 264 | "glob": "^7.1.0", 265 | "has": "^1.0.0", 266 | "htmlescape": "^1.1.0", 267 | "https-browserify": "^1.0.0", 268 | "inherits": "~2.0.1", 269 | "insert-module-globals": "^7.2.1", 270 | "labeled-stream-splicer": "^2.0.0", 271 | "mkdirp-classic": "^0.5.2", 272 | "module-deps": "^6.2.3", 273 | "os-browserify": "~0.3.0", 274 | "parents": "^1.0.1", 275 | "path-browserify": "^1.0.0", 276 | "process": "~0.11.0", 277 | "punycode": "^1.3.2", 278 | "querystring-es3": "~0.2.0", 279 | "read-only-stream": "^2.0.0", 280 | "readable-stream": "^2.0.2", 281 | "resolve": "^1.1.4", 282 | "shasum-object": "^1.0.0", 283 | "shell-quote": "^1.6.1", 284 | "stream-browserify": "^3.0.0", 285 | "stream-http": "^3.0.0", 286 | "string_decoder": "^1.1.1", 287 | "subarg": "^1.0.0", 288 | "syntax-error": "^1.1.1", 289 | "through2": "^2.0.0", 290 | "timers-browserify": "^1.0.1", 291 | "tty-browserify": "0.0.1", 292 | "url": "~0.11.0", 293 | "util": "~0.12.0", 294 | "vm-browserify": "^1.0.0", 295 | "xtend": "^4.0.0" 296 | }, 297 | "dependencies": { 298 | "concat-stream": { 299 | "version": "1.6.2", 300 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 301 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 302 | "dev": true, 303 | "requires": { 304 | "buffer-from": "^1.0.0", 305 | "inherits": "^2.0.3", 306 | "readable-stream": "^2.2.2", 307 | "typedarray": "^0.0.6" 308 | } 309 | }, 310 | "through2": { 311 | "version": "2.0.5", 312 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 313 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 314 | "dev": true, 315 | "requires": { 316 | "readable-stream": "~2.3.6", 317 | "xtend": "~4.0.1" 318 | } 319 | } 320 | } 321 | }, 322 | "browserify-aes": { 323 | "version": "1.2.0", 324 | "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", 325 | "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", 326 | "dev": true, 327 | "requires": { 328 | "buffer-xor": "^1.0.3", 329 | "cipher-base": "^1.0.0", 330 | "create-hash": "^1.1.0", 331 | "evp_bytestokey": "^1.0.3", 332 | "inherits": "^2.0.1", 333 | "safe-buffer": "^5.0.1" 334 | } 335 | }, 336 | "browserify-cipher": { 337 | "version": "1.0.1", 338 | "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", 339 | "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", 340 | "dev": true, 341 | "requires": { 342 | "browserify-aes": "^1.0.4", 343 | "browserify-des": "^1.0.0", 344 | "evp_bytestokey": "^1.0.0" 345 | } 346 | }, 347 | "browserify-des": { 348 | "version": "1.0.2", 349 | "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", 350 | "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", 351 | "dev": true, 352 | "requires": { 353 | "cipher-base": "^1.0.1", 354 | "des.js": "^1.0.0", 355 | "inherits": "^2.0.1", 356 | "safe-buffer": "^5.1.2" 357 | } 358 | }, 359 | "browserify-rsa": { 360 | "version": "4.1.0", 361 | "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", 362 | "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", 363 | "dev": true, 364 | "requires": { 365 | "bn.js": "^5.0.0", 366 | "randombytes": "^2.0.1" 367 | } 368 | }, 369 | "browserify-sign": { 370 | "version": "4.2.1", 371 | "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", 372 | "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", 373 | "dev": true, 374 | "requires": { 375 | "bn.js": "^5.1.1", 376 | "browserify-rsa": "^4.0.1", 377 | "create-hash": "^1.2.0", 378 | "create-hmac": "^1.1.7", 379 | "elliptic": "^6.5.3", 380 | "inherits": "^2.0.4", 381 | "parse-asn1": "^5.1.5", 382 | "readable-stream": "^3.6.0", 383 | "safe-buffer": "^5.2.0" 384 | }, 385 | "dependencies": { 386 | "readable-stream": { 387 | "version": "3.6.0", 388 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 389 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 390 | "dev": true, 391 | "requires": { 392 | "inherits": "^2.0.3", 393 | "string_decoder": "^1.1.1", 394 | "util-deprecate": "^1.0.1" 395 | } 396 | } 397 | } 398 | }, 399 | "browserify-zlib": { 400 | "version": "0.2.0", 401 | "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", 402 | "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", 403 | "dev": true, 404 | "requires": { 405 | "pako": "~1.0.5" 406 | } 407 | }, 408 | "buffer": { 409 | "version": "5.2.1", 410 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", 411 | "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", 412 | "dev": true, 413 | "requires": { 414 | "base64-js": "^1.0.2", 415 | "ieee754": "^1.1.4" 416 | } 417 | }, 418 | "buffer-from": { 419 | "version": "1.1.2", 420 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 421 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 422 | "dev": true 423 | }, 424 | "buffer-xor": { 425 | "version": "1.0.3", 426 | "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", 427 | "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", 428 | "dev": true 429 | }, 430 | "builtin-status-codes": { 431 | "version": "3.0.0", 432 | "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", 433 | "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", 434 | "dev": true 435 | }, 436 | "cached-path-relative": { 437 | "version": "1.0.2", 438 | "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", 439 | "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", 440 | "dev": true 441 | }, 442 | "call-bind": { 443 | "version": "1.0.2", 444 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 445 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 446 | "dev": true, 447 | "requires": { 448 | "function-bind": "^1.1.1", 449 | "get-intrinsic": "^1.0.2" 450 | } 451 | }, 452 | "chalk": { 453 | "version": "4.1.2", 454 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 455 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 456 | "dev": true, 457 | "requires": { 458 | "ansi-styles": "^4.1.0", 459 | "supports-color": "^7.1.0" 460 | } 461 | }, 462 | "chokidar": { 463 | "version": "3.5.2", 464 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", 465 | "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", 466 | "dev": true, 467 | "requires": { 468 | "anymatch": "~3.1.2", 469 | "braces": "~3.0.2", 470 | "fsevents": "~2.3.2", 471 | "glob-parent": "~5.1.2", 472 | "is-binary-path": "~2.1.0", 473 | "is-glob": "~4.0.1", 474 | "normalize-path": "~3.0.0", 475 | "readdirp": "~3.6.0" 476 | } 477 | }, 478 | "cipher-base": { 479 | "version": "1.0.4", 480 | "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", 481 | "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", 482 | "dev": true, 483 | "requires": { 484 | "inherits": "^2.0.1", 485 | "safe-buffer": "^5.0.1" 486 | } 487 | }, 488 | "color-convert": { 489 | "version": "2.0.1", 490 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 491 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 492 | "dev": true, 493 | "requires": { 494 | "color-name": "~1.1.4" 495 | } 496 | }, 497 | "color-name": { 498 | "version": "1.1.4", 499 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 500 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 501 | "dev": true 502 | }, 503 | "combine-source-map": { 504 | "version": "0.8.0", 505 | "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", 506 | "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", 507 | "dev": true, 508 | "requires": { 509 | "convert-source-map": "~1.1.0", 510 | "inline-source-map": "~0.6.0", 511 | "lodash.memoize": "~3.0.3", 512 | "source-map": "~0.5.3" 513 | }, 514 | "dependencies": { 515 | "convert-source-map": { 516 | "version": "1.1.3", 517 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", 518 | "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", 519 | "dev": true 520 | } 521 | } 522 | }, 523 | "commander": { 524 | "version": "6.2.1", 525 | "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", 526 | "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", 527 | "dev": true 528 | }, 529 | "concat-map": { 530 | "version": "0.0.1", 531 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 532 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 533 | "dev": true 534 | }, 535 | "concat-stream": { 536 | "version": "2.0.0", 537 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", 538 | "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", 539 | "dev": true, 540 | "requires": { 541 | "buffer-from": "^1.0.0", 542 | "inherits": "^2.0.3", 543 | "readable-stream": "^3.0.2", 544 | "typedarray": "^0.0.6" 545 | }, 546 | "dependencies": { 547 | "readable-stream": { 548 | "version": "3.6.0", 549 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 550 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 551 | "dev": true, 552 | "requires": { 553 | "inherits": "^2.0.3", 554 | "string_decoder": "^1.1.1", 555 | "util-deprecate": "^1.0.1" 556 | } 557 | } 558 | } 559 | }, 560 | "console-browserify": { 561 | "version": "1.2.0", 562 | "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", 563 | "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", 564 | "dev": true 565 | }, 566 | "constants-browserify": { 567 | "version": "1.0.0", 568 | "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", 569 | "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", 570 | "dev": true 571 | }, 572 | "convert-source-map": { 573 | "version": "1.8.0", 574 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", 575 | "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", 576 | "dev": true, 577 | "requires": { 578 | "safe-buffer": "~5.1.1" 579 | }, 580 | "dependencies": { 581 | "safe-buffer": { 582 | "version": "5.1.2", 583 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 584 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 585 | "dev": true 586 | } 587 | } 588 | }, 589 | "core-util-is": { 590 | "version": "1.0.2", 591 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 592 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 593 | "dev": true 594 | }, 595 | "create-ecdh": { 596 | "version": "4.0.4", 597 | "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", 598 | "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", 599 | "dev": true, 600 | "requires": { 601 | "bn.js": "^4.1.0", 602 | "elliptic": "^6.5.3" 603 | }, 604 | "dependencies": { 605 | "bn.js": { 606 | "version": "4.12.0", 607 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 608 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 609 | "dev": true 610 | } 611 | } 612 | }, 613 | "create-hash": { 614 | "version": "1.2.0", 615 | "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", 616 | "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", 617 | "dev": true, 618 | "requires": { 619 | "cipher-base": "^1.0.1", 620 | "inherits": "^2.0.1", 621 | "md5.js": "^1.3.4", 622 | "ripemd160": "^2.0.1", 623 | "sha.js": "^2.4.0" 624 | } 625 | }, 626 | "create-hmac": { 627 | "version": "1.1.7", 628 | "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", 629 | "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", 630 | "dev": true, 631 | "requires": { 632 | "cipher-base": "^1.0.3", 633 | "create-hash": "^1.1.0", 634 | "inherits": "^2.0.1", 635 | "ripemd160": "^2.0.0", 636 | "safe-buffer": "^5.0.1", 637 | "sha.js": "^2.4.8" 638 | } 639 | }, 640 | "crypto-browserify": { 641 | "version": "3.12.0", 642 | "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", 643 | "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", 644 | "dev": true, 645 | "requires": { 646 | "browserify-cipher": "^1.0.0", 647 | "browserify-sign": "^4.0.0", 648 | "create-ecdh": "^4.0.0", 649 | "create-hash": "^1.1.0", 650 | "create-hmac": "^1.1.0", 651 | "diffie-hellman": "^5.0.0", 652 | "inherits": "^2.0.1", 653 | "pbkdf2": "^3.0.3", 654 | "public-encrypt": "^4.0.0", 655 | "randombytes": "^2.0.0", 656 | "randomfill": "^1.0.3" 657 | } 658 | }, 659 | "dash-ast": { 660 | "version": "1.0.0", 661 | "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", 662 | "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", 663 | "dev": true 664 | }, 665 | "define-properties": { 666 | "version": "1.1.3", 667 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 668 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 669 | "dev": true, 670 | "requires": { 671 | "object-keys": "^1.0.12" 672 | } 673 | }, 674 | "defined": { 675 | "version": "1.0.0", 676 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", 677 | "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", 678 | "dev": true 679 | }, 680 | "deps-sort": { 681 | "version": "2.0.1", 682 | "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", 683 | "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", 684 | "dev": true, 685 | "requires": { 686 | "JSONStream": "^1.0.3", 687 | "shasum-object": "^1.0.0", 688 | "subarg": "^1.0.0", 689 | "through2": "^2.0.0" 690 | }, 691 | "dependencies": { 692 | "through2": { 693 | "version": "2.0.5", 694 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 695 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 696 | "dev": true, 697 | "requires": { 698 | "readable-stream": "~2.3.6", 699 | "xtend": "~4.0.1" 700 | } 701 | } 702 | } 703 | }, 704 | "des.js": { 705 | "version": "1.0.1", 706 | "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", 707 | "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", 708 | "dev": true, 709 | "requires": { 710 | "inherits": "^2.0.1", 711 | "minimalistic-assert": "^1.0.0" 712 | } 713 | }, 714 | "detective": { 715 | "version": "5.2.0", 716 | "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", 717 | "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", 718 | "dev": true, 719 | "requires": { 720 | "acorn-node": "^1.6.1", 721 | "defined": "^1.0.0", 722 | "minimist": "^1.1.1" 723 | } 724 | }, 725 | "diffie-hellman": { 726 | "version": "5.0.3", 727 | "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", 728 | "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", 729 | "dev": true, 730 | "requires": { 731 | "bn.js": "^4.1.0", 732 | "miller-rabin": "^4.0.0", 733 | "randombytes": "^2.0.0" 734 | }, 735 | "dependencies": { 736 | "bn.js": { 737 | "version": "4.12.0", 738 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 739 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 740 | "dev": true 741 | } 742 | } 743 | }, 744 | "domain-browser": { 745 | "version": "1.2.0", 746 | "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", 747 | "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", 748 | "dev": true 749 | }, 750 | "duplexer2": { 751 | "version": "0.1.4", 752 | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", 753 | "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", 754 | "dev": true, 755 | "requires": { 756 | "readable-stream": "^2.0.2" 757 | } 758 | }, 759 | "elliptic": { 760 | "version": "6.5.4", 761 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", 762 | "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", 763 | "dev": true, 764 | "requires": { 765 | "bn.js": "^4.11.9", 766 | "brorand": "^1.1.0", 767 | "hash.js": "^1.0.0", 768 | "hmac-drbg": "^1.0.1", 769 | "inherits": "^2.0.4", 770 | "minimalistic-assert": "^1.0.1", 771 | "minimalistic-crypto-utils": "^1.0.1" 772 | }, 773 | "dependencies": { 774 | "bn.js": { 775 | "version": "4.12.0", 776 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 777 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 778 | "dev": true 779 | } 780 | } 781 | }, 782 | "error-ex": { 783 | "version": "1.3.2", 784 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 785 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 786 | "dev": true, 787 | "requires": { 788 | "is-arrayish": "^0.2.1" 789 | } 790 | }, 791 | "es-abstract": { 792 | "version": "1.18.4", 793 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.4.tgz", 794 | "integrity": "sha512-xjDAPJRxKc1uoTkdW8MEk7Fq/2bzz3YoCADYniDV7+KITCUdu9c90fj1aKI7nEZFZxRrHlDo3wtma/C6QkhlXQ==", 795 | "dev": true, 796 | "requires": { 797 | "call-bind": "^1.0.2", 798 | "es-to-primitive": "^1.2.1", 799 | "function-bind": "^1.1.1", 800 | "get-intrinsic": "^1.1.1", 801 | "has": "^1.0.3", 802 | "has-symbols": "^1.0.2", 803 | "internal-slot": "^1.0.3", 804 | "is-callable": "^1.2.3", 805 | "is-negative-zero": "^2.0.1", 806 | "is-regex": "^1.1.3", 807 | "is-string": "^1.0.6", 808 | "object-inspect": "^1.11.0", 809 | "object-keys": "^1.1.1", 810 | "object.assign": "^4.1.2", 811 | "string.prototype.trimend": "^1.0.4", 812 | "string.prototype.trimstart": "^1.0.4", 813 | "unbox-primitive": "^1.0.1" 814 | } 815 | }, 816 | "es-to-primitive": { 817 | "version": "1.2.1", 818 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 819 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 820 | "dev": true, 821 | "requires": { 822 | "is-callable": "^1.1.4", 823 | "is-date-object": "^1.0.1", 824 | "is-symbol": "^1.0.2" 825 | } 826 | }, 827 | "events": { 828 | "version": "3.3.0", 829 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", 830 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", 831 | "dev": true 832 | }, 833 | "evp_bytestokey": { 834 | "version": "1.0.3", 835 | "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", 836 | "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", 837 | "dev": true, 838 | "requires": { 839 | "md5.js": "^1.3.4", 840 | "safe-buffer": "^5.1.1" 841 | } 842 | }, 843 | "fast-safe-stringify": { 844 | "version": "2.0.8", 845 | "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", 846 | "integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==", 847 | "dev": true 848 | }, 849 | "fill-range": { 850 | "version": "7.0.1", 851 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 852 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 853 | "dev": true, 854 | "requires": { 855 | "to-regex-range": "^5.0.1" 856 | } 857 | }, 858 | "foreach": { 859 | "version": "2.0.5", 860 | "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", 861 | "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", 862 | "dev": true 863 | }, 864 | "frida-any-promise": { 865 | "version": "2.0.0", 866 | "resolved": "https://registry.npmjs.org/frida-any-promise/-/frida-any-promise-2.0.0.tgz", 867 | "integrity": "sha512-UbQZMmq7JybTSLBBhsoBfR6R0ydi4t7l0D9ttD4MGUKOxrNlUzCJEw0vw+ubSLok9MNXTZ63MBrPUNJRKhAnrg==", 868 | "dev": true 869 | }, 870 | "frida-buffer": { 871 | "version": "1.0.7", 872 | "resolved": "https://registry.npmjs.org/frida-buffer/-/frida-buffer-1.0.7.tgz", 873 | "integrity": "sha512-7/7SuGI411k7JuQPIjETS07oa9h95E39kA8ky3/8D2ybL7XhVR1s6LPo/q8ew6zeWYQ1x52ZHhJGyoOAfWUJBA==", 874 | "dev": true, 875 | "requires": { 876 | "buffer": "^5.3.0" 877 | }, 878 | "dependencies": { 879 | "buffer": { 880 | "version": "5.7.1", 881 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 882 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 883 | "dev": true, 884 | "requires": { 885 | "base64-js": "^1.3.1", 886 | "ieee754": "^1.1.13" 887 | } 888 | } 889 | } 890 | }, 891 | "frida-compile": { 892 | "version": "10.2.4", 893 | "resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-10.2.4.tgz", 894 | "integrity": "sha512-nwAOHT3yB7YY9xodTmkhjWEw0cwQiHal3ah+q/wcNh5n5Vyl7q6jgLF7aJjQ0zhMP0hy+5+D2QXnQmtArXcwzw==", 895 | "dev": true, 896 | "requires": { 897 | "@frida/mold-source-map": "^1.0.0", 898 | "@frida/uglifyify": "^7.0.1", 899 | "bignumber.js": "^9.0.0", 900 | "browserify": "^17.0.0", 901 | "chalk": "^4.1.0", 902 | "chokidar": "^3.0.0", 903 | "commander": "^6.1.0", 904 | "concat-stream": "^2.0.0", 905 | "frida-any-promise": "^2.0.0", 906 | "frida-buffer": "^1.0.7", 907 | "frida-fs": "^3.0.0", 908 | "frida-http": "^3.0.0", 909 | "frida-net": "^3.0.1", 910 | "frida-process": "^3.0.1", 911 | "node-notifier": "^8.0.1", 912 | "through2": "^4.0.2", 913 | "tsify": "^5.0.2", 914 | "typescript": "^4.0.2" 915 | } 916 | }, 917 | "frida-fs": { 918 | "version": "3.0.1", 919 | "resolved": "https://registry.npmjs.org/frida-fs/-/frida-fs-3.0.1.tgz", 920 | "integrity": "sha512-lbf3CYySo6jNw82EUAWYe31f1wbgIARdnzHDIdDrrxowBS19xvrZSYMYHqw2iJWkTOzJ4ueoF6WGF85QtCsM4g==", 921 | "dev": true 922 | }, 923 | "frida-http": { 924 | "version": "3.0.0", 925 | "resolved": "https://registry.npmjs.org/frida-http/-/frida-http-3.0.0.tgz", 926 | "integrity": "sha512-3jyuQx6vEMcmbnmSR4QzzdcLERhrjR90Gjg/wtYD7wUxZMwMxasfFeqmcLQ+exLNTwD+dI9HquGByuSn3h+9rw==", 927 | "dev": true, 928 | "requires": { 929 | "http-parser-js": "^0.5.1" 930 | } 931 | }, 932 | "frida-net": { 933 | "version": "3.0.1", 934 | "resolved": "https://registry.npmjs.org/frida-net/-/frida-net-3.0.1.tgz", 935 | "integrity": "sha512-N4wu2120FZQC9YZsKWoGnfGlSwVPI9VcQW48kYccuYKhXfMWTnKnDZRA3MJ7sxMMX4zrOkihe9vtHw1aoBCqAg==", 936 | "dev": true, 937 | "requires": { 938 | "ipaddr.js": "^1.9.1" 939 | } 940 | }, 941 | "frida-process": { 942 | "version": "3.0.1", 943 | "resolved": "https://registry.npmjs.org/frida-process/-/frida-process-3.0.1.tgz", 944 | "integrity": "sha512-TigqmU3Y4XNkJi1bYIC6lT3dUSVRMzyjguIvlHs8XH9+39ykRztgoARJd6vH2+n58OeQFs03MlQiW/KI5q6jVQ==", 945 | "dev": true 946 | }, 947 | "fs.realpath": { 948 | "version": "1.0.0", 949 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 950 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 951 | "dev": true 952 | }, 953 | "fsevents": { 954 | "version": "2.3.2", 955 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 956 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 957 | "dev": true, 958 | "optional": true 959 | }, 960 | "function-bind": { 961 | "version": "1.1.1", 962 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 963 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 964 | "dev": true 965 | }, 966 | "get-assigned-identifiers": { 967 | "version": "1.2.0", 968 | "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", 969 | "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", 970 | "dev": true 971 | }, 972 | "get-intrinsic": { 973 | "version": "1.1.1", 974 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 975 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 976 | "dev": true, 977 | "requires": { 978 | "function-bind": "^1.1.1", 979 | "has": "^1.0.3", 980 | "has-symbols": "^1.0.1" 981 | } 982 | }, 983 | "glob": { 984 | "version": "7.1.7", 985 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 986 | "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 987 | "dev": true, 988 | "requires": { 989 | "fs.realpath": "^1.0.0", 990 | "inflight": "^1.0.4", 991 | "inherits": "2", 992 | "minimatch": "^3.0.4", 993 | "once": "^1.3.0", 994 | "path-is-absolute": "^1.0.0" 995 | } 996 | }, 997 | "glob-parent": { 998 | "version": "5.1.2", 999 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1000 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1001 | "dev": true, 1002 | "requires": { 1003 | "is-glob": "^4.0.1" 1004 | } 1005 | }, 1006 | "growly": { 1007 | "version": "1.3.0", 1008 | "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", 1009 | "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", 1010 | "dev": true 1011 | }, 1012 | "has": { 1013 | "version": "1.0.3", 1014 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1015 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1016 | "dev": true, 1017 | "requires": { 1018 | "function-bind": "^1.1.1" 1019 | } 1020 | }, 1021 | "has-bigints": { 1022 | "version": "1.0.1", 1023 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", 1024 | "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", 1025 | "dev": true 1026 | }, 1027 | "has-flag": { 1028 | "version": "4.0.0", 1029 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1030 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1031 | "dev": true 1032 | }, 1033 | "has-symbols": { 1034 | "version": "1.0.2", 1035 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", 1036 | "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", 1037 | "dev": true 1038 | }, 1039 | "hash-base": { 1040 | "version": "3.1.0", 1041 | "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", 1042 | "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", 1043 | "dev": true, 1044 | "requires": { 1045 | "inherits": "^2.0.4", 1046 | "readable-stream": "^3.6.0", 1047 | "safe-buffer": "^5.2.0" 1048 | }, 1049 | "dependencies": { 1050 | "readable-stream": { 1051 | "version": "3.6.0", 1052 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 1053 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 1054 | "dev": true, 1055 | "requires": { 1056 | "inherits": "^2.0.3", 1057 | "string_decoder": "^1.1.1", 1058 | "util-deprecate": "^1.0.1" 1059 | } 1060 | } 1061 | } 1062 | }, 1063 | "hash.js": { 1064 | "version": "1.1.7", 1065 | "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", 1066 | "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", 1067 | "dev": true, 1068 | "requires": { 1069 | "inherits": "^2.0.3", 1070 | "minimalistic-assert": "^1.0.1" 1071 | } 1072 | }, 1073 | "hmac-drbg": { 1074 | "version": "1.0.1", 1075 | "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", 1076 | "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", 1077 | "dev": true, 1078 | "requires": { 1079 | "hash.js": "^1.0.3", 1080 | "minimalistic-assert": "^1.0.0", 1081 | "minimalistic-crypto-utils": "^1.0.1" 1082 | } 1083 | }, 1084 | "htmlescape": { 1085 | "version": "1.1.1", 1086 | "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", 1087 | "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", 1088 | "dev": true 1089 | }, 1090 | "http-parser-js": { 1091 | "version": "0.5.3", 1092 | "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", 1093 | "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", 1094 | "dev": true 1095 | }, 1096 | "https-browserify": { 1097 | "version": "1.0.0", 1098 | "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", 1099 | "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", 1100 | "dev": true 1101 | }, 1102 | "ieee754": { 1103 | "version": "1.2.1", 1104 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 1105 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 1106 | "dev": true 1107 | }, 1108 | "inflight": { 1109 | "version": "1.0.6", 1110 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1111 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1112 | "dev": true, 1113 | "requires": { 1114 | "once": "^1.3.0", 1115 | "wrappy": "1" 1116 | } 1117 | }, 1118 | "inherits": { 1119 | "version": "2.0.4", 1120 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1121 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1122 | "dev": true 1123 | }, 1124 | "inline-source-map": { 1125 | "version": "0.6.2", 1126 | "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", 1127 | "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", 1128 | "dev": true, 1129 | "requires": { 1130 | "source-map": "~0.5.3" 1131 | } 1132 | }, 1133 | "insert-module-globals": { 1134 | "version": "7.2.1", 1135 | "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", 1136 | "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", 1137 | "dev": true, 1138 | "requires": { 1139 | "JSONStream": "^1.0.3", 1140 | "acorn-node": "^1.5.2", 1141 | "combine-source-map": "^0.8.0", 1142 | "concat-stream": "^1.6.1", 1143 | "is-buffer": "^1.1.0", 1144 | "path-is-absolute": "^1.0.1", 1145 | "process": "~0.11.0", 1146 | "through2": "^2.0.0", 1147 | "undeclared-identifiers": "^1.1.2", 1148 | "xtend": "^4.0.0" 1149 | }, 1150 | "dependencies": { 1151 | "concat-stream": { 1152 | "version": "1.6.2", 1153 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 1154 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 1155 | "dev": true, 1156 | "requires": { 1157 | "buffer-from": "^1.0.0", 1158 | "inherits": "^2.0.3", 1159 | "readable-stream": "^2.2.2", 1160 | "typedarray": "^0.0.6" 1161 | } 1162 | }, 1163 | "through2": { 1164 | "version": "2.0.5", 1165 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 1166 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 1167 | "dev": true, 1168 | "requires": { 1169 | "readable-stream": "~2.3.6", 1170 | "xtend": "~4.0.1" 1171 | } 1172 | } 1173 | } 1174 | }, 1175 | "internal-slot": { 1176 | "version": "1.0.3", 1177 | "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", 1178 | "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", 1179 | "dev": true, 1180 | "requires": { 1181 | "get-intrinsic": "^1.1.0", 1182 | "has": "^1.0.3", 1183 | "side-channel": "^1.0.4" 1184 | } 1185 | }, 1186 | "ipaddr.js": { 1187 | "version": "1.9.1", 1188 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1189 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 1190 | "dev": true 1191 | }, 1192 | "is-arguments": { 1193 | "version": "1.1.0", 1194 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", 1195 | "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", 1196 | "dev": true, 1197 | "requires": { 1198 | "call-bind": "^1.0.0" 1199 | } 1200 | }, 1201 | "is-arrayish": { 1202 | "version": "0.2.1", 1203 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 1204 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 1205 | "dev": true 1206 | }, 1207 | "is-bigint": { 1208 | "version": "1.0.2", 1209 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", 1210 | "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", 1211 | "dev": true 1212 | }, 1213 | "is-binary-path": { 1214 | "version": "2.1.0", 1215 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1216 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1217 | "dev": true, 1218 | "requires": { 1219 | "binary-extensions": "^2.0.0" 1220 | } 1221 | }, 1222 | "is-boolean-object": { 1223 | "version": "1.1.1", 1224 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", 1225 | "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", 1226 | "dev": true, 1227 | "requires": { 1228 | "call-bind": "^1.0.2" 1229 | } 1230 | }, 1231 | "is-buffer": { 1232 | "version": "1.1.6", 1233 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 1234 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", 1235 | "dev": true 1236 | }, 1237 | "is-callable": { 1238 | "version": "1.2.3", 1239 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", 1240 | "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", 1241 | "dev": true 1242 | }, 1243 | "is-core-module": { 1244 | "version": "2.5.0", 1245 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", 1246 | "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", 1247 | "dev": true, 1248 | "requires": { 1249 | "has": "^1.0.3" 1250 | } 1251 | }, 1252 | "is-date-object": { 1253 | "version": "1.0.4", 1254 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", 1255 | "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", 1256 | "dev": true 1257 | }, 1258 | "is-docker": { 1259 | "version": "2.2.1", 1260 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", 1261 | "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", 1262 | "dev": true 1263 | }, 1264 | "is-extglob": { 1265 | "version": "2.1.1", 1266 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1267 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1268 | "dev": true 1269 | }, 1270 | "is-generator-function": { 1271 | "version": "1.0.9", 1272 | "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", 1273 | "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==", 1274 | "dev": true 1275 | }, 1276 | "is-glob": { 1277 | "version": "4.0.1", 1278 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 1279 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 1280 | "dev": true, 1281 | "requires": { 1282 | "is-extglob": "^2.1.1" 1283 | } 1284 | }, 1285 | "is-negative-zero": { 1286 | "version": "2.0.1", 1287 | "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", 1288 | "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", 1289 | "dev": true 1290 | }, 1291 | "is-number": { 1292 | "version": "7.0.0", 1293 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1294 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1295 | "dev": true 1296 | }, 1297 | "is-number-object": { 1298 | "version": "1.0.5", 1299 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", 1300 | "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", 1301 | "dev": true 1302 | }, 1303 | "is-regex": { 1304 | "version": "1.1.3", 1305 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", 1306 | "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", 1307 | "dev": true, 1308 | "requires": { 1309 | "call-bind": "^1.0.2", 1310 | "has-symbols": "^1.0.2" 1311 | } 1312 | }, 1313 | "is-string": { 1314 | "version": "1.0.6", 1315 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", 1316 | "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", 1317 | "dev": true 1318 | }, 1319 | "is-symbol": { 1320 | "version": "1.0.4", 1321 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", 1322 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", 1323 | "dev": true, 1324 | "requires": { 1325 | "has-symbols": "^1.0.2" 1326 | } 1327 | }, 1328 | "is-typed-array": { 1329 | "version": "1.1.5", 1330 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", 1331 | "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", 1332 | "dev": true, 1333 | "requires": { 1334 | "available-typed-arrays": "^1.0.2", 1335 | "call-bind": "^1.0.2", 1336 | "es-abstract": "^1.18.0-next.2", 1337 | "foreach": "^2.0.5", 1338 | "has-symbols": "^1.0.1" 1339 | } 1340 | }, 1341 | "is-utf8": { 1342 | "version": "0.2.1", 1343 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 1344 | "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", 1345 | "dev": true 1346 | }, 1347 | "is-wsl": { 1348 | "version": "2.2.0", 1349 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", 1350 | "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", 1351 | "dev": true, 1352 | "requires": { 1353 | "is-docker": "^2.0.0" 1354 | } 1355 | }, 1356 | "isarray": { 1357 | "version": "1.0.0", 1358 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1359 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 1360 | "dev": true 1361 | }, 1362 | "isexe": { 1363 | "version": "2.0.0", 1364 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1365 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1366 | "dev": true 1367 | }, 1368 | "jsonparse": { 1369 | "version": "1.3.1", 1370 | "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", 1371 | "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", 1372 | "dev": true 1373 | }, 1374 | "labeled-stream-splicer": { 1375 | "version": "2.0.2", 1376 | "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", 1377 | "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", 1378 | "dev": true, 1379 | "requires": { 1380 | "inherits": "^2.0.1", 1381 | "stream-splicer": "^2.0.0" 1382 | } 1383 | }, 1384 | "lodash.memoize": { 1385 | "version": "3.0.4", 1386 | "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", 1387 | "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", 1388 | "dev": true 1389 | }, 1390 | "lru-cache": { 1391 | "version": "6.0.0", 1392 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1393 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1394 | "dev": true, 1395 | "requires": { 1396 | "yallist": "^4.0.0" 1397 | } 1398 | }, 1399 | "md5.js": { 1400 | "version": "1.3.5", 1401 | "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", 1402 | "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", 1403 | "dev": true, 1404 | "requires": { 1405 | "hash-base": "^3.0.0", 1406 | "inherits": "^2.0.1", 1407 | "safe-buffer": "^5.1.2" 1408 | } 1409 | }, 1410 | "miller-rabin": { 1411 | "version": "4.0.1", 1412 | "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", 1413 | "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", 1414 | "dev": true, 1415 | "requires": { 1416 | "bn.js": "^4.0.0", 1417 | "brorand": "^1.0.1" 1418 | }, 1419 | "dependencies": { 1420 | "bn.js": { 1421 | "version": "4.12.0", 1422 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 1423 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 1424 | "dev": true 1425 | } 1426 | } 1427 | }, 1428 | "minimalistic-assert": { 1429 | "version": "1.0.1", 1430 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 1431 | "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", 1432 | "dev": true 1433 | }, 1434 | "minimalistic-crypto-utils": { 1435 | "version": "1.0.1", 1436 | "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", 1437 | "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", 1438 | "dev": true 1439 | }, 1440 | "minimatch": { 1441 | "version": "3.0.4", 1442 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1443 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1444 | "dev": true, 1445 | "requires": { 1446 | "brace-expansion": "^1.1.7" 1447 | } 1448 | }, 1449 | "minimist": { 1450 | "version": "1.2.5", 1451 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1452 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1453 | "dev": true 1454 | }, 1455 | "mkdirp-classic": { 1456 | "version": "0.5.3", 1457 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 1458 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", 1459 | "dev": true 1460 | }, 1461 | "module-deps": { 1462 | "version": "6.2.3", 1463 | "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", 1464 | "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", 1465 | "dev": true, 1466 | "requires": { 1467 | "JSONStream": "^1.0.3", 1468 | "browser-resolve": "^2.0.0", 1469 | "cached-path-relative": "^1.0.2", 1470 | "concat-stream": "~1.6.0", 1471 | "defined": "^1.0.0", 1472 | "detective": "^5.2.0", 1473 | "duplexer2": "^0.1.2", 1474 | "inherits": "^2.0.1", 1475 | "parents": "^1.0.0", 1476 | "readable-stream": "^2.0.2", 1477 | "resolve": "^1.4.0", 1478 | "stream-combiner2": "^1.1.1", 1479 | "subarg": "^1.0.0", 1480 | "through2": "^2.0.0", 1481 | "xtend": "^4.0.0" 1482 | }, 1483 | "dependencies": { 1484 | "concat-stream": { 1485 | "version": "1.6.2", 1486 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 1487 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 1488 | "dev": true, 1489 | "requires": { 1490 | "buffer-from": "^1.0.0", 1491 | "inherits": "^2.0.3", 1492 | "readable-stream": "^2.2.2", 1493 | "typedarray": "^0.0.6" 1494 | } 1495 | }, 1496 | "through2": { 1497 | "version": "2.0.5", 1498 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 1499 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 1500 | "dev": true, 1501 | "requires": { 1502 | "readable-stream": "~2.3.6", 1503 | "xtend": "~4.0.1" 1504 | } 1505 | } 1506 | } 1507 | }, 1508 | "node-notifier": { 1509 | "version": "8.0.2", 1510 | "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz", 1511 | "integrity": "sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==", 1512 | "dev": true, 1513 | "requires": { 1514 | "growly": "^1.3.0", 1515 | "is-wsl": "^2.2.0", 1516 | "semver": "^7.3.2", 1517 | "shellwords": "^0.1.1", 1518 | "uuid": "^8.3.0", 1519 | "which": "^2.0.2" 1520 | } 1521 | }, 1522 | "normalize-path": { 1523 | "version": "3.0.0", 1524 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1525 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1526 | "dev": true 1527 | }, 1528 | "object-assign": { 1529 | "version": "4.1.1", 1530 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1531 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 1532 | "dev": true 1533 | }, 1534 | "object-inspect": { 1535 | "version": "1.11.0", 1536 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", 1537 | "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", 1538 | "dev": true 1539 | }, 1540 | "object-keys": { 1541 | "version": "1.1.1", 1542 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1543 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1544 | "dev": true 1545 | }, 1546 | "object.assign": { 1547 | "version": "4.1.2", 1548 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", 1549 | "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", 1550 | "dev": true, 1551 | "requires": { 1552 | "call-bind": "^1.0.0", 1553 | "define-properties": "^1.1.3", 1554 | "has-symbols": "^1.0.1", 1555 | "object-keys": "^1.1.1" 1556 | } 1557 | }, 1558 | "once": { 1559 | "version": "1.4.0", 1560 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1561 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1562 | "dev": true, 1563 | "requires": { 1564 | "wrappy": "1" 1565 | } 1566 | }, 1567 | "os-browserify": { 1568 | "version": "0.3.0", 1569 | "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", 1570 | "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", 1571 | "dev": true 1572 | }, 1573 | "pako": { 1574 | "version": "1.0.11", 1575 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", 1576 | "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", 1577 | "dev": true 1578 | }, 1579 | "parents": { 1580 | "version": "1.0.1", 1581 | "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", 1582 | "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", 1583 | "dev": true, 1584 | "requires": { 1585 | "path-platform": "~0.11.15" 1586 | } 1587 | }, 1588 | "parse-asn1": { 1589 | "version": "5.1.6", 1590 | "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", 1591 | "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", 1592 | "dev": true, 1593 | "requires": { 1594 | "asn1.js": "^5.2.0", 1595 | "browserify-aes": "^1.0.0", 1596 | "evp_bytestokey": "^1.0.0", 1597 | "pbkdf2": "^3.0.3", 1598 | "safe-buffer": "^5.1.1" 1599 | } 1600 | }, 1601 | "parse-json": { 1602 | "version": "2.2.0", 1603 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 1604 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", 1605 | "dev": true, 1606 | "requires": { 1607 | "error-ex": "^1.2.0" 1608 | } 1609 | }, 1610 | "path-browserify": { 1611 | "version": "1.0.1", 1612 | "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", 1613 | "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", 1614 | "dev": true 1615 | }, 1616 | "path-is-absolute": { 1617 | "version": "1.0.1", 1618 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1619 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1620 | "dev": true 1621 | }, 1622 | "path-parse": { 1623 | "version": "1.0.7", 1624 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1625 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1626 | "dev": true 1627 | }, 1628 | "path-platform": { 1629 | "version": "0.11.15", 1630 | "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", 1631 | "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", 1632 | "dev": true 1633 | }, 1634 | "pbkdf2": { 1635 | "version": "3.1.2", 1636 | "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", 1637 | "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", 1638 | "dev": true, 1639 | "requires": { 1640 | "create-hash": "^1.1.2", 1641 | "create-hmac": "^1.1.4", 1642 | "ripemd160": "^2.0.1", 1643 | "safe-buffer": "^5.0.1", 1644 | "sha.js": "^2.4.8" 1645 | } 1646 | }, 1647 | "picomatch": { 1648 | "version": "2.3.0", 1649 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 1650 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 1651 | "dev": true 1652 | }, 1653 | "process": { 1654 | "version": "0.11.10", 1655 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 1656 | "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", 1657 | "dev": true 1658 | }, 1659 | "process-nextick-args": { 1660 | "version": "2.0.1", 1661 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1662 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", 1663 | "dev": true 1664 | }, 1665 | "public-encrypt": { 1666 | "version": "4.0.3", 1667 | "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", 1668 | "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", 1669 | "dev": true, 1670 | "requires": { 1671 | "bn.js": "^4.1.0", 1672 | "browserify-rsa": "^4.0.0", 1673 | "create-hash": "^1.1.0", 1674 | "parse-asn1": "^5.0.0", 1675 | "randombytes": "^2.0.1", 1676 | "safe-buffer": "^5.1.2" 1677 | }, 1678 | "dependencies": { 1679 | "bn.js": { 1680 | "version": "4.12.0", 1681 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 1682 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", 1683 | "dev": true 1684 | } 1685 | } 1686 | }, 1687 | "punycode": { 1688 | "version": "1.4.1", 1689 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1690 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", 1691 | "dev": true 1692 | }, 1693 | "querystring": { 1694 | "version": "0.2.0", 1695 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1696 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", 1697 | "dev": true 1698 | }, 1699 | "querystring-es3": { 1700 | "version": "0.2.1", 1701 | "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", 1702 | "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", 1703 | "dev": true 1704 | }, 1705 | "randombytes": { 1706 | "version": "2.1.0", 1707 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1708 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1709 | "dev": true, 1710 | "requires": { 1711 | "safe-buffer": "^5.1.0" 1712 | } 1713 | }, 1714 | "randomfill": { 1715 | "version": "1.0.4", 1716 | "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", 1717 | "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", 1718 | "dev": true, 1719 | "requires": { 1720 | "randombytes": "^2.0.5", 1721 | "safe-buffer": "^5.1.0" 1722 | } 1723 | }, 1724 | "read-only-stream": { 1725 | "version": "2.0.0", 1726 | "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", 1727 | "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", 1728 | "dev": true, 1729 | "requires": { 1730 | "readable-stream": "^2.0.2" 1731 | } 1732 | }, 1733 | "readable-stream": { 1734 | "version": "2.3.7", 1735 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1736 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1737 | "dev": true, 1738 | "requires": { 1739 | "core-util-is": "~1.0.0", 1740 | "inherits": "~2.0.3", 1741 | "isarray": "~1.0.0", 1742 | "process-nextick-args": "~2.0.0", 1743 | "safe-buffer": "~5.1.1", 1744 | "string_decoder": "~1.1.1", 1745 | "util-deprecate": "~1.0.1" 1746 | }, 1747 | "dependencies": { 1748 | "safe-buffer": { 1749 | "version": "5.1.2", 1750 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1751 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 1752 | "dev": true 1753 | }, 1754 | "string_decoder": { 1755 | "version": "1.1.1", 1756 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1757 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1758 | "dev": true, 1759 | "requires": { 1760 | "safe-buffer": "~5.1.0" 1761 | } 1762 | } 1763 | } 1764 | }, 1765 | "readdirp": { 1766 | "version": "3.6.0", 1767 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1768 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1769 | "dev": true, 1770 | "requires": { 1771 | "picomatch": "^2.2.1" 1772 | } 1773 | }, 1774 | "resolve": { 1775 | "version": "1.20.0", 1776 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 1777 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 1778 | "dev": true, 1779 | "requires": { 1780 | "is-core-module": "^2.2.0", 1781 | "path-parse": "^1.0.6" 1782 | } 1783 | }, 1784 | "ripemd160": { 1785 | "version": "2.0.2", 1786 | "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", 1787 | "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", 1788 | "dev": true, 1789 | "requires": { 1790 | "hash-base": "^3.0.0", 1791 | "inherits": "^2.0.1" 1792 | } 1793 | }, 1794 | "safe-buffer": { 1795 | "version": "5.2.1", 1796 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1797 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1798 | "dev": true 1799 | }, 1800 | "safer-buffer": { 1801 | "version": "2.1.2", 1802 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1803 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1804 | "dev": true 1805 | }, 1806 | "semver": { 1807 | "version": "7.3.5", 1808 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 1809 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 1810 | "dev": true, 1811 | "requires": { 1812 | "lru-cache": "^6.0.0" 1813 | } 1814 | }, 1815 | "sha.js": { 1816 | "version": "2.4.11", 1817 | "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", 1818 | "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", 1819 | "dev": true, 1820 | "requires": { 1821 | "inherits": "^2.0.1", 1822 | "safe-buffer": "^5.0.1" 1823 | } 1824 | }, 1825 | "shasum-object": { 1826 | "version": "1.0.0", 1827 | "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", 1828 | "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", 1829 | "dev": true, 1830 | "requires": { 1831 | "fast-safe-stringify": "^2.0.7" 1832 | } 1833 | }, 1834 | "shell-quote": { 1835 | "version": "1.7.2", 1836 | "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", 1837 | "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", 1838 | "dev": true 1839 | }, 1840 | "shellwords": { 1841 | "version": "0.1.1", 1842 | "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", 1843 | "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", 1844 | "dev": true 1845 | }, 1846 | "side-channel": { 1847 | "version": "1.0.4", 1848 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1849 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1850 | "dev": true, 1851 | "requires": { 1852 | "call-bind": "^1.0.0", 1853 | "get-intrinsic": "^1.0.2", 1854 | "object-inspect": "^1.9.0" 1855 | } 1856 | }, 1857 | "simple-concat": { 1858 | "version": "1.0.1", 1859 | "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", 1860 | "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", 1861 | "dev": true 1862 | }, 1863 | "source-map": { 1864 | "version": "0.5.7", 1865 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1866 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1867 | "dev": true 1868 | }, 1869 | "source-map-support": { 1870 | "version": "0.5.19", 1871 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 1872 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 1873 | "dev": true, 1874 | "requires": { 1875 | "buffer-from": "^1.0.0", 1876 | "source-map": "^0.6.0" 1877 | }, 1878 | "dependencies": { 1879 | "source-map": { 1880 | "version": "0.6.1", 1881 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1882 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1883 | "dev": true 1884 | } 1885 | } 1886 | }, 1887 | "stream-browserify": { 1888 | "version": "3.0.0", 1889 | "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", 1890 | "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", 1891 | "dev": true, 1892 | "requires": { 1893 | "inherits": "~2.0.4", 1894 | "readable-stream": "^3.5.0" 1895 | }, 1896 | "dependencies": { 1897 | "readable-stream": { 1898 | "version": "3.6.0", 1899 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 1900 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 1901 | "dev": true, 1902 | "requires": { 1903 | "inherits": "^2.0.3", 1904 | "string_decoder": "^1.1.1", 1905 | "util-deprecate": "^1.0.1" 1906 | } 1907 | } 1908 | } 1909 | }, 1910 | "stream-combiner2": { 1911 | "version": "1.1.1", 1912 | "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", 1913 | "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", 1914 | "dev": true, 1915 | "requires": { 1916 | "duplexer2": "~0.1.0", 1917 | "readable-stream": "^2.0.2" 1918 | } 1919 | }, 1920 | "stream-http": { 1921 | "version": "3.2.0", 1922 | "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", 1923 | "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", 1924 | "dev": true, 1925 | "requires": { 1926 | "builtin-status-codes": "^3.0.0", 1927 | "inherits": "^2.0.4", 1928 | "readable-stream": "^3.6.0", 1929 | "xtend": "^4.0.2" 1930 | }, 1931 | "dependencies": { 1932 | "readable-stream": { 1933 | "version": "3.6.0", 1934 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 1935 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 1936 | "dev": true, 1937 | "requires": { 1938 | "inherits": "^2.0.3", 1939 | "string_decoder": "^1.1.1", 1940 | "util-deprecate": "^1.0.1" 1941 | } 1942 | } 1943 | } 1944 | }, 1945 | "stream-splicer": { 1946 | "version": "2.0.1", 1947 | "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", 1948 | "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", 1949 | "dev": true, 1950 | "requires": { 1951 | "inherits": "^2.0.1", 1952 | "readable-stream": "^2.0.2" 1953 | } 1954 | }, 1955 | "string.prototype.trimend": { 1956 | "version": "1.0.4", 1957 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", 1958 | "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", 1959 | "dev": true, 1960 | "requires": { 1961 | "call-bind": "^1.0.2", 1962 | "define-properties": "^1.1.3" 1963 | } 1964 | }, 1965 | "string.prototype.trimstart": { 1966 | "version": "1.0.4", 1967 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", 1968 | "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", 1969 | "dev": true, 1970 | "requires": { 1971 | "call-bind": "^1.0.2", 1972 | "define-properties": "^1.1.3" 1973 | } 1974 | }, 1975 | "string_decoder": { 1976 | "version": "1.3.0", 1977 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1978 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1979 | "dev": true, 1980 | "requires": { 1981 | "safe-buffer": "~5.2.0" 1982 | } 1983 | }, 1984 | "strip-bom": { 1985 | "version": "2.0.0", 1986 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 1987 | "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", 1988 | "dev": true, 1989 | "requires": { 1990 | "is-utf8": "^0.2.0" 1991 | } 1992 | }, 1993 | "strip-json-comments": { 1994 | "version": "2.0.1", 1995 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1996 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1997 | "dev": true 1998 | }, 1999 | "subarg": { 2000 | "version": "1.0.0", 2001 | "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", 2002 | "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", 2003 | "dev": true, 2004 | "requires": { 2005 | "minimist": "^1.1.0" 2006 | } 2007 | }, 2008 | "supports-color": { 2009 | "version": "7.2.0", 2010 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2011 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2012 | "dev": true, 2013 | "requires": { 2014 | "has-flag": "^4.0.0" 2015 | } 2016 | }, 2017 | "syntax-error": { 2018 | "version": "1.4.0", 2019 | "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", 2020 | "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", 2021 | "dev": true, 2022 | "requires": { 2023 | "acorn-node": "^1.2.0" 2024 | } 2025 | }, 2026 | "terser": { 2027 | "version": "5.7.1", 2028 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz", 2029 | "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==", 2030 | "dev": true, 2031 | "requires": { 2032 | "commander": "^2.20.0", 2033 | "source-map": "~0.7.2", 2034 | "source-map-support": "~0.5.19" 2035 | }, 2036 | "dependencies": { 2037 | "commander": { 2038 | "version": "2.20.3", 2039 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 2040 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 2041 | "dev": true 2042 | }, 2043 | "source-map": { 2044 | "version": "0.7.3", 2045 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", 2046 | "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", 2047 | "dev": true 2048 | } 2049 | } 2050 | }, 2051 | "through": { 2052 | "version": "2.3.8", 2053 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2054 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 2055 | "dev": true 2056 | }, 2057 | "through2": { 2058 | "version": "4.0.2", 2059 | "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", 2060 | "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", 2061 | "dev": true, 2062 | "requires": { 2063 | "readable-stream": "3" 2064 | }, 2065 | "dependencies": { 2066 | "readable-stream": { 2067 | "version": "3.6.0", 2068 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 2069 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 2070 | "dev": true, 2071 | "requires": { 2072 | "inherits": "^2.0.3", 2073 | "string_decoder": "^1.1.1", 2074 | "util-deprecate": "^1.0.1" 2075 | } 2076 | } 2077 | } 2078 | }, 2079 | "timers-browserify": { 2080 | "version": "1.4.2", 2081 | "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", 2082 | "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", 2083 | "dev": true, 2084 | "requires": { 2085 | "process": "~0.11.0" 2086 | } 2087 | }, 2088 | "to-regex-range": { 2089 | "version": "5.0.1", 2090 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2091 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2092 | "dev": true, 2093 | "requires": { 2094 | "is-number": "^7.0.0" 2095 | } 2096 | }, 2097 | "tsconfig": { 2098 | "version": "5.0.3", 2099 | "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz", 2100 | "integrity": "sha1-X0J45wGACWeo/Dg/0ZZIh48qbjo=", 2101 | "dev": true, 2102 | "requires": { 2103 | "any-promise": "^1.3.0", 2104 | "parse-json": "^2.2.0", 2105 | "strip-bom": "^2.0.0", 2106 | "strip-json-comments": "^2.0.0" 2107 | } 2108 | }, 2109 | "tsify": { 2110 | "version": "5.0.4", 2111 | "resolved": "https://registry.npmjs.org/tsify/-/tsify-5.0.4.tgz", 2112 | "integrity": "sha512-XAZtQ5OMPsJFclkZ9xMZWkSNyMhMxEPsz3D2zu79yoKorH9j/DT4xCloJeXk5+cDhosEibu4bseMVjyPOAyLJA==", 2113 | "dev": true, 2114 | "requires": { 2115 | "convert-source-map": "^1.1.0", 2116 | "fs.realpath": "^1.0.0", 2117 | "object-assign": "^4.1.0", 2118 | "semver": "^6.1.0", 2119 | "through2": "^2.0.0", 2120 | "tsconfig": "^5.0.3" 2121 | }, 2122 | "dependencies": { 2123 | "semver": { 2124 | "version": "6.3.0", 2125 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 2126 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 2127 | "dev": true 2128 | }, 2129 | "through2": { 2130 | "version": "2.0.5", 2131 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", 2132 | "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", 2133 | "dev": true, 2134 | "requires": { 2135 | "readable-stream": "~2.3.6", 2136 | "xtend": "~4.0.1" 2137 | } 2138 | } 2139 | } 2140 | }, 2141 | "tty-browserify": { 2142 | "version": "0.0.1", 2143 | "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", 2144 | "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", 2145 | "dev": true 2146 | }, 2147 | "typedarray": { 2148 | "version": "0.0.6", 2149 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 2150 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 2151 | "dev": true 2152 | }, 2153 | "typescript": { 2154 | "version": "4.3.5", 2155 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", 2156 | "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", 2157 | "dev": true 2158 | }, 2159 | "umd": { 2160 | "version": "3.0.3", 2161 | "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", 2162 | "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", 2163 | "dev": true 2164 | }, 2165 | "unbox-primitive": { 2166 | "version": "1.0.1", 2167 | "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", 2168 | "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", 2169 | "dev": true, 2170 | "requires": { 2171 | "function-bind": "^1.1.1", 2172 | "has-bigints": "^1.0.1", 2173 | "has-symbols": "^1.0.2", 2174 | "which-boxed-primitive": "^1.0.2" 2175 | } 2176 | }, 2177 | "undeclared-identifiers": { 2178 | "version": "1.1.3", 2179 | "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", 2180 | "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", 2181 | "dev": true, 2182 | "requires": { 2183 | "acorn-node": "^1.3.0", 2184 | "dash-ast": "^1.0.0", 2185 | "get-assigned-identifiers": "^1.2.0", 2186 | "simple-concat": "^1.0.0", 2187 | "xtend": "^4.0.1" 2188 | } 2189 | }, 2190 | "url": { 2191 | "version": "0.11.0", 2192 | "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", 2193 | "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", 2194 | "dev": true, 2195 | "requires": { 2196 | "punycode": "1.3.2", 2197 | "querystring": "0.2.0" 2198 | }, 2199 | "dependencies": { 2200 | "punycode": { 2201 | "version": "1.3.2", 2202 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 2203 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", 2204 | "dev": true 2205 | } 2206 | } 2207 | }, 2208 | "util": { 2209 | "version": "0.12.4", 2210 | "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", 2211 | "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", 2212 | "dev": true, 2213 | "requires": { 2214 | "inherits": "^2.0.3", 2215 | "is-arguments": "^1.0.4", 2216 | "is-generator-function": "^1.0.7", 2217 | "is-typed-array": "^1.1.3", 2218 | "safe-buffer": "^5.1.2", 2219 | "which-typed-array": "^1.1.2" 2220 | } 2221 | }, 2222 | "util-deprecate": { 2223 | "version": "1.0.2", 2224 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2225 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 2226 | "dev": true 2227 | }, 2228 | "uuid": { 2229 | "version": "8.3.2", 2230 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 2231 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", 2232 | "dev": true 2233 | }, 2234 | "vm-browserify": { 2235 | "version": "1.1.2", 2236 | "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", 2237 | "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", 2238 | "dev": true 2239 | }, 2240 | "which": { 2241 | "version": "2.0.2", 2242 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2243 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2244 | "dev": true, 2245 | "requires": { 2246 | "isexe": "^2.0.0" 2247 | } 2248 | }, 2249 | "which-boxed-primitive": { 2250 | "version": "1.0.2", 2251 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", 2252 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", 2253 | "dev": true, 2254 | "requires": { 2255 | "is-bigint": "^1.0.1", 2256 | "is-boolean-object": "^1.1.0", 2257 | "is-number-object": "^1.0.4", 2258 | "is-string": "^1.0.5", 2259 | "is-symbol": "^1.0.3" 2260 | } 2261 | }, 2262 | "which-typed-array": { 2263 | "version": "1.1.4", 2264 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", 2265 | "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", 2266 | "dev": true, 2267 | "requires": { 2268 | "available-typed-arrays": "^1.0.2", 2269 | "call-bind": "^1.0.0", 2270 | "es-abstract": "^1.18.0-next.1", 2271 | "foreach": "^2.0.5", 2272 | "function-bind": "^1.1.1", 2273 | "has-symbols": "^1.0.1", 2274 | "is-typed-array": "^1.1.3" 2275 | } 2276 | }, 2277 | "wrappy": { 2278 | "version": "1.0.2", 2279 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2280 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2281 | "dev": true 2282 | }, 2283 | "xtend": { 2284 | "version": "4.0.2", 2285 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 2286 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", 2287 | "dev": true 2288 | }, 2289 | "yallist": { 2290 | "version": "4.0.0", 2291 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2292 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2293 | "dev": true 2294 | } 2295 | } 2296 | } 2297 | --------------------------------------------------------------------------------