绕过libmsaoaidsec.so的frida检测
学习文章:https://bbs.kanxue.com/thread-280754.htm
根据大佬的文章,复现一次libmsaoaidsec.so frida检测的绕过
首先是hook一下dlopen,查看程序是在哪里退出的,很显然是 libmsaoaidsec.so

可以看到只执行了 libmsaoaidsec.so 中的onEnter,说明JNI_onload方法还没有执行,执行方法可能就在 init 或者initarray方法内,搜索发现,只有一个 init_proc 的方法。这个时候可以用 strace 来看一下具体在哪个地址退出的。在 init 方法执行之前堵塞程序十秒,进行strace操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| var ishook = false; function hook_dlopen() { Interceptor.attach(Module.findExportByName(null, 'android_dlopen_ext'), { onEnter: function (args) { var pathptr = args[0]; if (pathptr !== undefined && pathptr !== null) { this.path = ptr(pathptr).readCString(); console.log("onEnter: " + this.path); if (this.path.indexOf("libmsaoaidsec.so") != -1) { ishook = true; console.log("进入休眠10s") Java.perform(function (){ var System = Java.use('java.lang.System'); System.currentTimeMillis(); var start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < 10000) {} console.log("休眠结束") }) } } }, onLeave: function (retval) { console.log("onLeave: " + this.path); } }) }
|
1
| strace -e trace=process -i -f -p <PID>
|
输出结果如下,可以看到有 exit_group 执行,再找一下执行的地址 7f46fba008

找到退出之后的新PID
发现 7f46fba008 地址并没有对应的 so ,那么代码很有可能是动态执行的
再执行
1
| strace -e trace=process,memory -i -f -p <PID>
|
mmap申请的内存正好包含下面的退出方法

再去找maps文件发现mmap在libc.so中


hook一下 mmap 方法,打印堆栈
1 2 3 4 5 6 7 8 9 10 11 12 13
| function hook_mmap() { var mmap = Module.findExportByName('libc.so','mmap'); console.log("mmap: ", mmap) Interceptor.attach(mmap, { onEnter: function (args) { console.log("mmap onEnter"); console.log(Thread.backtrace(this.context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join("\n") + '\n'); }, onLeave: function (retval) { console.log("mmap onLeave"); } }); }
|

顺着堆栈开始找 0x17fcc
找到了这个方法

这个方法是创建了一个新线程执行 sub_175F8 函数,返回值是创建结果,我的思路是让其成功创建线程,然后直接 request掉 sub_175F8 方法,而且这个方法是个void方法,不需要考虑返回值的问题


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| var ishook = false; function hook_dlopen() { Interceptor.attach(Module.findExportByName(null, 'android_dlopen_ext'), { onEnter: function (args) { var pathptr = args[0]; if (pathptr !== undefined && pathptr !== null) { this.path = ptr(pathptr).readCString(); console.log("onEnter: " + this.path); if (this.path.indexOf("libmsaoaidsec.so") != -1) { ishook = true; hook_sub_E338(); } } }, onLeave: function (retval) { console.log("onLeave: " + this.path); } }) }
function hook_sub_E338() { var call_constructors = null; Process.getModuleByName("linker64").enumerateSymbols().forEach(function (symbol) { if (symbol.name.indexOf('call_constructors') != -1) { call_constructors = symbol.address; console.log("call constructors: ", call_constructors) } }) Interceptor.attach(call_constructors, { onEnter: function (args) { if (ishook) { var Addr = Module.findBaseAddress('libmsaoaidsec.so'); console.log("Addr: ", Addr) var f1 = Addr.add(0x175F8); Interceptor.replace(f1, new NativeCallback(function () {}, 'void', ['pointer'])) ishook = false; } }, onLeave: function (retval) { } }) }
hook_dlopen();
function hook_mmap() { var mmap = Module.findExportByName('libc.so','mmap'); console.log("mmap: ", mmap) Interceptor.attach(mmap, { onEnter: function (args) { console.log("mmap onEnter"); console.log(Thread.backtrace(this.context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join("\n") + '\n'); }, onLeave: function (retval) { console.log("mmap onLeave"); } }); }
|
也是成功了

再试试hook sub_17FA0 方法,这个有一个int返回值,创建成功是返回0,int类型的返回值就不需要使用jni函数转类型了,直接返回0就行。可以看到依旧可以成功注入

继续往上找进行置空也是可以的,但是越往上越容易出问题,因为可能不止光进行了检测退出这个这个操作。