小黑盒 hook pthread_create 过frida检测
小黑盒抓包的时候,想用自吐加密算法查看用的是什么加密,发现frida做了检测,启动frida脚本就会提示程序终止


目前使用的frida版本是16.0.19,未作任何特征隐藏
常见的frida检测就那么几种,进程和端口检测等,我们先看下是否是在so中进行检测,这里我们尝试通过hook dlopen 函数,查看一下so加载流程,结果发现,加载到 libmsaoaidsec.so
时,frida被终止
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
| Java.perform(function () { var dlopen = Module.findExportByName(null, "dlopen"); var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext"); Interceptor.attach(dlopen, { onEnter: function (args) { var path_ptr = args[0]; var path = ptr(path_ptr).readCString(); console.log("[dlopen:]", path); }, onLeave: function (retval) {
} });
Interceptor.attach(android_dlopen_ext, { onEnter: function (args) { var path_ptr = args[0]; var path = ptr(path_ptr).readCString(); console.log("[dlopen_ext:]", path); }, onLeave: function (retval) {
} }); });
|

由so的加载流程可知,当libmsaoaidsec.so被加载之后,frida进程就被杀掉了,因此监测点在libmsaoaidsec.so中。
如果有了解过so的加载流程,那么就会知道linker会先对so进行加载与链接,然后调用so的.init_proc函数,接着调用.init_array中的函数,最后才是JNI_OnLoad函数,所以我需要先确定检测点大概在哪个函数中。
还有一个思路就是,如果app开启了线程检测,就有一个线程循环检测是否有frida特征,我们也可以直接hook线程函数pthread_create使其返回为空
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function hook_pthread_create() { var pt_create_func = Module.findExportByName("libc.so", 'pthread_create'); Interceptor.attach(pt_create_func, { onEnter: function (args) { var so_name = Process.findModuleByAddress(args[2]).name; if (so_name.indexOf("libmsaoaidsec.so") != -1) { try { Interceptor.replace(args[2], new NativeCallback(function () { console.log('replace success'); return null; }, 'void', ["void"])); } catch (e) { } } }, onLeave: function (retval) { } }) }
hook_pthread_create();
|
可以发现可以成功过掉frida检测,然后再将需要hook的脚本放下面

哔哩哔哩nop掉pthread_create过frida检测
同样使用frida尝试打印so加载流程,发现也是在 libmsaoaidsec.so
加载后程序结束,然后尝试一下过小黑盒的方式看下能否过frida检测

程序没有被终止,但是app也没打开,直接卡死在打开界面,那说明还是在pthread_create函数中进行检测

我们打印一下新线程要执行的函数地址
1 2 3 4 5 6 7 8 9
| function hook_pthread_create(){ ``console.log(``"libmsaoaidsec.so --- "` `+` `Process.findModuleByName(``"libmsaoaidsec.so"``).base) ``Interceptor.attach(Module.findExportByName(``"libc.so"``, ``"pthread_create"``),{ ``onEnter(args){ ``let func_addr ``=` `args[``2``] ``console.log(``"The thread function address is "` `+` `func_addr) ``} ``}) }
|

可以发现这里面有两个线程是libmsaoaidsec.so创建的,对应的函数偏移分别是0x11129和0x10975,这两个函数都检测了frida,绕过的方法很简单,直接nop掉pthread_create
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
| function hook_dlopen(soName = '') { 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(); if (path.indexOf(soName) >= 0) { locate_init() } } } } ); } function locate_init() { let secmodule = null Interceptor.attach(Module.findExportByName(null, "__system_property_get"), { onEnter: function (args) { secmodule = Process.findModuleByName("libmsaoaidsec.so") var name = args[0]; if (name !== undefined && name != null) { name = ptr(name).readCString(); if (name.indexOf("ro.build.version.sdk") >= 0) { bypass() } } } } ); } function hook_pthread_create() { console.log("libmsaoaidsec.so --- " + Process.findModuleByName("libmsaoaidsec.so").base) Interceptor.attach(Module.findExportByName("libc.so", "pthread_create"), { onEnter(args) { let func_addr = args[2] console.log("The thread function address is " + func_addr) } }) } function nop(addr) { Memory.patchCode(ptr(addr), 4, code => { const cw = new ThumbWriter(code, { pc: ptr(addr) }); cw.putNop(); cw.putNop(); cw.flush(); }); } function bypass(){ let module = Process.findModuleByName("libmsaoaidsec.so") nop(module.base.add(0x10AE4)) nop(module.base.add(0x113F8)) } setImmediate(hook_dlopen, "libmsaoaidsec.so")
|
最后呢,也是成功过掉检测
