首页
社区
课程
招聘
[原创][推荐][原创]用奥卡姆剃刀解决 ollvm 间接跳转和函数调用
发表于: 6天前 870

[原创][推荐][原创]用奥卡姆剃刀解决 ollvm 间接跳转和函数调用

6天前
870

上篇介绍了 native 去混淆中字符串加解密的技巧,本篇聚焦去除 native 中的间接跳转(indirect jump)和间接函数调用(indirect call)混淆。这类混淆经常被大厂 APP 使用,用以增加静态分析的难度和时间成本。

间接跳转与间接调用的本质是隐藏静态控制流:静态分析无法直接得知某条跳转或调用会落到哪个目标。最直接的思路是让程序运行一次,记录实际执行时的跳转/调用目标,然后把这些目标 patch 回二进制,从而恢复可读的控制流。

本文介绍两种简单、高效且实践可行的“暴力”修复思路,无需完整模拟环境或复杂的符号化执行:

对间接跳转与间接调用实现感兴趣的朋友,可以参考 ollvm 混淆项目:
7daK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6w2L8$3#2A6e0h3!0W2i4K6u0r3b7i4u0C8j5i4u0A6
d5dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6S2L8h3W2E0L8#2)9J5c8X3N6G2M7X3!0F1
671K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6p5M7X3g2S2L8g2y4G2N6h3I4W2i4K6u0r3L8$3I4D9N6X3@1I4y4H3`.`.

思路概述:

对于只需还原“大体执行逻辑”而不关心精确分支行为的场景,可以直接把函数内的所有 BR/BLR(或类似的间接跳转/调用指令)替换为 NOP,然后合并基本块。这样静态反编译会把原本被混淆的控制流线性化,便于快速查看调用关系与整体逻辑。

适用场景:

优缺点:

具体流程(推荐步骤):

示例截图:

运行脚本并合并基本块后的效果(可以看到这里还用到了间接函数调用保护):

思路概述:

通过静态分析先定位所有可能的间接跳转/调用指令(BR、BLR 等),自动生成 Frida hook 脚本,在运行时捕获这些指令的实际目标地址(通常以模块基址的相对偏移记录)。把运行时采集到的目标地址写入日志后,使用 IDA Python 脚本把原来的间接跳转/调用 patch 为直接跳转/调用(或直接把目标地址写回),从而尽可能恢复原始控制流。

优缺点:

具体流程 :

示例流程截图:
静态分析 修复前的控制流与伪代码:

运行 fix_blr_2_nop.py 作为预处理(可选):

生成 Frida hook 脚本:

调整脚本中的模块名并以 spawn 模式注入:

将 Frida 输出保存到日志文件,运行IDA 脚本 fix_indirect_jump.py 解析并 patch:

补丁生效后刷新伪代码:

小提示与实践建议:

本文给出两种“暴力但实用”的思路来处理基于 ollvm 的间接跳转与间接函数调用混淆:

两者结合使用,通常能大幅降低分析成本并较好地恢复可读控制流。

代码仓库: 05aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6A6L8h3t1@1k6r3@1@1L8W2)9J5c8V1c8W2j5h3c8D9P5g2)9J5k6o6x3H3x3o6l9`.

  • 方法1:暴力 NOP(快速但破坏分支信息)
  • 方法2:利用 Frida 批量 hook(更精确,但依赖实际执行路径)
  • 想快速定位函数调用、数据访问,而不要求分支精确还原;
  • 分析时间紧张,需要先得到可读伪代码以便后续调查。
  • 优点:快捷、无需运行环境或动态跟踪;
  • 缺点:破坏原始控制流,条件分支(if/while)将丢失,导致反编译器无法恢复分支语义。
  • 从函数入口向后扫描到下一个 RET(或函数结束)位置;
  • 列出这一区间内的 BR 指令地址;
  • 将这些指令 patch 为 NOP 并尝试合并基本块;
  • 优点:能恢复很多实际执行过的跳转/调用,得到更准确的控制流;
  • 缺点:不能覆盖未执行到的路径;条件跳转对应的分支如果未走到也无法修复;需要可运行环境并能加载目标 SO。
  • 使用 Frida 的 spawn + resume 或 frida -f 来启动并注入;
  • 让程序执行到这些间接跳转/调用位置;
  • 先用方法1 快速线性化函数,得到可读伪代码,再针对剩余的间接函数调用用方法2 精修;
  • 确保 Frida hook 输出包含模块相对偏移;
  • 对于未执行到的分支,可以考虑构造输入或模拟路径以触发更多分支,但工作量会增加;
  • patch 不满意,可以Ctl + ALT + P 打开补丁界面,把补丁删除后,F5刷新。
  1. 在 IDA 中把光标移动到目标函数入口;
  2. 运行脚本 fix_blr_2_nop.py ,脚本会:
    • 从函数入口向后扫描到下一个 RET(或函数结束)位置;
    • 列出这一区间内的 BR 指令地址;
    • 将这些指令 patch 为 NOP 并尝试合并基本块;
  3. 刷新反编译(F5)观察伪代码并继续人工分析。
  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 来启动并注入;
    • 让程序执行到这些间接跳转/调用位置;
  5. 保存日志:把 Frida 的输出保存为文本文件;
  6. 在 IDA 中运行补丁脚本:使用 fix_indirect_jump.py(或自写脚本)解析日志并将间接跳转/调用替换为直接跳转/调用或填写目标地址;
  7. 刷新反编译查看修复结果并人工验证。

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 6天前 被dreameriii编辑 ,原因: 链接
收藏
免费 69
支持
分享
最新回复 (25)
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
感谢分享
5天前
0
雪    币: 105
活跃值: (2212)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
666666666666
5天前
0
雪    币: 260
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
11
5天前
0
雪    币: 4978
活跃值: (5039)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
66666
5天前
0
雪    币: 104
活跃值: (7074)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
tql
5天前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
6666
5天前
0
雪    币: 6
活跃值: (2194)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
6666
5天前
0
雪    币: 2356
活跃值: (2886)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
666
5天前
0
雪    币: 1647
活跃值: (2798)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
10
666
5天前
0
雪    币: 8195
活跃值: (4698)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
学习学习
5天前
0
雪    币: 507
活跃值: (4217)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
看看
4天前
0
雪    币: 221
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
666
4天前
0
雪    币: 1614
活跃值: (2460)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
666
4天前
0
雪    币: 275
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
69666
4天前
0
雪    币: 204
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
666
3天前
0
雪    币: 71
活跃值: (1748)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
666
3天前
0
雪    币: 3
活跃值: (937)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
你的帖子非常有用,感谢!
2天前
0
雪    币: 13
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
fd
2天前
0
雪    币: 13
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
直接trace,blr和br打印调用
2天前
0
雪    币: 8605
活跃值: (6282)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
感谢分享
2天前
0
雪    币: 223
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
学习
2天前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
666
2天前
0
雪    币: 216
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24
1
2天前
0
雪    币: 740
活跃值: (2497)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
25
666
2天前
0
游客
登录 | 注册 方可回帖
返回