🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### frida注入hook脚本脱壳 脚本地址:[https://github.com/r0ysue/frida\_dump](https://github.com/r0ysue/frida_dump) #### 使用dump_so ``` frida -U packagename -l dump_so.js ``` ``` ____ / _ | Frida 12.4.8 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit . . . . . . . . More info at http://www.frida.re/docs/home/ [LGE AOSP on HammerHead::packagename]-> dump_so("name.so") [name]: name.so [base]: 0x99adf000 [size]: 0x2d4000 [path]: /data/app/packagename-2/lib/arm/name.so [dump]: /data/user/0/packagename/files/name.so_0x99adf000_0x2d4000.so undefined [LGE AOSP on HammerHead::packagename]-> ``` #### 使用dump_dex ``` frida -U --no-pause -f packagename -l dump_dex.js ``` ``` / _ | Frida 12.4.8 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit . . . . . . . . More info at http://www.frida.re/docs/home/ Spawned `packagename`. Resuming main thread! [Google Pixel XL::packagename]-> [dlopen:] libart.so _ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE 0x7ac6dc4f74 [DefineClass:] 0x7ac6dc4f74 [dump dex]: /data/data/packagename/files/7aab800000_8341c4.dex ``` #### 文件位置 dump 后的文件一般在手机里面 ![](https://img.kancloud.cn/e7/0c/e70c1c868fb2c2709531d1db40e09c19_335x351.png) #### 脚本代码 dump_dex.js ``` function get_self_process_name() { var openPtr = Module.getExportByName('libc.so', 'open'); var open = new NativeFunction(openPtr, 'int', ['pointer', 'int']); var readPtr = Module.getExportByName("libc.so", "read"); var read = new NativeFunction(readPtr, "int", ["int", "pointer", "int"]); var closePtr = Module.getExportByName('libc.so', 'close'); var close = new NativeFunction(closePtr, 'int', ['int']); var path = Memory.allocUtf8String("/proc/self/cmdline"); var fd = open(path, 0); if (fd != -1) { var buffer = Memory.alloc(0x1000); var result = read(fd, buffer, 0x1000); close(fd); result = ptr(buffer).readCString(); return result; } return "-1"; } function dump_dex() { var libart = Process.findModuleByName("libart.so"); var addr_DefineClass = null; var symbols = libart.enumerateSymbols(); for (var index = 0; index < symbols.length; index++) { var symbol = symbols[index]; var symbol_name = symbol.name; //这个DefineClass的函数签名是Android9的 //_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE if (symbol_name.indexOf("ClassLinker") >= 0 && symbol_name.indexOf("DefineClass") >= 0 && symbol_name.indexOf("Thread") >= 0 && symbol_name.indexOf("DexFile") >= 0 ) { console.log(symbol_name, symbol.address); addr_DefineClass = symbol.address; } } var dex_maps = {}; console.log("[DefineClass:]", addr_DefineClass); if (addr_DefineClass) { Interceptor.attach(addr_DefineClass, { onEnter: function (args) { var dex_file = args[5]; //ptr(dex_file).add(Process.pointerSize) is "const uint8_t* const begin_;" //ptr(dex_file).add(Process.pointerSize + Process.pointerSize) is "const size_t size_;" var base = ptr(dex_file).add(Process.pointerSize).readPointer(); var size = ptr(dex_file).add(Process.pointerSize + Process.pointerSize).readUInt(); if (dex_maps[base] == undefined) { dex_maps[base] = size; var magic = ptr(base).readCString(); if (magic.indexOf("dex") == 0) { var process_name = get_self_process_name(); if (process_name != "-1") { var dex_path = "/data/data/" + process_name + "/files/" + base.toString(16) + "_" + size.toString(16) + ".dex"; console.log("[find dex]:", dex_path); var fd = new File(dex_path, "wb"); if (fd && fd != null) { var dex_buffer = ptr(base).readByteArray(size); fd.write(dex_buffer); fd.flush(); fd.close(); console.log("[dump dex]:", dex_path); } } } } }, onLeave: function (retval) { } }); } } var is_hook_libart = false; function hook_dlopen() { Interceptor.attach(Module.findExportByName(null, "dlopen"), { onEnter: function (args) { var pathptr = args[0]; if (pathptr !== undefined && pathptr != null) { var path = ptr(pathptr).readCString(); //console.log("dlopen:", path); if (path.indexOf("libart.so") >= 0) { this.can_hook_libart = true; console.log("[dlopen:]", path); } } }, onLeave: function (retval) { if (this.can_hook_libart && !is_hook_libart) { dump_dex(); is_hook_libart = true; } } }) Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), { onEnter: function (args) { var pathptr = args[0]; if (pathptr !== undefined && pathptr != null) { var path = ptr(pathptr).readCString(); //console.log("android_dlopen_ext:", path); if (path.indexOf("libart.so") >= 0) { this.can_hook_libart = true; console.log("[android_dlopen_ext:]", path); } } }, onLeave: function (retval) { if (this.can_hook_libart && !is_hook_libart) { dump_dex(); is_hook_libart = true; } } }); } setImmediate(hook_dlopen); ``` dump_so.js ``` function dump_so(so_name) { Java.perform(function () { var currentApplication = Java.use("android.app.ActivityThread").currentApplication(); var dir = currentApplication.getApplicationContext().getFilesDir().getPath(); var libso = Process.getModuleByName(so_name); console.log("[name]:", libso.name); console.log("[base]:", libso.base); console.log("[size]:", ptr(libso.size)); console.log("[path]:", libso.path); var file_path = dir + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so"; var file_handle = new File(file_path, "wb"); if (file_handle && file_handle != null) { Memory.protect(ptr(libso.base), libso.size, 'rwx'); var libso_buffer = ptr(libso.base).readByteArray(libso.size); file_handle.write(libso_buffer); file_handle.flush(); file_handle.close(); console.log("[dump]:", file_path); } }); } ```