某款三国类题材游戏绕过Frida检测尝试

本文不构成任何技术操作指导或建议,仅供技术交流与学习参考。如发现本文内容存在可能违反法律规定的情况,请立即联系本人删除相关内容。(已对图片中出现的包名和应用名进行处理)

学习一篇文章: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);
// hook_system_property_get();
}
}
}
});
}
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]
代码如下:

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]
定位.init_proc函数,但是发现有平坦化混淆:
[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; // 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,下面框中的代码块就是需要绕过的逻辑
[Pastedimage20250528234902.png]
修改调度器函数如下:
[Pastedimage20250528235132.png]
然后apply patch,重打包app,安装到手机上,看看效果:
[Pastedimage20250528235536.png]
耶!成功!!!