ReMASTering Applications by Obfuscating during Compilation
Trail of Bits
August 20, 2014
apple, compilers, darpa, products, reversing
本文讨论了一种新型软件混淆工具包MAST的创建,该工具在LLVM编译器中实现,能够有效阻止即使资源最充足的对手理解程序。我们的实现受到国家级恶意软件使用的有效混淆技术和学术文献中讨论的技术启发。MAST使软件开发人员能够利用为攻击开发的技术来保护应用程序。
MAST是Cyber Fast Track的产物,我们要感谢Mudge和DARPA资助我们的工作。没有他们的支持,这个项目是不可能实现的。MAST现在是Trail of Bits的商业产品,有兴趣将其许可供自己使用的公司应联系info@trailofbits.com。
背景
如今发布软件存在很多风险。曾几何时,逆向工程软件是一个挑战,最好由经验丰富、技术娴熟的逆向工程师以巨大代价解决。对于资金充足的团体来说,逆向工程和重建专有技术是值得的,或者对于聪明但无聊的人来说,生成派对技巧也是值得的。尽管后一类人造成了各种轻微的互联网破坏,但直到相对最近,逆向工程才被广泛视为严重威胁。
然而,随着时间的推移,风险已经上升;犯罪实体、公司甚至国家都对软件漏洞极为感兴趣。这些实体要么寻求保护自己的网络、应用程序、用户,要么攻击他人的网络、应用程序、用户。历史上,软件混淆是“好人”关心的问题,他们有兴趣保护自己的知识产权。不久之后,恶意实体开始混淆自己的工具,以保护被捕获的工具免受分析。
成功混淆的一个近期例子是Gauss恶意软件作者使用的技术;在发现该恶意软件几天后,受人尊敬的恶意软件分析实验室和防病毒公司卡巴斯基实验室公开请求帮助解密部分代码。即使是一家专业公司也遇到足够多的麻烦而寻求外部帮助,这说明混淆可以非常有效。专业研究人员至今无法对Gauss进行去混淆。
动机
考虑到所有这些,我们受到Gauss的启发,创建了一个超越现有分析技术的软件保护系统。我们能否将软件利用和恶意软件混淆技术重新用于最先进的软件保护系统?我们的团队非常熟悉公开可用的辅助逆向工程任务的工具,并考虑了如何显著降低其效能,如果不能完全否认的话。
软件开发人员寻求保护程序中的各类信息。我们的系统必须为每种信息提供同等水平的保护,以满足这些潜在用例:
- 算法:对手对专有技术的了解
- 数据:对专有数据(公司或用户的)的了解
- 漏洞:对程序中漏洞的了解
为了使软件保护系统对开发人员有用,它必须:
- 易于使用:混淆应对我们的开发过程透明,不改变或干扰它。不应需要注释,尽管在某些情况下我们可能需要它们。
- 跨平台:混淆应统一适用于我们使用的所有应用程序和框架,包括可能运行在不同处理器架构上的移动或嵌入式设备。
- 抵御最先进的分析:我们的混淆应超越现有的静态分析工具和技术,需要新的研究进展才能看透。
最后,我们假设攻击者将能够访问静态程序映像;许多软件应用程序将直接可供 dedicated 攻击者访问。例如,对移动应用程序、防病毒签名或软件补丁感兴趣的攻击者将拥有静态程序映像进行研究。
我们的方法
我们决定主要专注于防止静态分析;在这个时代,有很多工具可以静态运行在应用程序二进制文件上,以较少的工作和时间获得信息,许多攻击者精通生成自己特定情境的工具。静态工具通常可以非常快速地运行大量代码,而不需要攻击者拥有执行目标二进制文件的环境。
我们决定采用一组组合技术,包括不透明谓词插入、代码扩散,以及——因为我们最初的范围是iOS应用程序——Objective-C符号混淆。这些使受保护的应用程序在没有环境数据的情况下无法理解,由于别名分析的限制,无法用当前的静态分析工具进行分析,并否认断点、方法名称检索脚本和其他常见逆向技术的有效性。结合起来,这些技术从各个方面攻击逆向工程师的工作流程和工具。
此外,我们在编译器(LLVM)内部完成了所有混淆工作,因为我们希望我们的技术彻底融入整个程序。LLVM可以利用程序知识生成真实的不透明谓词或将扩散的代码隐藏在未采用的虚假路径中,迫使逆向工程师参考程序的环境(可能不可用)来解决哪些指令序列是正确的。在编译器级别进行混淆比在现有二进制文件上操作更可靠:没有代码与数据的混淆或缺少关键应用程序行为。此外,编译器级别的混淆对基于LLVM的当前和未来开发工具是透明的。例如,MAST可以在发布当天混淆Swift——直接从Xcode IDE。
符号混淆
第一种也是最简单的技术是阻碍快速的Objective-C方法名称检索脚本;这当然是变换中最不有趣的部分,但会从iOS应用程序中移除大量人类可读信息。没有专有代码的方法或其他符号名称,更难一目了然地理解程序。
不透明谓词插入
我们应用的第二种技术,不透明谓词插入,并不是新技术。它以前以多种方式完成过,有能力的分析师已经开发出绕过许多常见实现的方法。我们通过插入具有不透明条件和替代分支的谓词创建了更强版本的谓词插入,这些分支对脚本或浏览代码的人来说看起来真实。真实的谓词显著减慢人类分析师的速度,也会通过使图比原始图大得多来减慢操作程序控制流图(CFGs)的工具。增加的CFG大小影响程序的大小和执行速度,但我们的测试表明影响较小或与类似工具一致。
代码扩散
第三种技术,代码扩散,是迄今为止最有趣的。我们采用了面向返回编程(ROP)的思想,并以防御性方式应用它们。
在直接情况下,攻击者利用应用程序中的漏洞并提供自己的代码供目标执行(shellcode)。然而,自从引入如DEP和NX等非可执行数据缓解措施以来,攻击者不得不找到执行恶意代码的方法而不引入任何新内容。ROP是一种利用应用程序中已存在代码的技术。通常,攻击者会在现有程序文本中编译一组短的“gadgets”,每个执行简单任务,然后将它们链接在一起,从一个跳到另一个,以构建他们利用所需的功能——通过在现有程序中跳转有效地创建一个新程序。
我们转换应用程序代码,使其以类似ROP的方式跳转,将程序的控制流图打乱成不同的单元。然而,与ROP不同,攻击者受限于他们可以找到的gadgets及其在运行时预测位置的能力,我们在编译期间精确控制gadgets的放置。例如,我们可以将gadgets存储在不透明谓词混淆期间插入的虚假程序中。应用此技术后,逆向工程师会立即注意到方便的图从IDA等工具中消失。此外,这种转换将使使用最先进的静态分析工具(如BAP)变得不可能,并阻碍依赖调试器具体执行的动态分析技术。代码扩散破坏了断点的语义价值,因为单个代码片段可能被许多不同函数重用,而不被同一函数的其他实例使用。
使用MAST混淆前的本地代码
使用MAST混淆后的本地代码
上面的图表演示了一个非常简单的函数在代码扩散变换之前和之后的情况,使用IDA的屏幕截图。在第一个图中,有一个完整的控制流图;然而在第二个图中,第一个基本块不再直接跳转到以下任何一个块;相反,它必须在运行时参考应用程序中其他位置的数据部分,然后才知道在哪种情况下跳转到哪里。在整个应用程序上运行此代码扩散变换将整个程序从一组连接图函数减少到更大的一组单基本块“函数”。
代码扩散对整个程序混淆有明显的性能影响。在我们的测试中,我们比较了bzip2在面向返回变换之前和之后的速度,减速约为55%(在x86上)。
环境密钥绑定
MAST还做了一件事使逆向工程更加困难——它将代码的执行绑定到特定设备,例如用户的手机。虽然使用设备特定特征将二进制文件绑定到设备并不是新的(它广泛用于DRM和一些恶意软件,如Gauss),但MAST能够将设备检查集成到每个混淆层中,因为它编织通过应用程序。环境密钥绑定和混淆的交织使程序比一些更常见的设备绑定方法更抵抗逆向工程。
攻击者不仅必须获取应用程序的任何副本,还必须获取和分析目标计算机的执行环境。整个环境通常更难获取,并且有更多的代码需要分析。即使环境被捕获并花时间逆向工程应用程序细节,结果也不会对运行在其他主机上的相同应用程序有用,因为每个主机运行其自己的密钥版本二进制文件。
结论
总之,MAST是一套编译时变换,提供易于使用、跨平台、最先进的软件混淆。它可以用于多种目的,例如防止攻击者逆向工程安全相关的软件补丁;保护您的专有技术;保护应用程序内的数据;以及保护您的应用程序免受漏洞猎人的侵害。虽然最初范围是iOS应用程序,但这些技术适用于任何可以用LLVM编译的软件。
如果您喜欢这篇文章,请分享:
Twitter
LinkedIn
GitHub
Mastodon
Hacker News
页面内容
符号混淆
不透明谓词插入
代码扩散
环境密钥绑定
最近帖子
非传统创新者奖学金
在您的PajaMAS中劫持多代理系统
我们构建了MCP一直需要的安全层
利用废弃硬件中的零日漏洞
Inside EthCC[8]:成为智能合约审计员
© 2025 Trail of Bits.
使用Hugo和Mainroad主题生成。