Frida学习笔记

简单Hook

调用原来的函数

example:

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
public void onClick(View view) {
String obj = editText.getText().toString();
String obj2 = editText2.getText().toString();
if (TextUtils.isEmpty(obj) || TextUtils.isEmpty(obj2)) {
Toast.makeText(LoginActivity.this.mContext, "username or password is empty.", 1).show();
} else if (LoginActivity.a(obj, obj).equals(obj2)) {
LoginActivity.this.startActivity(new Intent(LoginActivity.this.mContext, FridaActivity1.class));
LoginActivity.this.finishActivity(0);
} else {
Toast.makeText(LoginActivity.this.mContext, "Login failed.", 1).show();
}
}
private static String a(byte[] bArr) {
StringBuilder sb = new StringBuilder();
int i = 0;
...
return sb.toString().toLowerCase();
}

/* access modifiers changed from: private */
public static String a(String str, String str2) {
try {
SecretKeySpec secretKeySpec = new SecretKeySpec(str2.getBytes(), "HmacSHA256");
Mac instance = Mac.getInstance("HmacSHA256");
instance.init(secretKeySpec);
return a(instance.doFinal(str.getBytes()));
} catch (Exception e) {
e.printStackTrace();
return BuildConfig.FLAVOR;
}
}
}

可以看到,如果LoginActivity.a这个函数的返回值等于obj2,则通过验证,obj2为输入框的第二栏,所以我们只要看到obj经过运算后的结果就可以了

hook code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

function hook_java(){
Java.perform(function (){
var LoginActivity = Java.use("LoginActivity(类名)");
LoginActivity.a.overload('java.lang.String','java.lang.String').implementation = function (str,str2){ //有两个a,所以要通过指明变量个数指明是哪个a函数
var result = this.a(str,str2); //调用原来的函数
console.log("LoginActivity.a:",str,str2,result);
return result;
};
});
}

function main(){
hook_java();
}

setImmediate(main);

不调用原来的函数

example

1
2
3
4
5
6
7
8
9
10
11
12
13
public void onCheck() {
try {
if (a(b("请输入密码:")).equals("R4jSLLLLLLLLLLOrLE7/5B+Z6fsl65yj6BgC6YWz66gO6g2t65Pk6a+P65NK44NNROl0wNOLLLL=")) {
CheckSuccess();
startActivity(new Intent(this, FridaActivity2.class));
finishActivity(0);
return;
}
super.CheckFailed();
} catch (Exception e) {
e.printStackTrace();
}
}

可以看到,直接修改a的返回值就可以通过check了

hook code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function hook_java(){
Java.perform(function (){
var LoginActivity = Java.use("LoginActivity(类名)");
LoginActivity.a.implementation = function (barr){
return "R4jSLLLLLLLLLLOrLE7/5B+Z6fsl65yj6BgC6YWz66gO6g2t65Pk6a+P65NK44NNROl0wNOLLLL=";
};
});
}

function main(){
hook_java();
}

setImmediate(main);

主动调用函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function hook_java(){
Java.perform(function (){
var LoginActivity = Java.use("LoginActivity(类名)");
LoginActivity.function(); //调用静态函数

Java.choose("当前类路径,类似于com.example...",{
onMatch: function(instance){
instance.funcution; // 调用函数
}
onComplete: function(){

}
});
});
}

function main(){
hook_java();
}

setImmediate(main);

主动设置变量的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function hook_java(){
Java.perform(function (){
var LoginActivity = Java.use("LoginActivity(类名)");
LoginActivity.static_var.value = true; //改变静态变量值

Java.choose("当前类路径,类似于com.example...",{
onMatch: function(instance){
instance.var = true;
instance._var = true; //若变量与函数重名,则前面加下划线
}
onComplete: function(){

}
});
});
}

function main(){
hook_java();
}

setImmediate(main);

HOOK内部类的函数

逻辑代码是这样的:

1
2
3
4
5
6
7
public class FridaActivity extends BaseFridaActivity{
private static class InnerClass{
public static boolean check1(){
return false;
}
}
}

可以看到是private内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function hook_java(){
Java.perform(function (){
var InnerClass = Java.use("FridaActivity$InnerClass"); //$后面跟内部类名
InnerClase.check1.implementation = function(){
return true;
};

});
}

function main(){
hook_java();
}

setImmediate(main);

但是如果有多个check()函数的话,这样太不方便了,有没有可以获取所有函数的方法呢,答案是肯定的

getDeclareMethods() 可以帮助我们获取所有函数的方法

然后再进行字符串截取拼接就可以了

HOOK 动态dex

example如下:

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
public AbstractC0000CheckInterface getDynamicDexCheck() {
if (this.DynamicDexCheck == null) {
loaddex();
}
return this.DynamicDexCheck;
}

private void loaddex() {
File cacheDir = getCacheDir();
if (!cacheDir.exists()) {
cacheDir.mkdir();
}
String str = cacheDir.getAbsolutePath() + File.separator + "DynamicPlugin.dex";
File file = new File(str);
try {
if (!file.exists()) {
file.createNewFile();
copyFiles(this, "DynamicPlugin.dex", file);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
this.DynamicDexCheck = (AbstractC0000CheckInterface) new DexClassLoader(str, cacheDir.getAbsolutePath(), null, getClassLoader()).loadClass("com.example.androiddemo.Dynamic.DynamicCheck").newInstance();
if (this.DynamicDexCheck == null) {
Toast.makeText(this, "loaddex Failed!", 1).show();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}

枚举加载的类

1
2
3
4
5
6
7
Java.enumerateClassLoaders({
onMatch: function(loader){

},onComplete: function(){

}
});

frida是不能Java use接口的,要先找到接口实现的名字

1
2
3
4
5
6
7
Java.choose("com.example.androiddemo.Activity.FridaActivity5", {
onMatch: function (instance) {
console.log(instance.getDynamicDexCheck().$className); //$可以显示名字
}, onComplete: function () {

}
});

找到名字就可以hook这个实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
if (loader.findClass("com.example.androiddemo.Dynamic.DynamicCheck")) {
console.log(loader);
Java.classFactory.loader = loader; //切换classloader
}
} catch (error) {

}

}, onComplete: function () {

}
});

然后进行hook check函数

1
2
3
4
5
6
var DynamicCheck = Java.use("com.example.androiddemo.Dynamic.DynamicCheck");
console.log(DynamicCheck);
DynamicCheck.check.implementation = function () {
console.log("DynamicCheck.check");
return true;
}

HOOK 不同class的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function hook_FridaActivity6() {
Java.perform(function () {
var Frida6Class0 = Java.use("com.example.androiddemo.Activity.Frida6.Frida6Class0");
Frida6Class0.check.implementation = function () {
return true;
};
var Frida6Class1 = Java.use("com.example.androiddemo.Activity.Frida6.Frida6Class1");
Frida6Class1.check.implementation = function () {
return true;
};
var Frida6Class2 = Java.use("com.example.androiddemo.Activity.Frida6.Frida6Class2");
Frida6Class2.check.implementation = function () {
return true;
};
});
}