本文不构成任何技术操作指导或建议,仅供技术交流与学习参考。如发现本文内容存在可能违反法律规定的情况,请立即联系本人删除相关内容。(已对图片中出现的包名和应用名进行处理)
学习一篇文章:SO加载
参考文档:bilibili frida检测分析绕过
1.绕过frida反调试
学习到在linux系统中,so的加载是dlopen函数(系统级)在处理,frida检测往往在SO文件中,那我们就要排查是哪个SO文件在做这个事情,即查看调用栈。可以通过hook这个函数来查看调用栈:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function hook_dlopen(soName = '') { Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), { onEnter: function(args) { var pathptr = args[0]; if (pathptr) { var path = ptr(pathptr).readCString(); console.log("Loading: " + path); if (path.indexOf(soName) >= 0) { console.log("Already loading: " + soName); } } } }); } setImmediate(hook_dlopen);
|
结果如下:
1 2 3 4 5 6 7 8
| [ONEPLUS A6010::com.xxxxxxxxxx ]-> Loading: /system/framework/oat/arm64/embryo.odex Loading: /system/framework/oat/arm64/org.apache.http.legacy.boot.odex Loading: /data/app/com.xxxxxxxxxx-YbqwF-6pNu60XJkbEOJhjg==/oat/arm64/base.odex Loading: /data/app/com.xxxxxxxxxx-YbqwF-6pNu60XJkbEOJhjg==/lib/arm64/libnicai.so Loading: /data/app/com.xxxxxxxxxx-YbqwF-6pNu60XJkbEOJhjg==/lib/arm64/libmsaoaidsec.so Already loading: libmsaoaidsec.so Process terminated [ONEPLUS A6010::com.xxxxxxxxxx ]->
|
frida检测点就应该在libmsaoaidsec.so中,继续缩小范围,从下面这张图,我们可以了解到,在加载so时,在jni_onload()函数之前会先加载init()函数,我们可以通过设置jni钩子来判断检测点处在哪个阶段。
![[Pastedimage20250529000502.png]](/post/cd471d9e/Pastedimage20250529000502.png)
代码如下:
1 2 3 4 5 6 7 8
| function hook_JNI_OnLoad(){ let module = Process.findModuleByName("libmsaoaidsec.so") Interceptor.attach(module.base.add(0x13a4c + 1), { onEnter(args){ console.log("JNI_OnLoad") } }) }
|
hook后,没有任何回显,frida被毙掉,那么监测点就在init函数后,jni函数前。搜索:
![[Pastedimage20250529001012.png]](/post/cd471d9e/Pastedimage20250529001012.png)
定位.init_proc函数,但是发现有平坦化混淆:
![[Pastedimage20250528182508.png]](/post/cd471d9e/Pastedimage20250528182508.png)
通过D810去混淆结果如下:
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
| void init_proc() { const char *v0; __int64 v1; unsigned int v2; unsigned __int64 StatusReg; void *v4; int v6; int v7; void *v8; char *v10; FILE *v11; char v12[2000]; __int64 v13;
StatusReg = _ReadStatusReg(ARM64_SYSREG(3, 3, 0xD, 0, 2)); v13 = *(StatusReg + 40); v4 = &StatusReg + -0xFA; *off_47FB8 = sub_123F0(); sub_12550(); sub_12440(); if ( *off_47FB8 > 23 ) *off_47ED8 = 1; if ( (sub_25A48() & 1) == 0 ) { v10 = v12; memset(v10, 0, 0x7D0uLL); v2 = getpid(); _sprintf_chk(v12, 0LL, 2000LL, "/proc/%d/cmdline", v2); v11 = fopen(v12, "r"); if ( v11 ) { v8 = v4; memset(v4, 0, 0x7D0uLL); v0 = v4; fscanf(v11, "%s", v4); fclose(v11); if ( !strchr(v0, 58) ) sub_1BEC4(); } v1 = sub_13728(); sub_23AD4(v1); v6 = sub_C830(); if ( v6 != 1 || (v7 = sub_95C8()) != 0 ) sub_9150(); } }
|
主要是绕过if ( (sub_25A48() & 1) == 0 )分支,加上这段被混淆了,要善用Graph,下面框中的代码块就是需要绕过的逻辑
![[Pastedimage20250528234902.png]](/post/cd471d9e/Pastedimage20250528234902.png)
修改调度器函数如下:
![[Pastedimage20250528235132.png]](/post/cd471d9e/Pastedimage20250528235132.png)
然后apply patch,重打包app,安装到手机上,看看效果:
![[Pastedimage20250528235536.png]](/post/cd471d9e/Pastedimage20250528235536.png)
耶!成功!!!