mcpField
D
devirtualizing-vm-protected-code

devirtualizing-vm-protected-code

github.com/trilwu安全17754 次安装12 周前更新
代码仓库

关于 devirtualizing-vm-protected-code

devirtualizing-vm-protected-code 是用于分析二进制文件中自定义虚拟机保护逻辑的逆向工程技能。它介绍从定位虚拟机、梳理处理器到提取字节码并简化提升结果的分步流程,适用于分析受保护代码的人员。

主要功能

  1. 01定位虚拟机入口、分派器和出口
  2. 02还原虚拟上下文与操作码解码
  3. 03映射处理器及指令语义
  4. 04提取虚拟字节码
  5. 05提升并简化指令
  6. 06结合执行跟踪与符号执行

适用场景

  1. 01还原许可检查或加密例程
  2. 02分析 VMProtect 或 Themida 保护的函数
  3. 03跟踪目标路径而非整个虚拟机
  4. 04解包二进制文件后进行去虚拟化

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trilwu/secskills --skill devirtualizing-vm-protected-code

安装后在 Claude Code 中输入/devirtualizing-vm-protected-code确认已加载。

详细介绍

还原受虚拟机保护的代码

虚拟化混淆会将原生指令替换为自定义虚拟机的字节码,并将虚拟机嵌入二进制文件中,再通过解释器运行这些字节码。原始逻辑并没有消失,只是用一种需要先还原的指令集来表达。反虚拟化是一套固定流程:找到虚拟机、理解其处理程序、提取字节码,再将其提升为可读的形式。混淆器会在每次构建时改变,因此,真正持久的技能是这套流程,而非某个工具。

适用场景

  • 某个函数变成了大型的 fetch-decode-dispatch 循环,并使用处理程序表,而非普通控制流
  • 由 VMProtect、Themida/WinLicense、Oreans Code Virtualizer 或自定义操作码虚拟机保护的二进制文件
  • 还原虚拟化函数中的算法(许可证检查、加密例程、反作弊逻辑)
  • 解包后发现真实代码经过了虚拟化,而不只是打包

不适用场景

  • 对打包或受保护的二进制文件进行解包、转储和修复导入表——这属于 unpacking-protected-binaries,而且应当先做:先解除外层保护,再对其中暴露出的虚拟化核心进行反虚拟化。
  • 普通(非虚拟化)混淆——垃圾代码、不透明谓词、字符串加密——属于 analyzing-binaries 的常规工作。
  • 虚拟化或混淆的 JavaScript——reversing-obfuscated-javascript。
  • 利用还原出的逻辑中的漏洞——exploiting-memory-corruption。

流程

1. 定位虚拟机。 找到从原生代码切换到虚拟代码的位置:保存原生上下文并设置虚拟机的 vm_enter 存根;获取下一个虚拟操作码并通过处理程序表跳转的分发器循环;以及恢复原生上下文的 vm_exit。分发器是后续所有工作的锚点。

2. 还原虚拟机架构。 确定虚拟上下文——保存虚拟机寄存器和虚拟指令指针的结构——以及分发器如何将操作码解码为处理程序索引。记录虚拟机的形态:基于栈还是基于寄存器、操作码编码方式,以及字节码指针是否经过密钥或滚动混淆。

3. 理解处理程序。 每个处理程序都实现一条虚拟指令——类似加法、加载、存储、异或、压栈或原生调用的微操作。逐个分析处理程序;对单个处理程序进行符号执行(Triton、miasm)能比手动阅读更快地得出其语义,因为即使外围虚拟机十分庞大,处理程序本身仍然很小,且侧重于副作用。建立“操作码 → 语义”映射表。

4. 提取字节码。 理解处理程序后,读取分发器遍历的虚拟指令流——也就是用虚拟机指令集编写的实际程序。

5. 提升并简化。 将虚拟指令转换为 IR,并运行优化遍——常量折叠、死代码消除、窥孔优化——让冗长的虚拟指令尽可能还原出原始逻辑。基于 VTIL 的工具(以及针对 VMProtect x64 的 NoVmp)在这一步尤为出色:它们会将代码提升为可优化的 IR 并进行简化,把数千条虚拟操作压缩成少数几条真正的操作。如果没有适用于目标虚拟机的现成工具,也可以用 Triton 和 miasm 采用同样的提升与简化方法。

静态分析与动态分析

可以静态研究处理程序,但对于特定的虚拟化函数,动态执行跟踪——捕获给定输入实际运行的处理程序序列——通常是更快的切入方式:它能告诉你哪些处理程序相关以及它们的执行顺序,因此你可以还原实际执行的路径,而不必还原整个虚拟机。将两者结合起来:通过跟踪找出相关处理程序,通过符号执行获取其语义,再提升跟踪到的字节码。

预期

  • 没有通用按钮。 VMProtect 和 Themida 各不相同,不同版本也有差异,自定义 VM 更是毫无共通之处。现成的反虚拟化工具针对特定版本的保护器,换个版本就会失效;应将它们视为流水线中的加速工具,而非替代方案。
  • 核心部分可以恢复,即使无法还原整体。 你很少需要对整个二进制文件进行反虚拟化——你需要的是包含算法的那个函数。把范围限定在该函数上。
  • 存在嵌套和会变化的 VM。 有些保护器会在虚拟机内部进行虚拟化,或在每次构建时改变处理程序。一次恢复一层。

应当摒弃的自我安慰

  • “工具已经完成反虚拟化,所以我可以收工了。” 自动反虚拟化工具会匹配特定版本的保护器,在其他版本上可能悄无声息地产生不完整或错误的输出。请根据二进制文件的实际行为验证恢复出的逻辑。
  • “我必须对整个二进制文件进行反虚拟化。” 你需要的是目标函数。跟踪到该函数,只提升实际运行的代码;对整个二进制文件进行反虚拟化通常是在白费力气。
  • “处理程序太大了,看不懂。” 处理程序本质上是一个被大量混淆代码包围的微操作。应通过符号执行理解其语义,而不是逐行阅读噪声代码。
  • “它仍然处于加壳状态,我先进行反虚拟化。” 应先脱壳(unpacking-protected-binaries);反虚拟化针对的是解密后显露的代码,在移除外层之前,反调试/反转储防御会不断阻挠你。
  • “虚拟指令流就是答案。” 原始字节码并不是可读的逻辑——你必须提升并简化它。优化过程才能将恢复出的操作码还原为算法。

参考资料

  • unpacking-protected-binaries — 在反虚拟化前移除加壳/反调试机制
  • analyzing-binaries — 对恢复并完成反虚拟化的代码进行通用逆向工程
  • reviewing-cryptography — 当虚拟化例程用于加密/许可证检查时
  • exploiting-memory-corruption — 利用恢复出的逻辑中的漏洞

评论

支持 Markdown