某瓣app frida检测绕过

1、查看哪个so文件导致frida hook失效

直接运行一下frida脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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();
console.log("android_dlopen_ext:",path);
}
},
onLeave:function(retvel){

}
})
}

function main(){
hook_dlopen()
}

main()

打印到libmsaoaidsec.so文件的时候frida进程退出了,那么就可以锁定到libmsaoaidsec.so文件

2、查看对应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_patch() {
var patch = Module.findExportByName("libc.so", "pthread_create");
console.log("[pth_create]", patch);
Interceptor.attach(patch, {
onEnter: function (args) {
var module = Process.findModuleByAddress(args[2]);
if (module != null) {
console.log("开启线程-->", module.name, args[2].sub(module.base));
}
},
onLeave: function (retval) {}
});
}

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_patch()
}
}
},
onLeave:function(retvel){
//console.log("leave!");
}
})
}

function main(){
hook_dlopen()
}

main()

输出结果:

1
2
3
开启线程--> libmsaoaidsec.so 0x1c544
开启线程--> libmsaoaidsec.so 0x1b8d4
开启线程--> libmsaoaidsec.so 0x26e5c

3、ida分析对应so文件的方法


打开后搜索上方hook方法的地址值(1c544、1b8d4、26e5c)

搜索到1b8d4的时候发现有一个while死循环代码里面套了一个usleep方法,这里很可能是将frida强制退出的代码,我们查看哪里调用了该代码

将光标停留在方法名上按下键盘上的x键查看引用位置
通过一层层的网上找,发现调用的位置顺序是

1
init_proc -> 1BEC4 -> 1B924 -> 1B8D4

init_proc方法的作用是初始化进程,那么init_proc是起点,那么我们只需要把1B924这个方法hook掉,那么1B8D4方法就不会执行

4、hook对应方法

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
function hook_constructors() {
var linker64_base_addr = Module.getBaseAddress("linker64")
console.log("linker64_base_addr", linker64_base_addr)
var call_constructors_func_off = 0x50C00 // 需要改成你们自己的
var call_constructors_func_addr = linker64_base_addr.add(call_constructors_func_off)
var listener = Interceptor.attach(call_constructors_func_addr, {
onEnter: function (args) {
console.log("call_constructors -> enter")
var module = Process.findModuleByName("libmsaoaidsec.so")
if (module != null) {
Interceptor.replace(module.base.add(0x1B924), new NativeCallback(function () {
console.log("替换成功")
}, "void", []))
listener.detach()
}
},
})
}

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_constructors()
}
}
},
onLeave:function(retvel){

}
})
}

function main(){
hook_dlopen()
}

main()

在以上的hook文件中hook_constructors方法中的call_constructors_func_off变量需要替换成我们自己手机的链接库地址
该文件的位置在 /system/bin/linker64目录下,将该文件push到本地计算机,通过ida查找对应的地址值
用ida打开刚才的linker64文件后直接搜索constructors

这里获取到我们的安卓链接库的地址为0x4A174,运行以上脚本就可以发现frida可以正常hook了

5、补充

我们也可以把直接将打印出来的所有方法全部进行hook绕过(1c544、1b8d4、26e5c)

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
50
51
52
53
54
55
56
57
58
59
60
61
62
function hook_call_constructors() {
let linker = null;
if (Process.pointerSize === 4) {
linker = Process.findModuleByName("linker");
} else {
linker = Process.findModuleByName("linker64");
}
let call_constructors_addr, get_soname
let symbols = linker.enumerateSymbols();
for (let index = 0; index < symbols.length; index++) {
let symbol = symbols[index];
if (symbol.name === "__dl__ZN6soinfo17call_constructorsEv") {
call_constructors_addr = symbol.address;
} else if (symbol.name === "__dl__ZNK6soinfo10get_sonameEv") {
get_soname = new NativeFunction(symbol.address, "pointer", ["pointer"]);
}
}
console.log(call_constructors_addr)
var listener = Interceptor.attach(call_constructors_addr, {
onEnter: function (args) {
console.log("hooked call_constructors")
var module = Process.findModuleByName("libmsaoaidsec.so")
if (module != null) {
nop_addr(module.base.add(0x1c544))
console.log("0x1c544:替换成功")
nop_addr(module.base.add(0x1b8d4))
console.log("0x1b8d4:替换成功")
nop_addr(module.base.add(0x26e5c))
console.log("0x26e5c:替换成功")
listener.detach()
}

},
})
}

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();
if(path.indexOf("libmsaoaidsec.so")!=-1){
console.log("android_dlopen_ext:",path);
hook_call_constructors()
}
}
},
onLeave:function(retvel){
//console.log("leave!");
}
})
}

function main(){
hook_dlopen()
}

main()