经过一段时间的优化,现已开源 d54K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6&6L8%4g2J5i4K6u0V1k6$3W2@1i4K6u0r3K9h3!0K6i4K6u0V1M7h3u0V1K9g2)9J5k6s2c8J5j5h3y4W2M7R3`.`.。
功能范围不变,主要是把两个长期靠"碰运气"的用法补齐了。
旧行为:trace 一旦延时了n秒后,并且执行到起始地址就记录,不看这次调用带的是什么。于是第一次空调用就把 count=1 的记录机会占掉,真正想要的那次反而没被记下来。
现在:在 Trace 编辑页的「触发条件(可选)」里加条件,满足任意一条才记录。这样就可以对指定的url的签名算法进行 trace,或者是满足指定字节开头的请求体加密算法进行 trace。
典型场景——只 trace 指定 URL 的那次请求:
不匹配时的诊断(按 1/10/100/1000… 次递增输出,不会刷屏):
注意:条件配错会拒掉整条 trace(而不是退化成无条件),这是故意的 —— 静默失效会让你以为过滤在生效。日志里会写明 bad trigger: ...。
要观察的数据经常不在寄存器里,而在 [x0+0x10]、[[x0+8]+0x10] 甚至更深的地方。现在在「寄存器/取址表达式」那一栏点 ✎ 输入取址表达式… 直接写地址:
同一套表达式在监视、触发条件、Hook 的写入目标三处通用(Hook 那处写入语义不对称,数值改寄存器只支持 32/64 位,详见上文「Hook:真实修改数据」)。
⚠️ x17 是 Dobby 跳板占用的临时寄存器,到达本项目跳板前就可能被改写,不要把它当成原程序的可靠值。
表达式语法本身很小,真正需要的是"你要的字段在几层指针之后"这个判断。把下面这些一起丢给 AI,基本一次就能写对:
实测:用这个功能配合 AI,可以解决某社媒 App 的 VMP。大致流程就是:导出一个 trace 的配置文件,然后丢给 AI,跟 ta 说:
众所周知,trace 在算法分析中的地位举足轻重。但在 iOS 上,用 Frida Stalker 不够稳定、也容易被检测到;用 unidbg 或 chomper 又得补一大堆环境。所以今天,Ta来了!Ta 来了!Ta带着 QBDI 和 Dobby 走来了,不仅有着简单的界面,还有着实实在在的功能。
这是本人在二进制分析过程中结合大模型开发的一个工具,欢迎大家交流学习,目前已开源。
QBDI(QuarkslaB Dynamic binaryInstrumentation)是一款动态二进制插桩框架。简单说,它能把一段代码"托管"到自己的虚拟环境里执行,每执行一条指令都回调一次——于是你就能逐条指令地观察目标代码怎么跑、寄存器和内存怎么变,而不用改动原始二进制。
早期 QBDI 在 iOS 中支持有限,但官网最新版已经正式支持 iOS ARM64。这也是本项目选择它的直接原因:能在越狱 iPhone 上稳定地做指令级 trace。
QBDI 只解决"逐条指令记录"这件事,但它本身不负责把自己挂到目标代码上——你得先有办法在某个地址"插一脚",把控制权交给 QBDI。
这一步就交给 Dobby。Dobby 是一个 inline hook 库,负责在指定地址下钩子。二者分工很清晰:
一个管"从哪进",一个管"怎么记",配合起来才能实现"在函数中间任意一段,逐指令 trace"的效果。
每 trace 到一条指令,日志里会输出一行,格式如下:
为了让日志不至于爆炸,寄存器采用增量输出:
寄存器值统一以 16 位十六进制显示(如 0x000000016fdff8a0)。
在规则的「记录内容(logMask)」里勾选 向量寄存器(VREG),就会额外记录向量寄存器 v0–v31。它们和通用寄存器一样采用增量输出,但单独占一行、以 V{...} 开头:
每个向量寄存器是 128 位,以 32 位十六进制显示(高 64 位在前、低 64 位在后)。
向量寄存器数据量大,默认不开。调试 NEON、加解密等涉及向量运算的代码时再勾选。
插件顶部有一个总开关,它是所有规则的总闸。关闭时,即使 trace 条目已经配好,规则也不会生效。所以开始 trace 前,先确认总开关是打开的。

在某条 trace 条目上右滑,可以停用这条规则——规则还在,只是暂时不跑,方便随时切换。

在某条 trace 条目上左滑,则可以导出、复制或删除这条规则。

如果之前创建并导出过规则,直接选 【导入 Tracer】 就能复用,省去重新配置。下面介绍从零创建一条新规则。

进入后,先选定要 trace 的目标 App,再填入目标模块名,以及 trace 的起始地址和结束地址。
其中「延迟」是指等程序启动、加载完相关库之后再开始 trace,留几秒缓冲能避免模块还没就位就 hook 失败。「trace 次数」通常设为 1 就够了。
