Frida的Stalker中transform的逻辑
除了官网文档介绍了内部具体实现机制和过程之外:
对于,想要搞懂如何利用transform去调试代码来说:
需要明白的逻辑是:
此处代码:
Interceptor.attach(funcRealStartAddr, {
onEnter: function(args) {
...
var curTid = Process.getCurrentThreadId();
console.log("curTid=", curTid);
Stalker.follow(curTid, {
events: {
call: true, // CALL instructions: yes please
ret: false, // RET instructions
exec: false, // all instructions: not recommended as it's
block: false, // block executed: coarse execution trace
compile: false // block compiled: useful for coverage
},
// transform: (iterator: StalkerArm64Iterator) => {
transform: function (iterator) {
...
触发到的transform的iterator
来说:
- 每次触发=每个iterator:都(对应着)单个block=(basic)代码块
- 此处代码块有2种
- 非原始函数代码 ==
isAppCode=false
- 对应着应该是Stalker内部实现原理说的,copy拷贝出的代码
- 其中会额外加上很多逻辑,用于实现Stalker的功能和逻辑
- 估计就是这里说的这些内容
- [原创] sktrace:基于 Frida Stalker 的 trace 工具-Android安全-看雪-安全社区|安全招聘|kanxue.com
- 每当执行到一个基本块,
Stalker
都会做以下几件事:- 对于方法调用,保存
lr
等必要信息 - 重定位位置相关指令,例如:
ADR Xd, label
- 建立此块的索引,如果此块在达到可信阈值后,内容未曾变化,下次将不再重新编译(为了加快速度)
- 根据 transform 函数,编译生成一个新的基本块
GumExecBlock
,保存到GumSlab
。void transform(GumStalkerIterator iterator, GumStalkerOutput output, gpointer user_data)
可以控制读取,改动,写入指令。 - transform 过程中还可通过
void gum_stalker_iterator_put_callout (GumStalkerIterator self,GumStalkerCallout callout, gpointer data, GDestroyNotify data_destroy)
来设置一个当此位置被执行到时的callout
。通过此void callout(GumCpuContext cpu_context, gpointer user_data)
获取cpu
信息。 - 执行一个基本快
GumExecBlock
,开始下一个基本快
- 对于方法调用,保存
- 每当执行到一个基本块,
- [原创] sktrace:基于 Frida Stalker 的 trace 工具-Android安全-看雪-安全社区|安全招聘|kanxue.com
- 所以无需操作具体内部过程,直接忽略即可
- 对应着应该是Stalker内部实现原理说的,copy拷贝出的代码
- 原始函数代码 ==
isAppCode=true
- 是实际运行的代码,才是我们所要关注的代码
- 才会真正的去处理:比如判断是否是对应的(某个偏移量的)代码,然后去打印查看调试寄存器的值等等
- 是实际运行的代码,才是我们所要关注的代码
- 非原始函数代码 ==
此处去通过计算是否是 原始函数代码isAppCode 决定是否处理
具体详见示例代码: