文章总结: 本文针对ollvm混淆中的间接跳转与调用,提出两种实用修复方案:一是暴力NOP指令以快速线性化控制流,便于初步分析;二是利用Frida动态Hook捕获真实跳转目标并Patch回二进制,实现精确还原。建议结合两者,先用NOP粗略定位,再用动态方法精修,有效降低静态分析成本。 综合评分: 91 文章分类: 逆向分析,二进制安全,移动安全,安全工具
用奥卡姆剃刀解决 ollvm 间接跳转和函数调用
dreameriii dreameriii
看雪学苑
2026年1月19日 18:03 上海
本篇聚焦去除 native 中的间接跳转(indirect jump)和间接函数调用(indirect call)混淆。这类混淆经常被大厂 APP 使用,用以增加静态分析的难度和时间成本。
#
间接跳转与间接调用的本质是隐藏静态控制流:静态分析无法直接得知某条跳转或调用会落到哪个目标。最直接的思路是让程序运行一次,记录实际执行时的跳转/调用目标,然后把这些目标 patch 回二进制,从而恢复可读的控制流。
本文介绍两种简单、高效且实践可行的“暴力”修复思路,无需完整模拟环境或复杂的符号化执行:
- 方法1:暴力 NOP(快速但破坏分支信息)
- 方法2:利用 Frida 批量 hook(更精确,但依赖实际执行路径)
对间接跳转与间接调用实现感兴趣的朋友,可以参考 ollvm 混淆项目: https://github.com/KomiMoe/Arkari https://github.com/amimo/goron https://github.com/DreamSoule/ollvm17
#
01
方法1:暴力 NOP
思路概述:
对于只需还原“大体执行逻辑”而不关心精确分支行为的场景,可以直接把函数内的所有 BR/BLR(或类似的间接跳转/调用指令)替换为 NOP,然后合并基本块。这样静态反编译会把原本被混淆的控制流线性化,便于快速查看调用关系与整体逻辑。
适用场景:
- 想快速定位函数调用、数据访问,而不要求分支精确还原;
- 分析时间紧张,需要先得到可读伪代码以便后续调查。
优缺点:
- 优点:快捷、无需运行环境或动态跟踪;
- 缺点:破坏原始控制流,条件分支(if/while)将丢失,导致反编译器无法恢复分支语义。
具体流程(推荐步骤):
- 在 IDA 中把光标移动到目标函数入口;
- 运行脚本 fix_blr_2_nop.py ,脚本会:
- 从函数入口向后扫描到下一个 RET(或函数结束)位置;
- 列出这一区间内的 BR 指令地址;
- 将这些指令 patch 为 NOP 并尝试合并基本块;
- 刷新反编译(F5)观察伪代码并继续人工分析。
示例截图:
运行脚本并合并基本块后的效果(可以看到这里还用到了间接函数调用保护):
#
02
方法2:使用 Frida 批量 Hook(更精确)
思路概述:
通过静态分析先定位所有可能的间接跳转/调用指令(BR、BLR 等),自动生成 Frida hook 脚本,在运行时捕获这些指令的实际目标地址(通常以模块基址的相对偏移记录)。把运行时采集到的目标地址写入日志后,使用 IDA Python 脚本把原来的间接跳转/调用 patch 为直接跳转/调用(或直接把目标地址写回),从而尽可能恢复原始控制流。
优缺点:
- 优点:能恢复很多实际执行过的跳转/调用,得到更准确的控制流;
- 缺点:不能覆盖未执行到的路径;条件跳转对应的分支如果未走到也无法修复;需要可运行环境并能加载目标 SO。
具体流程 :
1.静态定位目标指令:在 IDA 中扫描待修复函数,记录 BR/BLR 指令地址;
2.自动生成 Frida 脚本:ALT+F7运行脚本toolchain_trace_indirect_jumps.py生成一个包含所有待 hook 地址的 Frida 脚本;
3.调整脚本:把脚本中的模块名改为你要分析的 so 名称,确认 log 输出格式(建议输出模块偏移、指令地址、寄存器值等);
4.启动被测进程并注入(建议使用 spawn 模式以便在早期捕获流程):
- 使用 Frida 的 spawn + resume 或 frida -f 来启动并注入;
- 让程序执行到这些间接跳转/调用位置;
-保存日志:把 Frida 的输出保存为文本文件;
-在 IDA 中运行补丁脚本:使用 fix_indirect_jump.py(或自写脚本)解析日志并将间接跳转/调用替换为直接跳转/调用或填写目标地址;
-刷新反编译查看修复结果并人工验证。
示例流程截图:
静态分析 修复前的控制流与伪代码:
运行 fix_blr_2_nop.py 作为预处理(可选):
生成 Frida hook 脚本:
调整脚本中的模块名并以 spawn 模式注入:
将 Frida 输出保存到日志文件,运行IDA 脚本 fix_indirect_jump.py 解析并 patch:
补丁生效后刷新伪代码:
小提示与实践建议:
- 先用方法1 快速线性化函数,得到可读伪代码,再针对剩余的间接函数调用用方法2 精修;
- 确保 Frida hook 输出包含模块相对偏移;
- 对于未执行到的分支,可以考虑构造输入或模拟路径以触发更多分支,但工作量会增加;
- patch 不满意,可以Ctl + ALT + P 打开补丁界面,把补丁删除后,F5刷新。
#
03
推荐工作流(结合使用)
- 先用方法1 对关键函数进行快速线性化,快速定位调用链与数据流;
- 对仍保留大量间接调用的位置,生成 Frida hook 并运行获取实际目标;
- 用 IDA Python 将运行时采集的目标 patch 回文件;
- 手工检查复杂分支和关键算法,必要时结合动态调试、符号化执行或手工分析恢复剩余逻辑。
总结
本文给出两种“暴力但实用”的思路来处理基于 ollvm 的间接跳转与间接函数调用混淆:
- 方法1(暴力 NOP)适合快速获得可读伪代码,节省时间;
- 方法2(Frida 批量 hook)能更精确地恢复实际执行路径但依赖于程序运行时覆盖到相关分支。
两者结合使用,通常能大幅降低分析成本并较好地恢复可读控制流。
代码仓库:https://github.com/imb4dm4n/Deadly-3000
#
看雪ID:dreameriii
https://bbs.kanxue.com/user-home-715292.htm
*本文为看雪论坛优秀文章,由 dreameriii 原创,转载请注明来自看雪社区
往期推荐
逆向分析某手游基于异常的内存保护
解决Il2cppapi混淆,通杀DumpUnityCs文件
记录一次Unity加固的探索与实现
DLINK路由器命令注入漏洞从1DAY到0DAY
量子安全 quantum ctf Global Hyperlink Zone Hack the box
球分享
球点赞
球在看
点击阅读原文查看更多
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:看雪学苑 dreameriii dreameriii《用奥卡姆剃刀解决 ollvm 间接跳转和函数调用》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论