app常见的libmsaoaidsec.so绕过姿势
最近在学习安卓逆向的时候遇到了libmsaoaidsec.so导致无法frida注入,这里自己收集了一些绕过的方法,如有错误的地方还请各位大佬指正
hook pthread_create
[原创]【安卓逆向】libmsaoaidsec.so反调试及算法逆向案例(爱库存)-Android安全-看雪-安全社区|安全招聘|kanxue.com
用frida先注入一下,可以看到在输出hello之后直接被杀掉

看看是加载了哪个so之后退出
1 2 3 4 5 6 7 8 9 10 11 12 13
| function hook_dlopen() { 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("load " + path); } } } ); }
|
可以猜测是libmsaoaidsec.so这个so存在反frida注入

关于绕过的方法网上很多,大多就是Hook pthread_create函数,然后nop掉他的创建的线程函数
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
| function replace(addr) { Interceptor.replace(addr, new NativeCallback(function () { console.log(`replace ${addr}`) }, 'void', [])); }
function nop_64(addr) { Memory.protect(addr, 4 , 'rwx'); var w = new Arm64Writer(addr); w.putRet(); w.flush(); w.dispose(); }
function hook_pthread_create(soname) { let replaces = []; let pthread_create = Module.findExportByName(null, "pthread_create"); if (!pthread_create) { console.log("pthread_create not found in libc.so"); return; } Interceptor.attach(pthread_create, { onEnter: function (args) { let start_routine = args[2]; let libmsaoaidsec = Process.findModuleByAddress(start_routine); if (libmsaoaidsec && libmsaoaidsec.name === soname) { if (!replaces.includes(start_routine.toString())) { let libmsaoaidsec_addr = libmsaoaidsec.base; let func_offset = start_routine.sub(libmsaoaidsec_addr); console.log("The thread function offset address in libmsaoaidsec.so(" + libmsaoaidsec_addr + ") is " + func_offset); console.log("replace: " + func_offset); } } } }); } setImmediate(hook_pthread_create, "libmsaoaidsec.so")
|
成功命中了,但是nop掉这三处之后app不知道为什么就卡死了

hook clone
这里我又找到了更底层的clone函数创建线程检测方法
[分享]某邦企业壳frida检测绕过-Android安全-看雪-安全社区|安全招聘|kanxue.com

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function hook_clone(soname) { var clone = Module.findExportByName('libc.so', 'clone'); Interceptor.attach(clone, { onEnter: function(args) { if(args[3] != 0){ var addr = args[3].add(96).readPointer() var so_name = Process.findModuleByAddress(addr).name; var so_base = Module.getBaseAddress(so_name); var offset = (addr - so_base); console.log("===============>", so_name, addr,offset, offset.toString(16)); } }, onLeave: function(retval) { } }); }
setImmediate(hook_clone, "libmsaoaidsec.so")
|
这样也能成功获取到线程函数的地址

hook strstr
[原创] frida常用检测点及其原理–一把梭方案-Android安全-看雪-安全社区|安全招聘|kanxue.com
我们不妨进入这几个线程函数,来看看到底做了些什么


可以推测,就是open了一些系统文件,然后fgets获取其信息,再进行ststsr的关键点检测
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
| function hook_pthread_create(soname) { var pt_strstr = Module.findExportByName("libc.so", 'strstr'); var pt_strcmp = Module.findExportByName("libc.so", 'strcmp'); Interceptor.attach(pt_strstr, { onEnter: function (args) { var str1 = args[0].readCString(); var str2 = args[1].readCString(); if ( str2.indexOf("REJECT") !== -1 || str2.indexOf("tmp") !== -1 || str2.indexOf("frida") !== -1 || str2.indexOf("gum-js-loop") !== -1 || str2.indexOf("gmain") !== -1 || str2.indexOf("linjector") !== -1 ) { this.hook = true; } }, onLeave: function (retval) { if (this.hook) { retval.replace(0); } } }); Interceptor.attach(pt_strcmp, { onEnter: function (args) { var str1 = args[0].readCString(); var str2 = args[1].readCString(); if ( str2.indexOf("REJECT") !== -1 || str2.indexOf("tmp") !== -1 || str2.indexOf("frida") !== -1 || str2.indexOf("gum-js-loop") !== -1 || str2.indexOf("gmain") !== -1 || str2.indexOf("linjector") !== -1 ) { this.hook = true; } }, onLeave: function (retval) { if (this.hook) { retval.replace(0); } } }) } setImmediate(hook_pthread_create, "libmsaoaidsec.so")
|
直接对这些检测点的结果返回false, 同样可以绕过

魔改Frida -> rusda
https://github.com/taisuii/rusda
frida和frida-tools使用官方源即可,然后在手机上使用release的rusda-server-android-arm64,无需手动编译
使用rusda后发现居然直接绕过了
