查看哪个so在检测frida
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function hook_dlopen() {
Interceptor.attach(Module.findExportByName(
null
,
"android_dlopen_ext"
),
{
onEnter: function (args) {
var pathptr = args[
0
];
if
(pathptr !== undefined && pathptr !=
null
) {
var path = ptr(pathptr).readCString();
console.log(
"load "
+ path);
}
}
}
);
}
|
管他检测啥、直接一把梭
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
|
function replace_str() {
var pt_strstr = Module.findExportByName(
"libc.so"
,
'strstr'
);
var pt_strcmp = Module.findExportByName(
"libc.so"
,
'strcmp'
);
Interceptor.attach(pt_strstr, {
onEnter: function (args) {
var str1 = args[
0
].readCString();
var str2 = args[
1
].readCString();
if
(
str2.indexOf(
"REJECT"
) !== -
1
||
str2.indexOf(
"tmp"
) !== -
1
||
str2.indexOf(
"frida"
) !== -
1
||
str2.indexOf(
"gum-js-loop"
) !== -
1
||
str2.indexOf(
"gmain"
) !== -
1
||
str2.indexOf(
"linjector"
) !== -
1
) {
console.log(
"strstr-->"
, str1, str2);
this
.hook =
true
;
}
}, onLeave: function (retval) {
if
(
this
.hook) {
retval.replace(
0
);
}
}
});
Interceptor.attach(pt_strcmp, {
onEnter: function (args) {
var str1 = args[
0
].readCString();
var str2 = args[
1
].readCString();
if
(
str2.indexOf(
"REJECT"
) !== -
1
||
str2.indexOf(
"tmp"
) !== -
1
||
str2.indexOf(
"frida"
) !== -
1
||
str2.indexOf(
"gum-js-loop"
) !== -
1
||
str2.indexOf(
"gmain"
) !== -
1
||
str2.indexOf(
"linjector"
) !== -
1
) {
//console.log("strcmp-->", str1, str2);
this
.hook =
true
;
}
}, onLeave: function (retval) {
if
(
this
.hook) {
retval.replace(
0
);
}
}
})
}
replace_str();
|
检测的原因是因为安卓系统中,D-Bus通信并不常见,而且不同于在传统Linux系统中广泛使用,安卓系统使用Binder机制来实现进程间通信(IPC),而不是使用D-Bus
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
遍历连接手机所有端口发送D-bus消息,如果返回
"REJECT"
这个特征则认为存在frida-server。
内存中存在frida rpc字符串,认为有frida-server
/*
* Mini-portscan to detect frida-server on any local port.
*/
for
(i = 0 ; i <= 65535 ; i++) {
sock = socket(AF_INET , SOCK_STREAM , 0);
sa.sin_port = htons(i);
if
(connect(sock , (
struct
sockaddr*)&sa ,
sizeof
sa) != -1) {
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME,
"FRIDA DETECTION [1]: Open Port: %d"
, i);
memset
(res, 0 , 7);
// send a D-Bus AUTH message. Expected answer is “REJECT"
send(sock,
"\x00"
, 1, NULL);
send(sock,
"AUTH\r\n"
, 6, NULL);
usleep(100);
if
(ret = recv(sock, res, 6, MSG_DONTWAIT) != -1) {
if
(
strcmp
(res,
"REJECT"
) == 0) {
/* Frida server detected. Do something… */
}
}
}
close(sock);
}
|
检测D-Bus可以通过hook系统库函数,比如strstr、strcmp等等
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
|
function replace_str() {
var pt_strstr = Module.findExportByName(
"libc.so"
,
'strstr'
);
var pt_strcmp = Module.findExportByName(
"libc.so"
,
'strcmp'
);
Interceptor.attach(pt_strstr, {
onEnter: function (args) {
var str1 = args[
0
].readCString();
var str2 = args[
1
].readCString();
if
(str2.indexOf(
"REJECT"
) !== -
1
) {
//console.log("strcmp-->", str1, str2);
this
.hook =
true
;
}
}, onLeave: function (retval) {
if
(
this
.hook) {
retval.replace(
0
);
}
}
});
Interceptor.attach(pt_strcmp, {
onEnter: function (args) {
var str1 = args[
0
].readCString();
var str2 = args[
1
].readCString();
if
(str2.indexOf(
"REJECT"
) !== -
1
) {
//console.log("strcmp-->", str1, str2);
this
.hook =
true
;
}
}, onLeave: function (retval) {
if
(
this
.hook) {
retval.replace(
0
);
}
}
})
}
replace_str();
|
maps文件中存储的是APP运行时加载的依赖
当启动frida后,在maps文件中就会存在 frida-agent-64.so
、frida-agent-32.so
文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
char
line[
512
];
FILE* fp;
fp = fopen(
"/proc/self/maps"
,
"r"
);
if
(fp) {
while
(fgets(line,
512
, fp)) {
if
(strstr(line,
"frida"
)) {
/* Evil library is loaded. Do something… */
}
}
fclose(fp);
} else {
/* Error opening /proc/self/maps. If this happens, something is off. */
}
}
|
绕过
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
|
function replace_str_maps() {
var pt_strstr = Module.findExportByName(
"libc.so"
,
'strstr'
);
var pt_strcmp = Module.findExportByName(
"libc.so"
,
'strcmp'
);
Interceptor.attach(pt_strstr, {
onEnter: function (args) {
var str1 = args[
0
].readCString();
var str2 = args[
1
].readCString();
if
(str2.indexOf(
"REJECT"
) !== -
1
|| str2.indexOf(
"frida"
) !== -
1
) {
this
.hook =
true
;
}
}, onLeave: function (retval) {
if
(
this
.hook) {
retval.replace(
0
);
}
}
});
Interceptor.attach(pt_strcmp, {
onEnter: function (args) {
var str1 = args[
0
].readCString();
var str2 = args[
1
].readCString();
if
(str2.indexOf(
"REJECT"
) !== -
1
|| str2.indexOf(
"frida"
) !== -
1
) {
this
.hook =
true
;
}
}, onLeave: function (retval) {
if
(
this
.hook) {
retval.replace(
0
);
}
}
})
}
replace_str();
|
在 /proc/pid/task
目录下,可以通过查看不同的线程子目录,来获取进程中每个线程的运行时信息。这些信息包括线程的状态、线程的寄存器内容、线程占用的CPU时间、线程的堆栈信息等。通过这些信息,可以实时观察和监控进程中每个线程的运行状态,帮助进行调试、性能优化和问题排查等工作。
/proc/pid/fd
目录的作用在于提供了一种方便的方式来查看进程的文件描述符信息,这对于调试和监控进程非常有用。通过查看文件描述符信息,可以了解进程打开了哪些文件、网络连接等,帮助开发者和系统管理员进行问题排查和分析工作。
打开frida调试后这个task目录下会多出几个线程,检测点在查看这些多出来的线程是否和frida调试相关。
在某些app中就会去读取 /proc/stask/线程ID/status
文件,如果是运行frida产生的,则进行反调试。例如:gmain/gdbus/gum-js-loop/pool-frida
等
绕过
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
|
function replace_str() {
var pt_strstr = Module.findExportByName(
"libc.so"
,
'strstr'
);
var pt_strcmp = Module.findExportByName(
"libc.so"
,
'strcmp'
);
Interceptor.attach(pt_strstr, {
onEnter: function (args) {
var str1 = args[
0
].readCString();
var str2 = args[
1
].readCString();
if
(str2.indexOf(
"tmp"
) !== -
1
||
str2.indexOf(
"frida"
) !== -
1
||
str2.indexOf(
"gum-js-loop"
) !== -
1
||
str2.indexOf(
"gmain"
) !== -
1
||
str2.indexOf(
"gdbus"
) !== -
1
||
str2.indexOf(
"pool-frida"
) !== -
1
||
str2.indexOf(
"linjector"
) !== -
1
) {
//console.log("strcmp-->", str1, str2);
this
.hook =
true
;
}
}, onLeave: function (retval) {
if
(
this
.hook) {
retval.replace(
0
);
}
}
});
Interceptor.attach(pt_strcmp, {
onEnter: function (args) {
var str1 = args[
0
].readCString();
var str2 = args[
1
].readCString();
if
(str2.indexOf(
"tmp"
) !== -
1
||
str2.indexOf(
"frida"
) !== -
1
||
str2.indexOf(
"gum-js-loop"
) !== -
1
||
str2.indexOf(
"gmain"
) !== -
1
||
str2.indexOf(
"gdbus"
) !== -
1
||
str2.indexOf(
"pool-frida"
) !== -
1
||
str2.indexOf(
"linjector"
) !== -
1
) {
//console.log("strcmp-->", str1, str2);
this
.hook =
true
;
}
}, onLeave: function (retval) {
if
(
this
.hook) {
retval.replace(
0
);
}
}
})
}
replace_str();
|
/data/local/tmp/
目录下会生成一个文件夹并且会生成一下带有frida的特征。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
function hook_open(){
var pth
=
Module.findExportByName(null,
"open"
);
Interceptor.attach(ptr(pth),{
onEnter:function(args){
this.filename
=
args[
0
];
console.log("",this.filename.readCString())
if
(this.filename.readCString().indexOf(
".so"
) !
=
-
1
){
args[
0
]
=
ptr(
0
)
}
},onLeave:function(retval){
return
retval;
}
})
}
setImmediate(hook_open)
|
替换一个正常的
更多【 frida常用检测点及其原理--一把梭方案】相关视频教程:www.yxfzedu.com