Heavy lifting with McSema 2.0
四年前,我们发布了McSema,我们的x86到LLVM位码二进制翻译器。自那时起,它不断扩展和增强;我们添加了x86-64支持,进行了性能优化,并改进了其可用性和文档。
然而,过去几年中,不仅仅是McSema在改进。同时,程序越来越多地采用现代x86特性,如高级向量扩展(AVX)指令,这些指令操作256位宽的向量寄存器。适应这些变化是艰巨但可实现的工作。然后,我们的提升目标扩展到包括AArch64,这是现代智能手机使用的架构。那时我们意识到,我们需要退后一步,加强McSema的核心。这一重点的改变得到了回报;现在McSema可以将AArch64二进制文件转译为x86-64!继续阅读以获取更多细节。
Enter the dragon
今天我们宣布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现在支持提升利用高级向量指令集的程序。
- 更好的CFG恢复。提升错误的常见来源是控制流恢复不佳。我们改进了控制流恢复过程,使其更简单、更快、更准确。McSema的CFG恢复也开始纳入高级特性,如提升全局变量和栈变量。
- Binary Ninja支持。McSema现在具有通过Binary Ninja恢复程序控制流的测试版支持。
McSema 2.0正在积极开发中,并快速改进和增加特性。我们希望使使用和黑客McSema比以往更容易和更易访问。
See it soar: Using McSema 2
McSema的最大变化是切换到使用Remill进行指令语义,以及随后的AArch64支持。这一改进的一个很好的演示是展示McSema可以反汇编AArch64二进制文件,将其提升为位码,然后将该位码重新编译为x86-64机器代码。让我们开始吧!
Getting McSema
第一步是下载并安装代码。目前,Linux是McSema支持的主要平台;然而,我们正在努力支持macOS和Windows构建。如果你的目标是提升Windows二进制文件,那么不用担心!Linux构建的McSema可以愉快地分析Windows二进制文件。
上述链接的说明提供了更多你应该遵循的细节(例如获取依赖项、解决常见错误等),但下载和安装McSema的基本步骤如下:
|
|
这些命令将克隆Remill和McSema,调用一个通用构建脚本,在~/data/remill-build目录中编译两个项目,然后将项目安装到系统上。
Disassembling our first binary
使用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文件。
Lifting to bitcode
第二步是使用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。
Compiling bitcode back to runnable programs
终于到了让魔法发生的时候了——我们将从AArch64程序获取位码,并使其在x86-64上运行。我们方便地确保了一个Clang编译器与McSema一起安装,并且以不与你已安装的任何其他编译器冲突的方式安装。以下是使用该Clang将提升的位码编译为名为/tmp/maze.aarch64.lifted的可执行文件的方法:
|
|
注意:如果由于某种原因remill-clang-3.9对你不起作用,那么你也可以使用~/data/remill-build/libraries/llvm/bin/clang。
Solving the maze
我们现在已成功将AArch64程序二进制文件转译为x86-64程序二进制文件。等等,什么?是的,我们真的做到了。运行转译版本显示正确的输出,提示我们如何玩游戏。
|
|
但是,如果我们尽力尝试,却无法解决迷宫呢?那不会是一个问题,因为我们总是可以使用KLEE符号执行器为我们解决迷宫。
Your new workout routine
我们已经练习了所有动作,你的新锻炼程序准备好了。你程序的第一天是反汇编二进制文件并制作CFG文件。
|
|
第二天是你的提升日,我们将CFG文件提升为LLVM位码。
|
|
第三天以一些紧张的编译结束你的一周,从提升的位码生成新的机器代码可执行文件。
|
|
最后,不要忘记你的伸展运动。我们希望确保那些肌肉仍然工作。
|
|
Come with me if you want to lift
Maze转译和符号执行演示只是你可以用McSema 2做的事情的表面。最终目标一直是使二进制文件能够像源代码一样被对待。随着McSema 2中的众多改进,我们正接近这一理想。在接下来的几个月里,我们将更多地讨论McSema 2的其他激动人心的特性(如栈和全局变量恢复)以及Trail of Bits和其他人如何使用McSema。
我们很乐意与你讨论McSema以及它如何解决你的二进制分析和转换问题。我们总是在Empire Hacking Slack和通过我们的联系页面上可用。
不过现在,系好你的腰带——是时候进行一些繁重的工作了。McSema版本2已为你的二进制文件准备好。
如果你喜欢这篇文章,分享它: Twitter LinkedIn GitHub Mastodon Hacker News