抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

学一下stalker脚本怎么写的。

Frida的Stalker · 逆向调试利器:Frida

JavaScript API | Frida • A world-class dynamic instrumentation toolkit

[Stalker · Frida逆向实例和工具函数

打印变化的寄存器

image-20250302082418067

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
function StalkerTrace() {
var base_hello_jni = Module.findBaseAddress("libhello-jni.so");
var sub_1CFF0 = base_hello_jni.add(0x1CFF0);
console.log(sub_1CFF0);
var module_hello_jni = Process.findModuleByName("libhello-jni.so");

var module_start = module_hello_jni.base;
var module_end = module_hello_jni.base + module_hello_jni.size;
var pre_regs = {}

Interceptor.attach(sub_1CFF0, {
onEnter: function (args) {
this.arg0 = args[0];
this.arg1 = args[1];
this.arg2 = args[2];
this.tid = Process.getCurrentThreadId();//当前的线程id

Stalker.follow(this.tid, {
events: {
call: false, // CALL instructions: yes please

ret: false, // RET instructions
exec: true, // all instructions: not recommended as it's
// a lot of data
block: false, // block executed: coarse execution trace
compile: false // block compiled: useful for coverage
},
// onCallSummary(summary) {
// console.log("onCallSummary:", Object.entries(summary));
// }, //总结
// onReceive(events) {
// // console.log(Stalker.parse(events))
// for (const [index, value] of Object.entries(Stalker.parse(events))) {
// if (value.indexOf("exec") >= 0) {
// var address = value.toString().split(",")
// var addr = address[1];
// var module = Process.findModuleByAddress(addr);
// if (module) {
// console.log("onReceive:", module.name + "!" + ptr(addr).sub(module.base), Instruction.parse(ptr(addr)));
// }
// }

// }
// },
transform(iterator) {
let instruction = iterator.next();
do {
const startAddress = instruction.address;
const is_module_code = startAddress.compare(module_start) >= 0 &&
startAddress.compare(module_end) === -1;
if (is_module_code) {
// console.log(startAddress, instruction);
iterator.putCallout(function (context) {
var pc = context.pc;
var module = Process.findModuleByAddress(pc);
if (module) {
var diff_regs = get_diff_regs(context, pre_regs);

console.log(module.name + "!" + ptr(pc).sub(module.base),
Instruction.parse(ptr(pc)),
JSON.stringify(diff_regs));
}

});
}

iterator.keep();
} while ((instruction = iterator.next()) !== null);
}


});

}, onLeave: function (retval) {

Stalker.unfollow(this.tid);//结束当前的trace

console.log("sub_1CFF0:", hexdump(this.arg0, { length: parseInt(this.arg1) }),
"\r\n", hexdump(this.arg2, { length: parseInt(this.arg1) }))
}
})
}


setImmediate(StalkerTrace);

遇到bl指令 就打印调用地址.

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
function hook_native_stalker(){


var so_addr = Module.findBaseAddress("libcheckout.so");
if (so_addr)
{
console.log("so_addr:", so_addr);
var addr_13F91 = so_addr.add(0x1E658);
console.log("The addr_13F91:", addr_13F91);
var stalker_hook = false;
Interceptor.attach(addr_13F91,
{
onEnter: function (args) {
console.warn(JSON.stringify({
// fname: args[1].readCString(),
// text: new ObjC.Object(args[2]).toString(),
backtrace: Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).map(m => m.moduleName+'!'+m.name),
ctx: this.context
}, null, 2));
var tid = Process.getCurrentThreadId();
this.tid = tid;
Stalker.follow(tid, {
events: {
call: true
},
/*
onCallSummary: function (summary) {
Object.keys(summary).forEach(s => {
var sym = DebugSymbol.fromAddress(ptr(s));
if (sym.moduleName == 'Viber')
console.log(summary[s], sym.name);
})
}
*/
transform: function (iterator) {
var instruction;
while ((instruction = iterator.next()) !== null) {
iterator.keep();
if (instruction.mnemonic.startsWith('bl')) {
try {
console.log('#' + tid + ':' + DebugSymbol.fromAddress(ptr(instruction.operands[0].value)));
} catch (e) {
// ignoring branch&link to register
}
}
}
}
});
},
onLeave: function (retval) {
Stalker.unfollow(this.tid);
Stalker.garbageCollect();
console.log("=====================================================")

}


})

}

}

hook_native_stalker()

每次执行bl指令时, 就打印当前pc, 并且尝试打印 cstring, x0

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
function hook_native_stalker_dy(){

var so_name = "libmetaxxx.so"
var so_addr = Module.findBaseAddress(so_name);
var so_size = Process.getModuleByName(so_name).size;

if (so_addr)
{
console.log("so_addr:", so_addr);
// var hook_addr = so_addr.add(0xc167c);
var hook_addr = so_addr.add(0xbe040);
console.log("The addr_13F91:", hook_addr);

var stalker_hook = false;

var pre_regs = {}

Interceptor.attach(hook_addr,
{
onEnter: function (args) {
console.warn(JSON.stringify({
// fname: args[1].readCString(),
// text: new ObjC.Object(args[2]).toString(),
backtrace: Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).map(m => m.moduleName+'!'+m.name),
ctx: this.context
}, null, 2));
var tid = Process.getCurrentThreadId();
this.tid = tid;
Stalker.follow(tid, {
events: {
call: true
},
/*
onCallSummary: function (summary) {
Object.keys(summary).forEach(s => {
var sym = DebugSymbol.fromAddress(ptr(s));
if (sym.moduleName == 'Viber')
console.log(summary[s], sym.name);
})
}
*/
transform: function (iterator) {
var instruction = iterator.next();
const startAddress = instruction.address;
if (startAddress){
var isModule = startAddress.compare(so_addr.add(0xbe040)) >= 0 && startAddress.compare(so_addr.add(so_size)) < 0;
do{
if (isModule){
if (instruction.mnemonic.startsWith('bl')) {
// var uuid = getUuid()
// console.log("uuid 1", uuid)
try {

iterator.putCallout(function (context) {
var pc = context.pc; //获取pc寄存器,当前地址
var lr = context.lr; //获取pc寄存器,当前地址
var x0 = context.x0; //获取pc寄存器,当前地址
var module = Process.findModuleByAddress(pc);
if (module) {
//如果模块存在
// var diff_regs = get_diff_regs(context, pre_regs);//得到所有的变化寄存器。

// console.log(module.name + "!" + ptr(pc).sub(module.base),
// Instruction.parse(ptr(pc)),
// // JSON.stringify(diff_regs)
// );
try{
console.log(Memory.readCString(ptr(x0)))
}
catch (e){

}

console.log("pc ====" + DebugSymbol.fromAddress(ptr(pc)))
// console.log("lr ====" + DebugSymbol.fromAddress(ptr(lr)))

}
});

// console.log('#' + tid + ':' + DebugSymbol.fromAddress(ptr(instruction.operands[0].value)));

// console.log(instruction.toString())
// console.log(context)
} catch (e) {
console.log("error", e)
// ignoring branch&link to register
}
}
}
iterator.keep();
} while ((instruction = iterator.next()) !== null);
}
},


});
},
onLeave: function (retval) {
Stalker.unfollow(this.tid);
Stalker.garbageCollect();
console.log("=====================================================")

}


})

}

}
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/**
功能: 跟踪native函数调用情况。
*/
var so_name = "libjiagu_64.so";
var TargetLibName = 'libjiagu_64.so'; // 待分析的so库文件名
var TargetFuncOffset = 0x1399d8; // 待分析的native函数偏移, 先在IDA里找到
var TraceCallNum = 1; // 默认只输出调用1次的函数


function hookTargetFunc() {
var baseAddr = Module.findBaseAddress(TargetLibName)
//console.log(TargetLibName + " Module Base: " + baseAddr);
if (baseAddr == null) {
console.log('Please makesure ' + TargetLibName + ' is Loaded, by setting extractNativeLibs true.');
return;
}

// hook指定的函数地址
Interceptor.attach(baseAddr.add(TargetFuncOffset), {
onEnter: function (args) {
console.log('\nCall ' + TargetFuncOffset.toString(16).toUpperCase() + ' In')
this.tid = Process.getCurrentThreadId();
Stalker.follow(this.tid, {
events: {
call: true, // CALL instructions: yes please

// Other events:
ret: false, // RET instructions
exec: false, // all instructions: not recommended as it's
// a lot of data
block: false, // block executed: coarse execution trace
compile: false // block compiled: useful for coverage
},

onReceive: function () {

},



/*
transform: function (iterator) {//主要是transform
var instruction = iterator.next();
do{
console.log(instruction.address + "\t:\t" + instruction);
iterator.keep();
} while ((instruction = iterator.next()) !== null);
},
*/



onCallSummary(summary) {
/*//console.log(JSON.stringify(summary)); // 调用的所有函数及次数,注意并不是实际调用顺序。
for (const target in summary) {
const number = summary[target];
if (number == TraceCallNum) {
var module = Process.findModuleByAddress(target);
if (module != null && module.name == TargetLibName) {
console.log(module.name + "!" + ptr(target).sub(module.base));
}
}
}*/
}

})
}, onLeave: function (retVal) {
console.log('Call ' + TargetFuncOffset.toString(16).toUpperCase() + ' Out\n')
Stalker.unfollow(this.tid)
}
})
}

function hook(addr) {
Interceptor.attach(addr, {
onEnter: function (args) {
var module = Process.findModuleByAddress(addr);
this.args0 = args[0];
this.args1 = args[1];
this.args2 = args[2];
this.args3 = args[3];
this.args4 = args[4];
this.logs = []
this.logs.push("------------------------\n");
this.logs.push("call " + module.name + "!" + ptr(addr).sub(module.base) + "\n");
this.logs.push("onEnter args0: " + print_arg(this.args0));
this.logs.push("onEnter args1: " + print_arg(this.args1));
this.logs.push("onEnter args2: " + print_arg(this.args2));
this.logs.push("onEnter args3: " + print_arg(this.args3));
this.logs.push("onEnter args4: " + print_arg(this.args4));
}, onLeave: function (ret) {
this.logs.push("onLeave args0: " + print_arg(this.args0));
this.logs.push("onLeave args1:" + print_arg(this.args1));
this.logs.push("onLeave args2:" + print_arg(this.args2));
this.logs.push("onLeave args3:" + print_arg(this.args3));
this.logs.push("onLeave args4:" + print_arg(this.args4));
this.logs.push("onLeave return: " + print_arg(ret));
console.log(this.logs)
}
})
}

function print_arg(addr) {
var range = Process.findRangeByAddress(addr);
console.log(range)
if (range != null) {
return hexdump(addr) + "\r\n";
} else {
return ptr(addr) + "\r\n";
}
}


function main() {
// 需要hook的函数地址列表
var funcAddr = [
];

if (funcAddr.length == 0) {
hookTargetFunc();
} else {
var baseAddr = Module.findBaseAddress(TargetLibName);
console.log(TargetLibName + " Module Base: " + baseAddr);

for (var i = 0; i < funcAddr.length; i++) {
hook(baseAddr.add(funcAddr[i]));
}
}
}
var zlib_count=0;
var next_in,avail_in,next_out,avail_out;
function hook_zlib(){
Interceptor.attach(Module.findExportByName(null, "inflate"), {
// fd, buff, len
onEnter: function (args) {
zlib_count+=1
if(zlib_count>1){
main();
}

},
onLeave: function (ret) {
}
});
}



function anti_frida_check(){
var module = Process.findModuleByName("libjiagu_64.so");
Interceptor.attach(module.base.add(0x1770C), {
onEnter: function (args) {
try{
var s = this.context.x6.readCString();
if (s.indexOf('frida')!==-1 ||
s.indexOf('gum-js-loop')!==-1 ||
s.indexOf('gmain')!==-1 ||
s.indexOf('linjector')!==-1 ||
s.indexOf('/proc/')!==-1){
//console.log(s)
Memory.protect(this.context.x0, Process.pointerSize, 'rwx');
var replace_str=""
for(var i=0;i<s.length;i++){
replace_str+="0"
}
this.context.x0.writeUtf8String(replace_str);
}
}
catch (e){
}
},
onLeave: function (ret) {
}
});
}

function hook_dlopen() {
//hook_call_constructors();
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("dlopen "+path);
if (path.indexOf(so_name) >= 0) {
this.is_can_hook = true;
}
}
},
onLeave: function (retval) {
if (this.is_can_hook) {
//you can do any thing before stalker trace so
//trace_so();
anti_frida_check();
hook_zlib();
//hook_C918();
}
}
}
);
}
setImmediate(hook_dlopen);

评论

Related Issues not found

Please contact @1ens to initialize the comment