本文不构成任何技术操作指导或建议,仅供技术交流与学习参考。如发现本文内容存在可能违反法律规定的情况,请立即联系本人删除相关内容。(已对图片中出现的包名和应用名进行处理)
学习一篇文章:SO 加载
参考文档:bilibili frida 检测分析绕过
1. 绕过 frida 反调试
学习到在 linux 系统中,so 的加载是 dlopen 函数 (系统级) 在处理,frida 检测往往在 SO 文件中,那我们就要排查是哪个 SO 文件在做这个事情,即查看调用栈。可以通过 hook 这个函数来查看调用栈:
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);
// hook_system_property_get();
}
}
}
});
}
setImmediate(hook_dlopen);
结果如下:
[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 钩子来判断检测点处在哪个阶段。

代码如下:
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 函数前。搜索:

定位.init_proc函数,但是发现有平坦化混淆:

通过 D810 去混淆结果如下:
void init_proc()
{
const char *v0; // x23
__int64 v1; // x0
unsigned int v2; // w0
unsigned __int64 StatusReg; // [xsp+0h] [xbp-870h] BYREF
void *v4; // [xsp+8h] [xbp-868h]
int v6; // [xsp+18h] [xbp-858h]
int v7; // [xsp+1Ch] [xbp-854h]
void *v8; // [xsp+20h] [xbp-850h]
char *v10; // [xsp+30h] [xbp-840h]
FILE *v11; // [xsp+38h] [xbp-838h]
char v12[2000]; // [xsp+40h] [xbp-830h] BYREF
__int64 v13; // [xsp+810h] [xbp-60h]
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,下面框中的代码块就是需要绕过的逻辑

修改调度器函数如下:

然后 apply patch,重打包 app,安装到手机上,看看效果:

耶!成功!!!