frida常用大全

hook 检测函数

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);
}
}
}
);
}

查看所有android_dlopen_ext打开的动态库

修改寄存器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var soAddr = Module.findBaseAddress("lib.so");
var funcAddr = soAddr.add(0x121974)

Interceptor.attach(funcAddr,{
onEnter: function(args){

console.log('onEnter arg[]: ',this.context.x0) // 32位是r寄存器 this.context.r0

console.log('onEnter arg[]: ',hexdump(this.context.x0)) // 内存才可以 hexdump

// console.log('onEnter arg[]: ',args[0])
// this.arg0 = args[0]
},
onLeave: function(retval){
console.log('onLeave arg[]: ')
console.log('onLeave result: ',retval)
}
});

Hook webview 页面

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//frida -U "<ProcessName>" -l Android_WebView_inspector.js

function Android_WebView_inspector() {

//实例化一个对象
var WebView = Java.use('android.webkit.WebView');
//重写WebView类的重载方法,因为setWebContentsDebuggingEnabled不是静态方法,所以需要一个对象来调用这个方法
WebView.$init.overload('android.content.Context').implementation = function (a) {
console.log("WebView.$init is called!1");
var retval = this.$init(a);
this.setWebContentsDebuggingEnabled(true);
return retval;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet').implementation = function (a, b) {
console.log("WebView.$init is called!2");
var retval = this.$init(a, b);
this.setWebContentsDebuggingEnabled(true);
return retval;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int').implementation = function (a, b, c) {
console.log("WebView.$init is called!3");
var retval = this.$init(a, b, c);
this.setWebContentsDebuggingEnabled(true);
return retval;
}
//始终设置为true,打开调试
WebView.setWebContentsDebuggingEnabled.implementation = function () {
this.setWebContentsDebuggingEnabled(true);
console.log("setWebContentsDebuggingEnabled is called!");

}
}


// replace_str_maps();


// setTimeout(Android_WebView_inspector, 3000);

// console.log("脚本加载成功");

console.log("脚本加载成功");
function main() {
Java.perform(function () {
var WebView = Java.use('android.webkit.WebView');
WebView.$init.overload('android.content.Context').implementation = function (a) {
var result = this.$init(a);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet').implementation = function (a, b) {
var result = this.$init(a, b);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int').implementation = function (a, b, c) {
var result = this.$init(a, b, c);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'int').implementation = function (a, b, c, d) {
var result = this.$init(a, b, c, d);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'boolean').implementation = function (a, b, c, d) {
var result = this.$init(a, b, c, d);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'java.util.Map', 'boolean').implementation = function (a, b, c, d, e) {
var result = this.$init(a, b, c, d, e);
this.setWebContentsDebuggingEnabled(true);
return result;
}
WebView.$init.overload('android.content.Context', 'android.util.AttributeSet', 'int', 'int', 'java.util.Map', 'boolean').implementation = function (a, b, c, d, e, f) {
var result = this.$init(a, b, c, d, e, f);
this.setWebContentsDebuggingEnabled(true);
return result;
}
});
}
setImmediate(main);


// setTimeout(main, 2000);

function main2() {
Java.perform(function () {

// Hook WebView 的 loadUrl 方法 (经测试全部用的是这个)
// var WebView = Java.use('android.webkit.WebView');
// WebView.loadUrl.overload('java.lang.String').implementation = function(url) {
// console.log("WebView loading URL: " + url);
// // 打印栈追踪 (调用链)
// var stackTrace = Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Exception').$new());
// console.log("调用链: " + stackTrace);
// // 继续执行原来的 loadUrl 方法
// return this.loadUrl(url);
// };

// Hook WebView 的 loadUrl 方法 (经测试全部用的是这个)
var WebView = Java.use('android.webkit.WebView');
WebView.setWebContentsDebuggingEnabled.overload("boolean").implementation = function (s) {
console.log("强制开启webview调试");
this.setWebContentsDebuggingEnabled(true)
}
WebView.loadUrl.overload('java.lang.String').implementation = function (url) {
console.log("WebView loading URL: " + url);
if (url.startsWith("javascript:") && url.includes("window.requestConfig")) {
// 提取Base64字符串
var base64EncodedString = url.match(/"([^"]+)"/)[1]; // 匹配出Base64字符串
// 解码Base64
var decodedBase64 = Java.use('android.util.Base64').decode(base64EncodedString, 0);
var decodedString = Java.use('java.lang.String').$new(decodedBase64, "UTF-8");
// 使用Java的replace方法进行转义字符替换
decodedString = decodedString.replace(Java.use('java.lang.String').$new("\\u0026"), Java.use('java.lang.String').$new("&"));
decodedString = decodedString.replace(Java.use('java.lang.String').$new("\\u003d"), Java.use('java.lang.String').$new("="));
console.log("解码 Base64: " + decodedString)
}
// 打印栈追踪 (调用链)
var stackTrace = Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Exception').$new());
console.log("调用链: " + stackTrace);
// 继续执行原来的 loadUrl 方法
return this.loadUrl(url);
};

// 解码Unicode字符串的函数
function decodeUnicode(str) {
return str.replace(/\\u[\dA-Fa-f]{4}/g, function (match) {
return String.fromCharCode(parseInt(match.replace("\\u", ""), 16));
});
}


// Hook WebViewClient 的 onPageFinished 方法
var WebViewClient = Java.use('android.webkit.WebViewClient');
WebViewClient.onPageFinished.overload('android.webkit.WebView', 'java.lang.String').implementation = function (view, url) {
console.log("WebView finished loading URL: " + url);
// 可以在这里处理更多逻辑,如获取网页内容
return this.onPageFinished(view, url);
};

// Hook WebView 的 WebResourceRequest
var WebResourceRequest = Java.use('android.webkit.WebResourceRequest');
var WebViewClient2 = Java.use('android.webkit.WebViewClient');

WebViewClient2.shouldInterceptRequest.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest').implementation = function (view, request) {
var requestUrl = request.getUrl().toString();
console.log("Intercepting WebResourceRequest: " + requestUrl);

// 在这里可以执行任何自定义逻辑,如修改请求
return this.shouldInterceptRequest(view, request);
};
});
}


// setTimeout(main2, 3000);

hook So层的 newStringUTF8

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

function hook_NewStringUTF() {
var artModule = Process.findModuleByName("libart.so");
var symbols = artModule.enumerateSymbols();
var newStringUTF = null;
for (let i = 0; i < symbols.length; i++) {
let symbol = symbols[i];
if (symbol.name.indexOf("NewStringUTF") !== -1) {
console.log(symbol.name);
newStringUTF = symbol.address;
}
}
if (newStringUTF) {
Interceptor.attach(newStringUTF, {
onEnter: function (args) {
let string = args[1].readCString()
console.log("[字符串]:", string);
console.log("[调用栈]:",Thread.backtrace(this.context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join('\n') + '\n');
}, onLeave: function (retval) {
}
})
} else {
console.log("没有这个函数")
}
}

hook具体函数地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function hook_dlsym(){
// 获取dlsym函数的地址
let dlsymAddr = Module.findExportByName("libdl.so","dlsym");
console.log(dlsymAddr);
// hook dlsym
Interceptor.attach(dlsymAddr,{
onEnter:function(args){
this.args1 = args[1];
},
onLeave:function(retval){
let md= Process.findModuleByAddress(retval);
if(md==null)return;
console.log("函数:"+this.args1.readCString(),"模块:"+md.name,"地址:"+retval,"偏移:"+retval.sub(md.base));
}
})
}

HashMap或转Json

方法一:直接打印:

1
2
3
4
var HashMap = Java.use('java.util.HashMap');
console.log("map:" + Java.cast(map, HashMap).toString());

// 输出展示:map -> {onlyCanExchange=0, pageSize=5, pageNum=1}

方法二:借助Gson转Json打印(推荐)

1
2
3
4
var Gson = Java.use('com.google.gson.Gson').$new();
console.log("map -> " + Gson.toJsonTree(map).getAsJsonObject());

// 输出展示:map -> {"onlyCanExchange":0,"pageSize":"5","pageNum":"1"}