首页
社区
课程
招聘
[原创]无壳app的libmsaoaidsec.so frida反调试绕过姿势
发表于: 2025-3-2 13:37 10466

[原创]无壳app的libmsaoaidsec.so frida反调试绕过姿势

2025-3-2 13:37
10466

前言

当前许多应用通过集成 libmsaoaidsec.so 实现针对 Frida 的反调试机制,其核心逻辑是在应用启动过程中,当加载 libmsaoaidsec.so 动态库时,会通过 pthread_create() 创建独立线程,并在该线程内执行反调试函数,主动扫描 Frida 进程、端口、内存特征等痕迹。若检测到 Frida 存在,则触发进程终止或崩溃。
针对这种机制的绕过思路可以从破坏反调试线程的加载或执行入手,文章会对不同的app进行测试,对于使用libmsaoaidsec.so来进行反调试的app,思路是一样的。

定位

通过hook dlopen()函数根据最后加载的so文件来确定程序是在加载哪个so之后退出的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function hook_dlopen(){
    //Android8.0之后加载so通过android_dlopen_ext函数
    var android_dlopen_ext = Module.findExportByName(null,"android_dlopen_ext");
    console.log("addr_android_dlopen_ext",android_dlopen_ext);
    Interceptor.attach(android_dlopen_ext,{
        onEnter:function(args){
            var pathptr = args[0];
            if(pathptr!=null && pathptr != undefined){
                var path = ptr(pathptr).readCString();
                console.log("android_dlopen_ext:",path);
            }
        },
        onLeave:function(retvel){
            console.log("leave!");
        }
    })
}
hook_dlopen()

如下,可以看到加载完libmsaoaidsec.so之后程序就退出了。

接下来我们找一个时机,就是在加载libmsaoaidsec.so的时候打印它里面创建的线程

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
function hook_dlopen(){
    var android_dlopen_ext = Module.findExportByName(null,"android_dlopen_ext");
    console.log("addr_android_dlopen_ext",android_dlopen_ext);
    Interceptor.attach(android_dlopen_ext,{
        onEnter:function(args){
            var pathptr = args[0];
            if(pathptr!=null && pathptr != undefined){
                var path = ptr(pathptr).readCString();
                if(path.indexOf("libmsaoaidsec.so")!=-1){
                    console.log("android_dlopen_ext:",path);
                    hook_pthread()
                }
            }
        },
        onLeave:function(retvel){
             
        }
    })
}
 
function hook_pthread() {
    var pth_create = Module.findExportByName("libc.so", "pthread_create");
    console.log("[pth_create]", pth_create);
    Interceptor.attach(pth_create, {
        onEnter: function (args) {
            var module = Process.findModuleByAddress(args[2]);
            if (module != null) {
                console.log("address", module.name, args[2].sub(module.base));
            }
        },
        onLeave: function (retval) {}
    });
}
 
function main(){
    hook_dlopen()
}
 
main()

如下看打印结果,有兴趣的小伙伴可以利用IDA反编译libmsaoaidsec.so跳转到这些地址去看这些函数都干了什么事情

反调试绕过

现在已经知道了是哪些函数来检测的frida,然后一个很重要的事情就是找到一个时机去把这几个函数都替换掉或者nop掉。
如果去IDA里分析的话,跳转到这几个函数的地址,通过交叉引用查看他们的上一级函数,会发现最终他们都会聚集到init_proc函数里,这是一个初始化函数,在so加载时会自动被调用,而且是so加载过程中最先执行的函数,那么就要找一个比init_proc函数执行更早的一个时机来把检测frida的函数替换掉或者nop掉。
在so文件的链接过程中linker里的call_constructors()函数会触发构造函数,对初始化函数进行注册,然后执行初始化函数,注册的初始化函数会放在.init_array函数列表里,可以在调用call_constructors()函数的时候动态替换so文件里检测frida的函数的地址,使它指向自定义的空函数。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 9
支持
分享
最新回复 (7)
雪    币: 4182
活跃值: (3939)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
能否弄个中邮的分析下
2025-3-3 10:11
0
雪    币: 1472
活跃值: (2098)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
3
写的很nice,Android越来越卷啦????
2025-3-3 17:24
1
雪    币: 84
活跃值: (2168)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不错,现在方子越来月多了
2025-3-6 02:22
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
so 删掉就好了 
2025-3-7 11:17
0
雪    币: 218
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
wx_Lyg_548 so 删掉就好了
兄弟牛逼啊,咋直接删掉就行啊,我研究了半天
20小时前
0
雪    币: 218
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
WMBa0 写的很nice,Android越来越卷啦????
卷死了,现在这个so又进化了,加了检测,反hook
20小时前
0
雪    币: 2583
活跃值: (7108)
能力值: ( LV7,RANK:102 )
在线值:
发帖
回帖
粉丝
8
JNI_ONLOAD,INIT啥的,函数全部干掉试试呢
20小时前
0
游客
登录 | 注册 方可回帖
返回