JavaScript API 手册 | Frida JavaScript-api 中文手册

frida_Android

运行frida常用命令

运行server

1
2
3
4
adb push 名 /data/local/tmp
adb root
adb shell chmod +x /data/local/tmp/fridaad64
adb shell /data/local/tmp/frida-server

spwan启动

1
Frida -U -f 包名 -l hookbool.js

-U 指定USB设备

-f 用app包名spwn方式启动

-P 指定APP的pid,先要自行启动

-pause 暂停

-l 加载hook脚本

一些frida方法的收集

1
send(); //发送信息到控制台.

对hook脚本的初步解析

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
//在启动时就被hook的方法,通常用于绕过反调试,java.perform()是一个frida的接口
//几乎一切操作都在这个函数执行
Java.perform(function(){
let MainActivity = Java.use("packname.MainActivity"); //实例化一个类
MainActivity["isEmu"].implementation = function () {
console.log(`MainActivity.isEmu is called`);
let result = this["isEmu"]();
console.log(`MainActivity.isEmu result=${result}`);
return 0; //一般可以修改返回值如果报错用false,修改返回值
};
//调用方法并返回值。
MainActivity["g4tk4y"].implementation = function () {
console.log(`MainActivity.g4tk4y is called`);
let result = this["g4tk4y"]();
console.log(`MainActivity.g4tk4y result=${result}`);
return result; //修改返回值
};
//java.choose会遍历类的实例,调用方法,用于无法获得实例时动态引用,
//修改成员变量。我的理解是寻找一个系统自己的实例,而不是我们自己去实例化。
Java.choose("packname.MainActivity",{
onMatch:
function(x){
console.log("ok" + x);
let result = x.g4tk4y();
console.log(result);
},
onComplete: function () {
console.log("end");
}

});
var MainActivity = Java.use("packname.MainActivity");
//overload 选择被重载的对象,funname是方法名,int是要重载的类型
MainActivity.funname.overload('int').implementation = function (x) {
console.log("ok" + x);
//可修改结果,另一种修改返回值的方法
var result = "";
return result;
};
})



function hook() { //把方法封装为一个函数,在运行起来后可以直接调用执行
Java.perform(function(){
let MainActivity = Java.use("packname.MainActivity");
MainActivity["g4tk4y"].implementation = function () {
console.log(`MainActivity.g4tk4y is called`);
let result = this["g4tk4y"]();
console.log(`MainActivity.g4tk4y result=${result}`);
return result;
};
MainActivity.aaa("x"); //调用函数并传参
})
};

(function () { //(function(){..})();这样的形式会直接执行函数,
//以下函数用dia提取,用于hookso层的函数

// @ts-ignore
function print_arg(addr) {
try {
var module = Process.findRangeByAddress(addr);
if (module != null) return "\n"+hexdump(addr) + "\n";
return ptr(addr) + "\n";
} catch (e) {
return addr + "\n";
}
}

// @ts-ignore
function hook_native_addr(funcPtr, paramsNum) {
var module = Process.findModuleByAddress(funcPtr);
try {
Interceptor.attach(funcPtr, {
onEnter: function (args) {
this.logs = "";
this.params = [];
// @ts-ignore
this.logs=this.logs.concat("So: " + module.name + " Method: Java_ offset: " + ptr(funcPtr).sub(module.base) + "\n");
for (let i = 0; i < paramsNum; i++) {
this.params.push(args[i]);
this.logs=this.logs.concat("this.args" + i + " onEnter: " + print_arg(args[i]));
}
}, onLeave: function (retval) {
for (let i = 0; i < paramsNum; i++) {
this.logs=this.logs.concat("this.args" + i + " onLeave: " + print_arg(this.params[i]));
}
this.logs=this.logs.concat("retval onLeave: " + print_arg(retval) + "\n");
console.log(this.logs);
}
});
} catch (e) {
console.log(e);
}
}
// @ts-ignore
hook_native_addr(Module.findBaseAddress("libdebugme.so").add(0xff0), 0x1);
})();

//重载函数的其他类型
.overload()
.overload('int')
.overload('java.lang.Exception')
.overload('android.content.Context')
.overload('java.lang.String')
.overload('android.content.Context', 'java.lang.String')
.overload('java.io.BufferedInputStream', 'java.io.BufferedInputStream', 'int')
.overload('android.content.Context', 'java.lang.String', 'java.lang.String', 'java.lang.String')


上面的方法都是被动调用,下面一段脚本是主动调用脚本

1
2
3
4
5
6
Java.perform(function(){
var main =Java.use("com.moible.r15.main").$new();
var input = "66.666s";
var result = main.getit(input);
console.log(result);
})

有时候我们想要把一个调用方法封装在一个函数里面,在之后手动调用,然而在我们后面调用时可能会出现报错

这个时候我们要使用一下代码使handle能够在别的实例中运行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 send(Java.available); 
function get(){
Java.perform(function () {
send(Java.androidVersion);
send(Java.isMainThread());

Java.scheduleOnMainThread(function () {
send(Java.isMainThread());

var main = Java.use("com.moible.r15.main").$new(); //记得实例化new
var input = "66.666s"; //设置参数
var result = main.getit(input);
console.log(result);
});
});
}

frida_win_processes

frida可以hookwindows上的的进程,详见功能 |Frida • 世界一流的动态仪表工具包

1
frida -l hook.js -n [name]

这里的name是进程的程序名字。

简单列出frida的一些process API。参考bbs.kanxue.com/article-342.htm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var process = Process.findModuleByAddress(address) //根据包含的地址查找模块
var process = Process.findModuleByName() //根据名字查找在内存中的模块(str)->(模块对象)
process.base //模块基地址
process.name //模块名
process.size //模块大小
process.path //模块路径

setInterval(f, delay) //每隔delay毫秒调用f,返回一个id,使用clearinterval(id)取消对setIntervar()的调用

ptr(addr) //以指针形式调用地址数据

hexdump(addr,{offset:0,length:64,header:true,absi:true}) //把一个区域内的内存按格式导出

this.context //访问当前hook的上下文信息,其中this.context.rax可以获取寄存器的值

hook脚本来自Windows | Frida • A world-class dynamic instrumentation toolkit
通用脚本

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
   //const baseAddr = Module.findBaseAddress('Jvm.dll'); //获取hook对象的拓展模块基地址
//console.log('Jvm.dll baseAddr: ' + baseAddr);
var process = Process.findModuleByName("xx.exe"); //以名称获取进程中的模块
var baseaddr = process.base

//const f = resolveAddress('0x1FF44870'); //输入函数在ida中显示的地址,获得在内存中的地址

Interceptor.attach(baseaddr.add(0x0000), { // hook函数,函数被调用时执行
// 被hook时打印函数信息
onEnter(args) {
console.log('');
console.log('[+] Called SetAesDeCrypt0' + f); //被hook的函数地址
console.log('[+] Input: ' + args[0]); // 参数args[1],args[2]...
aegs[0] = 111; //修改参数
dumpAddr('Input', args[1], args[3].toInt32()); //导出指针参数的数据
this.outptr = args[2]; //保存参数的值以便函数结束时查看
this.outsize = args[3].toInt32();
var rdx=this.context.rdx; //以上下文获取寄存器的值
console.log(hexdump(ptr(rdx),{length: 16,ansi:true})); //导出寄存器指向内存的数据
},

onLeave(retval) { //函数结束时执行
dumpAddr('Output', this.outptr, this.outsize); // 获取我们保存的指针参数的值
console.log('[+] Returned from setAesDecrypt0: ' + retval); //函数的返回值
}
});

function dumpAddr(info, addr, size) { //导出内存数据
if (addr.isNull())
return;

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

// 如果想要色彩高亮,ansi为true
console.log(hexdump(buf, { offset: 0, length: size, header: true, ansi: false }));
}

function resolveAddress(addr) { //用IDA显示的地址获取当前内存中的地址,其实自己手算偏移也行
const idaBase = ptr('0x1FEE0000'); //输入IDA中显示的基地址,用于计算地址偏移
const offset = ptr(addr).sub(idaBase); //计算地址偏移
const result = baseAddr.add(offset); //计算现在在内存中的地址
console.log('[+] New addr=' + result); // 输出在内存中的地址
return result;
}

手动调用函数

1
2
var f = new NativeFunction(ptr(addr), 'void', ['int']); //函数地址,返回类型,参数类型,调用函数
f(1911); //调用函数并串参

实用脚本总结

hookjava函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Java.perform(function(){ 
let MainActivity = Java.use("com.exa.n.MainActivity");
MainActivity["func"].implementation = function (data) {
console.log(`func is called: data=${data}`);

var result;
result = this["func"](data);
return result;
};
})

function printstack() { //打印堆栈
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
}

hookso

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

var libapp = null;

function onLibappLoaded() {
const fn_addr = 0x2FE7F0;
Interceptor.attach(libapp.add(fn_addr), {
onEnter: function () {
var rdi = this.context.rdi;
console.log(rdi)
console.log(hexdump(ptr(rdi), { length: 100, ansi: true }))
}
});
}

function tryLoadLibapp() {
libapp = Module.findBaseAddress('libapp.so');
if (libapp === null)
setTimeout(tryLoadLibapp, 500);
else
onLibappLoaded();
}
tryLoadLibapp();

windows一般dump寄存器的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var inter=setInterval(function () {
var process = Process.findModuleByName("1.exe");
var baseaddr = process.base
console.log("base"+baseaddr);

clearInterval(inter);
console.log(hexdump(baseaddr.add(0x005160),{length:255,ansi:true}))

Interceptor.attach(baseaddr.add(0x001E7F), {
onEnter: function (args) {
var rax=this.context.rax;
console.log("secret" +rax);
console.log(hexdump(ptr(rax),{length: 48,ansi:true}));
}}),
},1)

修改寄存器的值

(用python处理数据)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function hookinput(data){
var baseaddr = Module.findBaseAddress("applib.so");
Interceptor.attach(baseaddr.add(0x001E7F), {
onEnter: function (args) {
var rdi=this.context.rdi;
console.log("hook" +rdi);
console.log(hexdump(ptr(rax),{length: 48,ansi:true}));
rdi.writeByteArray(data)
console.log("edit_after" +rdi);
console.log(hexdump(ptr(rax),{length: 48,ansi:true}));
}})
}
RTCPeerConnection.export = {
hookinput:hookinput
}
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
import time
import frida
import sys

def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)

device8 = frida.get_usb_device()
pid = device8.spawn("com.example.aaar")
device8.resume(pid)
time.sleep(1)
session = device8.attach(pid)
with open("hook.js") as f:
script = session.create_script(f.read())
script.on('message', on_message)
print('[*] Hook Start Running')
script.load()

ad = "".join('a' * 42)
test = f"flag{{{ad}}}"
input_arr_byte = bytearray(test.encode())
data = list(map(int,input_arr_byte))

script.export.inputhook(data)


单js脚本处理,适用于简单数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function stringToAsciiArray(str) {
return Array.from(str).map(char => char.charCodeAt(0));
}
const input = "flag{}";
const data = stringToAsciiArray(input);

function hookinput(data){
var baseaddr = Module.findBaseAddress("libflutter.so");
Interceptor.attach(baseaddr.add(0x001E7F), {
onEnter: function (args) {
var rdi=this.context.rdi;
console.log("hook" +rdi);
console.log(hexdump(ptr(rax),{length: 48,ansi:true}));
rdi.writeByteArray(data)
console.log("edit_after" +rdi);
console.log(hexdump(ptr(rax),{length: 48,ansi:true}));
}})
}
hookinput(data);

文件删除前转移,用于脱壳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
File.delete.implementation = function() {
var filePath = this.getAbsolutePath(); // 获取文件路径
console.log("文件将在删除之前被保存: " + filePath);

// 在删除之前复制文件到其他位置
var newFile = Java.use('java.io.File');
var destPath = "/data/data/com.nobody.zunjia/files/savedDexFile.dex"; // 新文件路径
var sourceFile = this;
var inputStream = Java.use('java.io.FileInputStream').$new(sourceFile);
var outputStream = Java.use('java.io.FileOutputStream').$new(destPath);

var buffer = Java.array('byte', [1024]); // 缓冲区
var bytesRead;
while ((bytesRead = inputStream.read(buffer)) !== -1) {
outputStream.write(buffer, 0, bytesRead);
}
inputStream.close();
outputStream.close();
console.log("文件已保存到: " + destPath);

// 执行原本的删除操作
return this.delete();
};

hook initarray,替换函数

d3ctf的一段模板,

原理是so的加载流程,liberaryLoad ->liberaryLoad0->dlopen(android_dlopen_ext)->__dl__ZN6soinfo17call_constructorsEv。此时so已经加载,然后会执行init_array段。

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
//frida version 17.1.0

function findSo(name){
var lib=null;
console.log(`finding ${name}`);
try {
lib = Process.findModuleByName(name)
if (lib === null) {
setTimeout(findSo,200,name);
}
else {
console.log(`found ${name} at ${lib.base}`);
return lib;
}
} catch { }
}

function hookI(name) {
var lib = findSo(name);
try {
var destFuncAddr = lib.base.add(0x08922A0);
Interceptor.replace(destFuncAddr, new NativeCallback(function () { //替换函数
console.log(`replace: ${name} func: ${destFuncAddr}`);
return 0;
}, 'int', []))
} catch { }
}

function hookInitArray(name) {
var linkermodule = Process.getModuleByName("linker64");
var call_function_addr = null;
var symbols = linkermodule.enumerateSymbols();

for (var i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
// console.log(symbol.name);

if (symbol.name.indexOf("__dl__ZN6soinfo17call_constructorsEv") != -1) {
call_function_addr = symbol.address;
console.log("call_function_addr:" + call_function_addr);
Interceptor.attach(call_function_addr, {
onEnter: function (args) {
console.log("call_constructors");
hookI(name);
}
})
return;
}
}
}

hookInitArray('libMediaPlayer.so');

追踪流程定位函数

r3ctf一道题的模板

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
//const FUNC_OFFSET = 0x1630  // 1
const FUNC_OFFSET = 0x17C0; // 2
//const FUNC_OFFSET = 0x0167B //3

const pow = [0x89, 0xc6, 0xbf, 0x02, 0x00, 0x00, 0x00, 0xe8] //eax
var powFlag = 0; //4
var shift = []; //4 r>> r<< l>> l<<

const delta = [0x48, 0x89, 0xc7, 0xff, 0xd1]; //esi
var deltaFlag = 0; //1
var deltaData = 0;

const sbox = [0x89, 0xce, 0x48, 0x89, 0xc7, 0x41, 0xff, 0xd0]; //rax:addr 256*4 bytes
var sboxFlag = 0;
var sboxData = [];//ptr

function matchPattern(code,pattern) {
for (let i = 0; i < pattern.length; i++) {
if (code[i] !== pattern[i]) return false;
}
return true;
}

const moduleBase = Process.getModuleByName("beatme").base;
const targetAddr = moduleBase.add(FUNC_OFFSET);

console.log("[*] Waiting to reach function at", targetAddr);

Interceptor.attach(targetAddr, {
onEnter(args) {
try {
console.log("[+] Entered target function, starting Stalker at", targetAddr);
console.log(ptr(args[1]))
Stalker.follow(Process.getCurrentThreadId(), {
transform(iterator) {
let instruction;
while ((instruction = iterator.next()) !== null) {
const addr = instruction.address;
const codeBytes = Memory.readByteArray(addr, 8);
const code = new Uint8Array(codeBytes);
// console.log(`[${addr}] ${instruction}`);
if ((powFlag < 4) && matchPattern(code,pow)) {
console.log("[*] Match pow found at:", addr.sub(moduleBase));
console.log(`[${addr}] ${instruction}`);
iterator.putCallout(function (context) {
if(powFlag >=4) return;
var rax = context.rax;
console.log(`shift: EAX = ${rax.toString(16)}`);
shift[powFlag++] = rax;
})
}
else if (!deltaFlag && matchPattern(code,delta)) {
console.log("[*] Match delta found at:", addr.sub(moduleBase));
console.log(`[${addr}] ${instruction}`);
iterator.putCallout(function (context) {
if(deltaFlag != 0) return;
var rsi = context.rsi;
console.log(`delta: RSI = ${rsi.toString(16)}`);
deltaData = rsi;
deltaFlag++;
})
}
else if (!sboxFlag && matchPattern(code,sbox)) {

console.log("[*] Match sbox found at:", addr.sub(moduleBase));
console.log(`[${addr}] ${instruction}`);
iterator.putCallout(function (context) {
if(sboxFlag != 0)return;
var rax = context.rax;
console.log(`sbox: RAX = ${rax.toString(16)}`);
for (let i = 0; i < 256; i++) {
const value = Memory.readU32(rax.add(i * 4));
sboxData.push(value);
sboxFlag++;
}
})
}
iterator.keep();
}
}
});
} catch (e) {
console.log(e);
}
},
onLeave: function (args) {
console.log(sboxData)
console.log(shift);
console.log(deltaData);

}
});

读系统文件

1
2
3
4
function reada(){
var f = File.readAllText("/proc/self/task");
console.log(f)
}

hook so加载

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
function hook() {
var addr = null;
try {
var module = Process.getModuleByName("libc.so");
addr = module.getExportByName("dlopen");
} catch (e) {
console.log(e);
}
console.log("dlopen:", addr);
Interceptor.attach(addr, {
onEnter: function (args) {
var loadName = args[0].readCString();
console.log("dlopen: ", loadName);
},
onLeave: function (retval) {
console.log("handle:", retval);
}
});

var android_dlopen_ext = module.getExportByName("android_dlopen_ext");
console.log("android_dlopen_ext:", android_dlopen_ext);
Interceptor.attach(android_dlopen_ext, {
onEnter: function (args) {
this.call_hook = false;
var so_name = ptr(args[0]).readCString();
console.log("android_dlopen_ext:", so_name);
},
onLeave: function (retval) { }
});
}

调用native函数,获取缓冲区数据

d3ctf一道题的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getpq(){
var libapp = findSo("libD3piano.so").base;
const fn_addr = 0x29AA0;
console.log("hook"+libapp);
Interceptor.attach(libapp.add(fn_addr), {
onEnter: function () {
try{
var x1 = this.context.x1;
var x2 = this.context.x2;
var gmpz_get_str = new NativeFunction(libapp.add(0x5CFD0),"pointer",["pointer","int","pointer"]); //调用native函数
var mallocAddrp = Memory.alloc(0x1000);//构造缓冲区
var mallocAddrq = Memory.alloc(0x1000);
var p = gmpz_get_str(mallocAddrp, 16, x1);
var q = gmpz_get_str(mallocAddrq, 16, x2);
console.log(mallocAddrp.readCString());
console.log(mallocAddrq.readCString());

}catch(e){
console.log(e);
}
}
});
}

虚拟机操作hook

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
function toHexUnsigned(val) {
return "0x" + (val >>> 0).toString(16);
}

let result = toHexUnsigned(0x38373635 << 3);
console.log("结果:", result); // → 0x1c1b1b28


function findSo(name){
var lib=null;
console.log(`finding ${name}`);
try {
lib = Process.findModuleByName(name)
if (lib === null) {
setTimeout(findSo,200,name);
}
else {
console.log(`found ${name} at ${lib.base}`);
return lib;
}
} catch { }
}
var tmp =0;
function getpq() {
var libapp = findSo("easyvm.exe").base;
const fn_addr = 0x1194B;
console.log("hook" + libapp);
setInterval(() => {
Interceptor.attach(libapp.add(fn_addr), {
onEnter: function () {
try {
var p1 = this.context.rax;
var p2 = this.context.rbp;
var p2var = p2.sub(0x74).readU32();
tmp = p1;
console.log(`${p1} ^ ${p2var} == ${toHexUnsigned(p1 ^ p2var)}`)
} catch (e) {
console.log(e);
}
}
});
// Interceptor.attach(libapp.add(0x1194e), {
// onEnter: function () {
// try {
// var p1 = this.context.rax;
// console.log(`2: ${tmp} ^ ${toHexUnsigned(p1 ^ tmp)} == ${toHexUnsigned(p1)}`)
// } catch (e) {
// console.log(e);
// }
// }
// });
// 》》
Interceptor.attach(libapp.add(0x1165B), {
onEnter: function () {
try {
var p1 = this.context.rdx;
var p2 = this.context.rcx;
console.log(`${p1} >> ${p2} == ${toHexUnsigned(p1 >> p2)}`)
} catch (e) {
console.log(e);
}
}
});
// 《《
Interceptor.attach(libapp.add(0x115B5), {
onEnter: function () {
try {
var p1 = this.context.rdx;
var p2 = this.context.rcx;
tmp =p2
console.log(`${p1} << ${p2} == ${toHexUnsigned(p1 << p2)}`)
} catch (e) {
console.log(e);
}
}
});
//%
Interceptor.attach(libapp.add(0x10EBC), {
onEnter: function () {
try {
var p1 = this.context.rax;
var p2 = this.context.rbp;
var p2var = p2.sub(0x8c).readU32();
console.log(`${p1} % ${p2var} == ${toHexUnsigned(p1 % p2var)}`)
} catch (e) {
console.log(e);
}
}
});
// /
Interceptor.attach(libapp.add(0x10EBC), {
onEnter: function () {
try {
var p1 = this.context.rax;
var p2 = this.context.rbp;
var p2var = p2.sub(0x94).readU32();
console.log(`${p1} // ${p2var} == ${toHexUnsigned(p1 / p2var)}`)
} catch (e) {
console.log(e);
}
}
});
// *
Interceptor.attach(libapp.add(0x10D63), {
onEnter: function () {
try {
var p1 = this.context.rax;
var p2 = this.context.rbp;
var p2var = p2.sub(0x9c).readU32();
console.log(`${p1} * ${p2var} == ${toHexUnsigned(p1 * p2var)}`)
} catch (e) {
console.log(e);
}
}
});
// -
Interceptor.attach(libapp.add(0x010CC6 ), {
onEnter: function () {
try {
var p1 = this.context.rax;
var p2 = this.context.rbp;
var p2var = p2.sub(0xa4).readU32();
console.log(`${p1} - ${p2var} == ${toHexUnsigned(p1.toUInt32() - p2var.toUInt32())}`);
} catch (e) {
console.log(e);
}
}
});
Interceptor.attach(libapp.add(0x10C2A), {
onEnter: function () {
try {
var p1 = this.context.rax;
var p2 = this.context.rdx;
console.log(`${p1} + ${p2} == ${toHexUnsigned(p1.toUInt32() + p2.toUInt32())}`)
} catch (e) {
console.log(e);
}
}
});

}, 500);

}


getpq();

创建函数(直接返回)

1
2
3
4
5
6
7
8
9
function create_fake_pthread_create() {
const fake_pthread_create = Memory.alloc(4096)
Memory.protect(fake_pthread_create, 4096, "rwx")
Memory.patchCode(fake_pthread_create, 4096, code => {
const cw = new Arm64Writer(code, { pc: ptr(fake_pthread_create) })
cw.putRet()
})
return fake_pthread_create
}

创建函数(死锁)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function fakePersistentThread() {
const codeAddr = Memory.alloc(0x1000);
Memory.protect(codeAddr, 0x1000, 'rwx');

const cw = new Arm64Writer(codeAddr, { pc: codeAddr });

cw.putBLabel('loop');
cw.putNop();
cw.putNop();
cw.putBCondLabel('al','loop');

return codeAddr;
}