论坛首页 密码学讨论区 阅读主题

[原创]抖音 VMP 分析:从入口到 Dispatch

444 浏览 14 回复
#1 楼主 2026-06-01 21:09:13
抖音 VMP 分析:从入口到 Dispatch

作者: 人生导师
日期: 2026 年 5 月 22 日
版本: 抖音 38.1.0
so 加密文件:libmetasec_ml.so

最近在看抖音的签名保护,发现核心逻辑藏在一个自研的 VMP 里。这篇算是我的分析笔记,记录了从找到 VM 入口到搞清楚 dispatch loop 的过程。水平有限,如果有分析错误的地方欢迎指正。

一、找到 VM 入口
方法:trace + IDA 逐行对照
trace 是执行记录,格式长这样:
行号 : 绝对地址 [偏移] "指令" 寄存器变化
923 : 0x71ee4bd618 [0x2a6618] "sub sp, sp, #0xa0" (r)sp=0x725beaea40 (w)sp=0x725beae9a0

一份 trace 最少五百万行汇编,最多一千一百万行。我手上有三份不同请求的 trace,目前在分析最短的那份(五百万行),另外还有一份七百万行的留着交叉验证。
追法很朴素:从入口开始,一条一条看地址偏移的末位。ARM64 指令固定 4 字节,正常顺序执行的话偏移末位是 0 → 4 → 8 → C → 0 → 4 → 8 → C 循环递增。一旦这个节奏断了——比如从 0x2a6618 突然跳到 0x2ab240——就说明有跳转发生了,这时候去 IDA 里看这条指令是什么:b、bl、blr、还是条件跳转。
但是也要看全,不能只盯末位。有时候两段不连续的代码正好拼在一起,末位看着是连续的,实际已经跳了。所以每次节奏"看起来正常"的时候也得瞄一眼完整偏移有没有突变。
遇到 bl(函数调用)就记录子函数的入口和返回点,确定它的范围。遇到 blr(间接调用)就更要注意,因为目标地址在寄存器里,可能跳到完全不同的地方。
包裹函数和真函数
从 7 神入口 0x2A6E38 往里追,很快遇到一个 bl:
91f : 0x71ee4bf434 [0x2a8434] "bl #0x71ee4c2238" // 包裹函数
922 : 0x71ee4c2240 [0x2ab240] "b #0x71ee4bd618" // 跳到真函数开头

这里的结构是:入口先调用一个包裹函数(wrapper),包裹函数里面再 b 跳转到真正干活的函数。b 不是 bl,不压返回地址,说明这是尾调用——包裹函数本身不做什么事,就是个跳板。
VM 入口定位
继续往下追,找到了关键调用:
c4d0 : 0x71ee4c4544 [0x2ad544] "blr x8" (r)x8=0x71ee4c5a90
c4d1 : 0x71ee4c5a90 [0x2aea90] "sub sp, sp, #0x30" // VM 入口
2e0e3 : 0x71ee4c4548 [0x2ad548] "ldp x29, x30, [sp, #0x20]" // 返回后继续

blr x8 间接调用,跳到 0x2AEA90。从行号看,c4d1 到 2e0e3(返回点),中间执行了差不多 18 万行指令。这就是 VM 的主体了。
对比三份 trace:两份里这个 VM 入口内部自己循环了 11 次,一份循环了 10 次。说明 VM 不是一条直线跑完的,内部有 dispatch loop,根据输入数据的不同,循环次数会变。
但是有个好消息:VM 入口只被外部调用了一次。不用担心别的地方还会再次进入 VM、重新设置初始状态。分析范围是确定的。
VM 前的初始化段
既然 VM 入口只进一次,那进入之前的那段代码就是初始化逻辑——准备 VM 需要的上下文、参数、状态。
确定范围:
c465 : 0x71ee4b46cc [0x29d6cc] "stp x29, x30, [sp, #-0x60]!" // 初始化开始
c4c4 : 0x71ee4b4780 [0x29d780] "bl #0x71ee4c4518" // 调用 VM

从行号 c465(50279)到 c4c4(50372),大概 93 行指令。这段就是进入 VM 前的全部准备工作。
另外还有一个封装函数 0x2AA36C,它是从 7 神入口到 VM 的桥梁。
阶段小结


内容
偏移
状态


7 神入口
0x2A6E38
已定位


包裹函数 → 真函数
0x2A8434 → 0x2A6618
已确认,hook 验证


VM 前初始化段
0x29D6CC ~ 0x29D780
已确定范围


VM 入口
0x2AEA90
已定位,内部循环 10~11 次

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-291314.htm
#2 2026-06-01 21:09:13
加油...
#3 2026-06-01 21:09:13
加油...
#4 2026-06-01 21:09:13
加油
#5 2026-06-01 21:09:13
关于vm可以去看《虚拟机系统与进程的通用平台》这本书,让你对vm有更加深入的了解,vm不关有解释型vm,还有动态二进制翻译的vm。被用于软件保护的大多用的解释型的vm,这样可以隐藏目标程序的指令,然后由vm自己的解释器,解释执行被抽象的vm字节码。像unicorn这种就是一个解释型的vm。
#6 2026-06-01 21:09:13
而且由于arm指令的公开性,几乎所有的vm的解释器在解释这些arm指令时的方法都差不多。或许你可以一边看unicorn是如何解释arm指令集的,然后这些方法和你分析的这个vmp的解释代码应该也是差不多的。
#7 2026-06-01 21:09:13
感谢分享
#8 2026-06-01 21:09:13
其实现在压根不用手工分析handle,直接让ai通过ida mcp来分析直接分分钟都是秒了,然后ai其实对vm指令的识别能力也是远超一般人,将vm指令的trace记录给ai,就算是魔改加密算法直接通过vm指令直接实现也是能精准识别并还原每个具体运算过程,我用ai分析过比这个vm还要复杂的
#9 2026-06-01 21:09:13
安卓逆向test

其实现在压根不用手工分析handle,直接让ai通过ida mcp来分析直接分分钟都是秒了,然后ai其实对vm指令的识别能力也是远超一般人,将vm指令的trace记录给ai,就算是魔改加密算法直接通过 ...
原理还是要搞清楚的
#10 2026-06-01 21:09:13
ldzspace

原理还是要搞清楚的
确实不能完全靠ai,起码还是得知道如何验证ai输出的是否正确,这两天我用deepseek v4pro去分析一个复杂vm的700来个handle也是中途出了一堆问题,要么就是有些handle语义搞错了,要么是typecode没对上,甚至还出过分发表地址搞错的,也是要自己手工验证然后纠错才基本完全搞完
#11 2026-06-01 21:09:13
不过总体来说用ai来分析复杂vm效率还是远超完全自己手动搞
#12 2026-06-01 21:09:13
安卓逆向test

其实现在压根不用手工分析handle,直接让ai通过ida mcp来分析直接分分钟都是秒了,然后ai其实对vm指令的识别能力也是远超一般人,将vm指令的trace记录给ai,就算是魔改加密算法直接通过 ...
AI 的实力是技术带来的,不等于个人能力。技术一直在更新,但核心思路和独立思考,才是真正的立身之本。自己不会推理判断,就没法验证 AI 内容的好坏。它只是个提效工具,它的答案,永远替代不了你自己的思考,看懂小说容易,自己创作却很难。AI 偏向结果导向的逆向输出,绝非什么一步登天的捷径。要是没法借着工具提升自己,那你和其他会用 AI 的人,本质上并无区别。
#13 2026-06-01 21:09:13
xklgl

AI 的实力是技术带来的,不等于个人能力。技术一直在更新,但核心思路和独立思考,才是真正的立身之本。自己不会推理判断,就没法验证 AI 内容的好坏。它只是个提效工具,它的答案,永远替代不了你自己的思考 ...
AI 就好比顶级赛车现在几乎人人都能上手 直线加速谁都会真正拉开差距见真章的还得看弯道技术
#14 2026-06-01 21:09:13
xklgl

AI 的实力是技术带来的,不等于个人能力。技术一直在更新,但核心思路和独立思考,才是真正的立身之本。自己不会推理判断,就没法验证 AI 内容的好坏。它只是个提效工具,它的答案,永远替代不了你自己的思考 ...
确实,但是ai确实能弥补一些能力比如说密码学方面,我自己是完全不懂,现在直接丢vm指令给ai魔改算法照样能识别出来
#15 2026-06-01 21:09:13
感谢分享

请登录后参与讨论

立即登录 注册账号