-
-
[原创]某旅行 App 基于 LR 劫持的 ARM64 控制流混淆逆向分析
-
-
[原创]某旅行 App 基于 LR 劫持的 ARM64 控制流混淆逆向分析
在分析某旅行类 App 的 native 层时遇到这种混淆。so 名就不说了,分析过看到这个混淆模式应该会觉得眼熟——对,思路一脉相承,换了个马甲而已。本文重点在混淆原理和自动化处理,跟目标无关。
在 IDA 中可以看到大量如下模式的调用:
乍看像是普通的函数调用,但 loc_14A8AC 内容很可疑:
只有一条 BL,没有任何逻辑。继续跟进 sub_14C1BC:
这里开始出现异常:函数末尾是 RET,但在此之前 X30 已经被修改,也就是说 RET 实际跳回的地址并不是调用方。
完整执行流追踪如下。
第一步,call site 设置 dispatch key 并跳转:
第二步,trampoline 再次 BL,X30 被覆盖:
这一步是整个混淆的核心——第二个 BL 把 X30 覆盖成了紧跟其后的地址,而这个地址恰好就是跳表的起始位置。
第三步,dispatcher 用 W0 计算跳表下标:
第四步,查表并劫持返回地址:
RET 执行时 X30 已经指向目标地址,call site 原本的 LR(0x158014)就此丢失,执行流不会返回到 LDR+BL 后面,而是直接跳到跳表计算出的目标。
一句话总结:LDR W0, =key + BL trampoline 这两条指令等价于一条 B <target>,目的是伪装成函数调用,破坏 IDA 的控制流图重建。
进一步分析发现,同一个二进制里存在多个 dispatcher,变换指令序列各不相同,例如:
变换顺序和参数不同,但结构完全一致。这意味着不能硬编码参数,需要对每个 dispatcher 动态提取变换链。
注意:patch 写入 idb 后不易撤销,建议跑之前先备份 idb 文件。
patch 前 IDA 伪代码充斥着无意义的函数调用,控制流图在每处 LDR+BL 处断裂,Hex-Rays 无法正确反编译;patch 后每处等价跳转还原为直接 B target,控制流图重新连通,反编译结果可读性大幅提升。
这种混淆的本质是用两次 BL 把跳表基址藏进 X30,再通过修改 X30 劫持 RET 的目标,对反汇编器造成干扰。识别的关键在于 LDR Wx,[X30,X0,SXTX#2] + ADD X30,X30,X0 + RET 这个固定的查表结构——无论变换参数怎么变,这三条指令的组合不变,因此可以可靠地自动化识别和还原。分析过相同类型对这套模式应该不陌生,脚本稍作调整即可复用。
[内核课程]《Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。