some frida scripts

frida script status
hook java Android Api
hook new StringBuilder
modify func retVal
traceback
hook native func
hook win dll

hook java android api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// frida -U -f com.example.frida_java_anti_frida -l .\hook_java_android_api.js
if (Java.available) {
Java.perform(function () {
var AppCompatActivity = Java.use(
"androidx.appcompat.app.AppCompatActivity"
);
var setSupportActionBar = AppCompatActivity.setSupportActionBar;
setSupportActionBar.implementation = function (arg) {
var retVal = this.setSupportActionBar(arg);
console.log("hook!");
return retVal;
};
});
} else console.log("Java not available");

hook new SrtingBuilder

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
// 检查java runtime可用性
if (Java.available) {
console.log("Java available");

Java.perform(function () {
console.log("boot java perform function");
var MainActivity = Java.use(
"com.example.frida_java_test_3.MainActivity"
);
console.log("load class");

Java.use("java.lang.StringBuilder").$init.overload(
"java.lang.String"
).implementation = function (args) {
// init?new?
const StringBuilder = Java.use("java.lang.StringBuilder");
var arg = args;
var result = this.$new(args);
console.log("the StringBuilder arg :", arg);
if (arg == "hack me") {
console.log("check magic str!");
console.log("hack it!");
result = this.$new("hacked!");
args = result;
}
console.log("ret:", result);
result = this.$init(args);
return;
// var a
//return a
};

MainActivity.getOne.implementation = function () {
var retVal = this.getOne();
console.log(retVal);
return retVal.toString();
};
});
} else console.log("Java not available");

modify func retVal

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
// 检查java runtime可用性
if (Java.available) {
console.log("Java available");
// **app's class loader?
// **Ensures that the current thread is attached to the VM and calls fn. (This isn't necessary in callbacks from Java.)?
// 如果无需等待class loader的初始化,则调用performNow
Java.perform(function () {
console.log("boot java perform function");
// 获取MainActivity类
// 可以获取其它类的实例
// Uses the app's class loader, but you may access classes on other loaders by calling Java.ClassFactory.get()
var MainActivity = Java.use(
"com.example.frida_java_test_1.MainActivity"
);
// 获取MainActivity的getOne实例(实际上是一个函数)
var getOne = MainActivity.getOne;
// 重写实现

getOne.implementation = function () {
// 先正常地走原函数的逻辑并获取返回值.
var result = this.getOne();
// 打印返回值并篡改。
console.log("Get return value", ",value =>", result);
result = "Hacked!";
console.log("It will be hooked to ", result);
// 返回我们所篡改的返回值
return result;
};
});
} else console.log("Java not available");

traceback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 打印onCreate时的调用堆栈
if (Java.available) {
Java.perform(function () {
var classname = "com.example." + "antifrida" + ".MainActivity";
var onCreate = Java.use(classname).onCreate;
onCreate.overload("android.os.Bundle").implementation = function (
args
) {
console.log(
Java.use("android.util.Log").getStackTraceString(
Java.use("java.lang.Throwable").$new()
)
);
this.onCreate(args);
};
});
}

hook native func

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
if (Java.available) {
// Interceptor.attach第一参为hook的函数地址,第二参为导出函数
// Module.findExportByName通过函数导出的名字获得该函数地址,常与Interceptor打配合
Interceptor.attach(
Module.findExportByName(
"libanti_frida.so",
"Java_com_example_antifrida_MainActivity_HelloWorld"
),
{
// Interceptor.attach的callback应该是只走onEnter和onLeave这两个函数,且入参固定为
// 其参数分别为入参和返回值
onEnter: function (args) {
console.log("Enter native HelloWorld ——");
},
onLeave: function (retVal) {
console.log("Leave native HelloWorld ——");
console.log("retVal : ", retVal);
console.log("try to modify it to : ", "hacked!");
// 制作jni规范的string串,mark
var env = Java.vm.getEnv(); //获取env对象,即第一个参数
var jstrings = env.newStringUtf("hacked!"); //返回的是字符串指针,构造一个newStringUtf对象用来代替这个指针
retVal.replace(jstrings); //替换返回值
},
}
);
// hook其它导出函数,可隐去。
var addr = Module.findExportByName("libanti_frida.so", "hello_world");
console.log("hello_world addr : ", addr);
Interceptor.attach(addr, {
onEnter: function (args) {
console.log("Enter native hello_world ——");
},
onLeave: function (retVal) {
console.log("Leave native hello_world ——");
// 返回的是字符串地址,用readUtf8String解释地址
console.log("retVal : ", retVal.readUtf8String());
},
});
// // 通过地址直接计算并hook
var str_name_so = "libanti_frida.so"; //需要hook的so名
var n_addr_func_offset = 0x00001970; //需要hook的函数的偏移
var n_addr_so = Module.findBaseAddress(str_name_so); //加载到内存后 函数地址 = so地址 + 函数偏移
var n_addr_func = parseInt(n_addr_so, 16) + n_addr_func_offset;
// 应该是使用规范
var ptr_func = new NativePointer(n_addr_func);
console.log("hello_world addr : ", ptr_func);
Interceptor.attach(ptr_func, {
//onEnter: 进入该函数前要执行的代码,其中args是传入的参数,一般so层函数第一个参数都是JniEnv,第二个参数是jclass,从第三个参数开始是我们java层传入的参数
onEnter: function (args) {
console.log("address hook start");
},
onLeave: function (retval) {
//onLeave: 该函数执行结束要执行的代码,其中retval参数即是返回值
console.log("return"); //返回值
},
});
} else {
console.log("boot err");
}

hook win dll

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
//find dll address
const baseAddr = Module.findBaseAddress("mydll.dll");
console.log("[+] mydll.dll baseAddr:" + baseAddr);

const encode = resolveAddress("0x180011082");
console.log(
"[+] Module found encode addr: " +
Module.findExportByName("mydll.dll", "encode")
);
Interceptor.attach(encode, {
onEnter: function (args) {
console.log("");
console.log("[+] Called encode: " + this.context.rip);
console.log("[+] a: " + args[0].readAnsiString(4));
console.log("[+] key: " + args[1]); // Plaintext// Length of data to en/decrypt
//dumpAddr("Input", args[0], args[1].toInt32());
//this.outptr = args[2]; // Store arg2 and arg3 in order to see when we leave the function
//this.outsize = args[3].toInt32();
},
onLeave: function (retVal) {
console.log("[+] Returned from func encode: " + this.context.rip);
},
});

function resolveAddress(addr) {
const base = ptr("0x180000000"); //ter the base address of jvm.dll as seen in your favorite disassembler
const offset = ptr(addr).sub(base); //Calculate offset in memory from base address in disassembler database
const result = baseAddr.add(offset); //Add current memory base address to offset of function to monitor
console.log("[+] New addr=" + result); // Write location of function in memory to console
return result;
}
function dumpAddr(info, addr, size) {
if (addr.isNull()) return;

console.log("Data dump " + info + " :");
const buf = addr.readByteArray(size);

console.log(
hexdump(buf, { offset: 0, length: size, header: true, ansi: true })
);
}