重型工具McSema 2.0 - Trail of Bits博客
Peter Goodman
2018年1月23日
binary-ninja, compilers, mcsema
四年前,我们发布了McSema,我们的x86到LLVM位码二进制转换器。自那时起,它不断扩展和优化;我们添加了x86-64支持,进行了性能优化,并改进了其可用性和文档。
然而,过去几年中,改进的不只是McSema。同时,程序越来越多地采用现代x86特性,如高级向量扩展(AVX)指令,这些指令操作256位宽的向量寄存器。适应这些变化是艰巨但可实现的工作。然后,我们的提升目标扩展到包括AArch64,这是现代智能手机使用的架构。那时我们意识到,我们需要退后一步,加强McSema的核心。这一重点转变带来了回报;现在McSema可以将AArch64二进制文件转译为x86-64!继续阅读以获取更多细节。
进入龙的时代
今天我们宣布McSema 2.0的正式发布!此版本极大地推进了McSema的核心,并为我们的二进制提升器带来了几个激动人心的新进展:
- Remill。指令语义现在完全分离到Remill,它们自己的库中。McSema是一个使用该库进行二进制提升的客户端。借用类比,McSema之于Remill,就像Clang之于LLVM。请关注未来使用Remill的项目。
- 简化语义。McSema和Remill的分离使得添加对新指令的支持更容易。在Remill中,指令语义可以直接用C++表达,并由Clang自动编译为LLVM位码。
- AArch64(64位ARMv8)。切换到使用Remill作为语义后端意味着McSema 2从一开始就支持多种架构。它不仅适用于x86和x86-64二进制文件,还支持提升64位ARMv8程序。
- SSE3/4和AVX支持。McSema现在支持提升利用高级向量指令集的程序。
- 更好的控制流图恢复。提升错误的常见来源是差的控制流恢复。我们改进了控制流恢复过程,使其更简单、更快、更准确。McSema的控制流图恢复也开始纳入高级特性,如提升全局变量和栈变量。
- Binary Ninja支持。McSema现在有beta支持,通过Binary Ninja恢复程序控制流。
McSema 2.0正在积极开发中,并快速改进和增加特性。我们希望使使用和 hacking McSema比以往更容易和更 accessible。
看它翱翔:使用McSema 2
McSema的最大变化是切换到使用Remill进行指令语义,以及随后的AArch64支持。这一改进的一个好演示是展示McSema可以反汇编AArch64二进制文件,将其提升为位码,然后将该位码重新编译为x86-64机器代码。让我们开始吧!
获取McSema
第一步是下载并安装代码。目前,Linux是McSema支持的主要平台;然而,我们正在努力支持macOS和Windows构建。如果你的目标是提升Windows二进制文件,那么不用担心!Linux构建的McSema将乐意分析Windows二进制文件。
上述链接的说明提供了更多细节,你应该遵循(例如获取依赖项、解决常见错误等),但下载和安装McSema的基本步骤如下:
|
|
这些命令将克隆Remill和McSema,调用一个通用构建脚本,在~/data/remill-build目录中编译两个项目,然后将项目安装到系统上。
反汇编我们的第一个二进制文件
使用McSema通常是一个两步或三步过程。第一步总是使用mcsema-disass命令行工具将二进制文件反汇编为“控制流图”文件。此文件包含程序二进制文件的所有原始代码和数据,但组织成逻辑分组,如变量、函数、指令块和它们之间的引用。
我们将使用Felipe Manzano的maze,编译为AArch64程序二进制文件,作为我们的运行示例。它是一个交互式命令行游戏,要求用户解决迷宫。maze的预编译二进制文件可以在McSema的examples/Maze/bin目录中找到。
|
|
上述步骤将从maze程序生成控制流图(CFG)文件,将CFG文件保存到/tmp/maze.aarch64.cfg。如果你在家跟随操作,没有许可版本的IDA Pro,但有Binary Ninja许可,那么你可以更改传递给–disassembler选项的值,指向Binary Ninja可执行文件(即–disassembler /opt/binaryninja/binaryninja)。最后,如果你是那些radare2坚持者之一,那么不用担心——我们已经为maze二进制文件制作了CFG文件。
提升到位码
第二步是使用mcsema-lift-3.9命令行工具将CFG文件提升为LLVM位码。这里的3.9不是McSema版本;它是LLVM工具链版本。LLVM是一个快速发展的项目,这有时意味着有趣的项目(例如KLEE)被遗留,只适用于较旧的LLVM版本。我们试图尽可能简单地让用户获得使用McSema的好处——这就是为什么McSema使用LLVM版本3.5及更高版本。事实上,使用McSema 2,你现在可以在系统上安装多个版本的McSema,每个针对不同的LLVM版本。关于这一点已经足够,是时候提升一些重量了!
|
|
上述命令指示McSema将提升的位码保存到文件/tmp/maze.aarch64.bc。–explicit_args命令行标志是McSema 2的一个新特性,模拟了McSema 1的原始行为。如果你的目标是执行提升位码的静态分析或符号执行,那么你将希望使用此选项。类似地,如果你正在将从一种架构(例如AArch64)提升的位码编译为另一种架构(例如x86-64)的机器代码,那么你也需要此选项。另一方面,如果你的目标是将提升的位码编译回相同架构的可执行程序(如Cyber Fault-tolerance Attack Recovery程序的情况),那么你不应使用–explicit_args。
将位码编译回可运行程序
终于到了让魔法发生的时候了——我们将从AArch64程序获取位码,并使其在x86-64上运行。我们方便地确保了一个Clang编译器与McSema一起安装,并且以不与你已安装的任何其他编译器冲突的方式。以下是使用该Clang将提升的位码编译为名为/tmp/maze.aarch64.lifted的可执行文件的方法。
|
|
注意:如果由于某种原因remill-clang-3.9对你不起作用,那么你也可以使用~/data/remill-build/libraries/llvm/bin/clang。
解决迷宫
我们现在已成功将AArch64程序二进制文件转译为x86-64程序二进制文件。等等,什么?是的,我们真的做到了。运行转译版本显示正确的输出,提示我们如何玩游戏的说明。
|
|
但如果——尽管我们尽力——我们无法解决迷宫?那不会是一个问题,因为我们总是可以使用KLEE符号执行器为我们解决迷宫。
你的新锻炼 routine
我们已经练习了所有动作,你的新锻炼 routine 准备好了。你 routine 的第1天是反汇编二进制文件并制作CFG文件。
|
|
第2天是你的提升日,我们将CFG文件提升为LLVM位码。
|
|
第3天以一些紧张的编译结束你的一周,从提升的位码产生新的机器代码可执行文件。
|
|
最后,不要忘记你的伸展运动。我们想确保那些肌肉仍然工作。
|
|
如果你想提升,就跟我来
Maze转译和符号执行演示只是你可以用McSema 2做的事情的表面。最终目标一直是使二进制文件能够像源代码一样被对待。随着McSema 2中的众多改进,我们正接近那个理想。在接下来的几个月里,我们将更多地讨论McSema 2的其他激动人心的特性(如栈和全局变量恢复)以及Trail of Bits和其他人如何使用McSema。
我们很乐意与你讨论McSema以及它如何解决你的二进制分析和转换问题。我们总是在Empire Hacking Slack和通过我们的联系页面 available。
不过现在,系上你的腰带——是时候进行一些重型提升了。McSema版本2已为你的二进制文件准备好。
如果你喜欢这篇文章,分享它:
Twitter
LinkedIn
GitHub
Mastodon
Hacker News