如果让我读全部的代码,那你真的不如杀了我!所以代码定位很重要,所以在这里就整理一下对于一些android自带的函数进行调用从来进行寻找关机代码和数据!

1、打印堆栈信息

1
2
3
4
5
6
7
8
9
function showStacks() {
console.log(
Java.use("android.util.Log")
.getStackTraceString(
Java.use("java.lang.Throwable").$new()
)
);
}

2、HashMap的put方法

1
2
3
4
5
var hashMap = Java.use("java.util.HashMap");
hashMap.put.implementation = function (a, b) {
console.log("hashMap.put: ", a, b);
return this.put(a, b);
}

frida -UF -l test1.js -o wenzi.txt

image-20231211220001750

3、ArrayList的add、addAll、set方法

这个方法可能调用的很多从而导致系统崩溃,建议配合equals函数进行查询然后输出,然后打印堆栈信息来看函数的运行逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var arrayList = Java.use("java.util.ArrayList");
arrayList.add.overload('java.lang.Object').implementation = function (a) {
if(a.equals("username=1625847503")){
showStacks();
console.log("arrayList.add: ", a);
}
//console.log("arrayList.add: ", a);
return this.add(a);
}
arrayList.add.overload('int', 'java.lang.Object').implementation = function (a, b) {
console.log("arrayList.add: ", a, b);
return this.add(a, b);
}

image-20231211221726087

4、TextUtils的isEmpty方法

1
2
3
4
5
6
7
8
9
var textUtils = Java.use("android.text.TextUtils");
textUtils.isEmpty.implementation = function (a) {

showStacks();
console.log("textUtils.isEmpty: ", a);

//console.log("textUtils.isEmpty: ", a);
return this.isEmpty(a);
}

image-20231211222057058

5、Log

1
2
3
4
5
6
7
8
var log = Java.use("android.util.Log");
log.w.overload('java.lang.String', 'java.lang.String')
.implementation = function (tag, message) {
showStacks();
console.log("log.w: ", tag, message);
return this.w(tag, message);
}

6、Collections的sort方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    var collections = Java.use("java.util.Collections");
collections.sort.overload('java.util.List').implementation = function (a) {
showStacks();
var result = Java.cast(a, Java.use("java.util.ArrayList"));
console.log("collections.sort List: ", result.toString());
return this.sort(a);
}
collections.sort.overload('java.util.List', 'java.util.Comparator')
.implementation = function (a, b) {
showStacks();
var result = Java.cast(a, Java.use("java.util.ArrayList"));
console.log("collections.sort List Comparator: ", result.toString());
return this.sort(a, b);
}

7、JSONObject的put、getString方法等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var jSONObject = Java.use("org.json.JSONObject");
jSONObject.put.overload('java.lang.String', 'java.lang.Object')
.implementation = function (a, b) {
showStacks();
//var result = Java.cast(a, Java.use("java.util.ArrayList"));
console.log("jSONObject.put: ", a, b);
return this.put(a, b);
}
jSONObject.getString.implementation = function (a) {
//showStacks();
//var result = Java.cast(a, Java.use("java.util.ArrayList"));
console.log("jSONObject.getString: ", a);
var result = this.getString(a);
console.log("jSONObject.getString result: ", result);
return result;
}

8、Toast的show方法

1
2
3
4
5
6
7
var toast = Java.use("android.widget.Toast");
toast.show.implementation = function () {
showStacks();
console.log("toast.show: ");
return this.show();
}

9、Base64

1
2
3
4
5
6
7
8
9
var base64 = Java.use("android.util.Base64");
base64.encodeToString.overload('[B', 'int').implementation = function (a, b) {
showStacks();
console.log("base64.encodeToString: ", JSON.stringify(a));
var result = this.encodeToString(a, b);
console.log("base64.encodeToString result: ", result)
return result;
}

10、String的getBytes、isEmpty方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var str = Java.use("java.lang.String");
str.getBytes.overload().implementation = function () {
showStacks();
var result = this.getBytes();
var newStr = str.$new(result);
console.log("str.getBytes result: ", newStr);
return result;
}
str.getBytes.overload('java.lang.String').implementation = function (a) {
showStacks();
var result = this.getBytes(a);
var newStr = str.$new(result, a);
console.log("str.getBytes result: ", newStr);
return result;
}

11、String构造函数的Hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var stringFactory = Java.use("java.lang.StringFactory");
stringFactory.newStringFromString.implementation = function (a) {
showStacks();
var retval = this.newStringFromString(a);
console.log("stringFactory.newStringFromString: ", retval);
return retval;
}
stringFactory.newStringFromChars.overload('[C').implementation = function (a) {
showStacks();
var retval = this.newStringFromChars(a);
console.log("stringFactory.newStringFromChars: ", retval);
return retval;
}

12、StringBuilder、StringBuffer的Hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var sb = Java.use("java.lang.StringBuilder");
sb.toString.implementation = function () {
var retval = this.toString();
if (retval.indexOf("Encrypt") != -1) {
showStacks();
}
console.log("StringBuilder.toString: ", retval);
return retval;
}
var sb = Java.use("java.lang.StringBuffer");
sb.toString.implementation = function () {
var retval = this.toString();
if (retval.indexOf("username") != -1) {
showStacks();
}
console.log("StringBuffer.toString: ", retval);
return retval;
}

13、findViewById 找控件id(打印R$id的属性)

相关控件可以用算法助手进行页面分析和定位,然后通过hook去查询

1
2
3
4
5
6
7
8
9
10
11
var btn_login_id = Java.use("com.dodonew.online.R$id").btn_login.value;
console.log("btn_login_id", btn_login_id);
var appCompatActivity = Java.use("android.support.v7.app.AppCompatActivity");
appCompatActivity.findViewById.implementation = function (a) {
if(a == btn_login_id){
showStacks();
console.log("appCompatActivity.findViewById: ", a);
}
return this.findViewById(a);
}

14、setOnClickListener

1
2
3
4
5
6
7
8
9
10
11
12
13
var btn_login_id = Java.use("com.dodonew.online.R$id").btn_login.value;
console.log("btn_login_id", btn_login_id);

var view = Java.use("android.view.View");
view.setOnClickListener.implementation = function (a) {
if(this.getId() == btn_login_id){
showStacks();
console.log("view.id: " + this.getId());
console.log("view.setOnClickListener is called");
}
return this.setOnClickListener(a);
}

总结:

以上就是一些常见的定位关键代码的方法,软件作者在写这个apk的时候很难避免不去使用这些相关控件的函数,所以可以通过这些方法去打印堆栈信息然后完成对函数的分析!