使用符号执行驯服受纳米虫保护的MIPS二进制文件:No Such Crackme
逆向工程:龙潭虎穴
MIPS 101
该挑战的第一个有趣细节是它是一个MIPS二进制文件;对我来说这确实有些异国情调。我主要看的是Intel汇编,所以有机会研究一个未知架构总是很吸引人。你知道这就像发现一个新玩具,所以我忍不住开始阅读MIPS基础知识。
这部分将仅描述您需要理解和破解二进制文件的基本信息;正如我所说,我根本不是MIPS专家。根据我所看到的,这与您在Intel x86 CPU上看到的非常相似:
- 它是小端序(注意也存在大端序版本,但本文不会涉及),
- 它有更多的通用寄存器,
- 调用约定类似于__fastcall:通过寄存器传递参数,并在$v0中获取函数返回值,
- 与x86不同,MIPS是RISC,因此更容易上手(相信我),
- 当然,有一个IDA处理器,
- Linux和常规工具也适用于MIPS,因此我们可以使用我们习惯的“正常”工具,
- 它也使用堆栈,但比x86少得多,因为大多数操作都在寄存器中(至少在这个挑战中)。
设置适当的调试环境
这个问题的答案是Qemu,正如预期的那样。您甚至可以在aurel32的网站上下载已经完全准备好且可用的Debian镜像。
|
|
随意在虚拟环境中安装您的基本工具,有些工具可能会派上用场(尽管安装它们可能需要一些时间):
|
|
最后,您应该能够运行这个野兽:
|
|
太棒了 :-)。
大局观
现在我们有了启动和调试挑战的方法,我们可以在IDA中打开二进制文件并开始理解使用了哪种保护方案。和往常一样,在这一点上,我们对细节真的不感兴趣:我们只想了解它是如何工作的,以及我们需要针对哪些部分来获得“好孩子”消息。
在IDA中花了一些时间后,二进制文件的工作方式如下:
- 它检查用户是否提供了一个参数:序列号
- 它检查提供的序列号是否为48个字符长
- 它将字符串转换为6个DWORD(/!\ 陷阱警告:转换有点奇怪,请确保验证您的算法)
- 野兽分叉成两个:
- [父进程] 似乎以某种方式驱动子进程,稍后会详细介绍
- [子进程] 在执行一大段代码修改(原地)6个原始DWORD后,它们与以下字符串进行比较 [ Synacktiv + NSC = <3 ]
- [子进程] 如果比较成功,您就赢了,否则就输了
基本上,我们需要找到6个输入DWORD,它们将在输出中生成以下内容:0x7953205b, 0x6b63616e, 0x20766974, 0x534e202b, 0x203d2043, 0x5d20333c。我们还知道父进程将与它的子进程交互,因此我们需要研究两个代码以确保正确理解挑战。
如果您更喜欢代码,以下是C语言的大局观:
|
|
动手实践
父进程负责
在了解大局后,我做的第一件事是查看父进程的代码。为什么?代码似乎比子进程的代码简单一些,所以我认为研究父进程会更合理,以理解我们需要颠覆的保护类型。
您甚至可以使用strace来更清晰地了解使用的系统调用:
|
|
这是一个我完全没有预料到的有趣输出。我们在这里看到的是父进程通过修改(可能,我们稍后会找出)其上下文来驱动其子进程,每次子进程SIGTRAP时(注意waitpid的第二个参数)。
从这里开始,如果您非常熟悉不同类型的软件保护(我不是说我是这个领域的专家,但我恰好知道这个 :-P),您几乎可以猜到那是什么:纳米虫!
纳米虫 101
纳米虫是一种相当不错的保护。不过,这是一个相当通用的名称;您真的可以以任何您喜欢的方式使用这种保护方案:您的想象力是唯一的限制。老实说,这是我第一次在Unix系统上看到这种保护;真是个好惊喜!
它通常这样工作:
- 您有两个进程:一个驱动进程和一个被驱动进程;一个父进程和一个子进程
- 驱动进程使用目标平台上可用的调试API(这里是ptrace,Windows上是CreateProcess/DebugActiveProcess)附加到被驱动进程
- 请注意,根据设计,您将无法附加到子进程,因为Windows和Linux都阻止了这一点(根据设计):有些人称这部分为DebugBlocker
- 不过,您将能够调试驱动进程
通常有趣的代码在子进程中,但再次强调,您可以做任何您想做的事情。基本上,如果您想要一个有效的保护,有两个规则:
- 确保被驱动进程没有其驱动进程就无法运行,并且它们彼此紧密绑定
- 保护的强度在于两个进程之间的这种强大/紧密的绑定
- 设计您的算法,使得移除驱动进程真的非常困难/痛苦/让攻击者发疯
被驱动进程可以通过例如int3/break指令来调用/通知驱动进程SIGTRAP
正如我所说,我更将这种保护方案视为一个配方:您真的可以随意自定义它。如果您想了解更多关于这个主题的内容,这里有一些您应该查看的链接:
- Linux应用程序的纳米虫和调试阻止程序:它很好地概述了如何在Linux上使这种保护方案工作,
- Unpackme I am Famous:这向您展示了Windows上真实受保护产品中纳米虫的样子;由我的伙伴@w4kfu完成,
- Debug me:另一个在Windows上使用纳米虫的甜蜜挑战
父进程如何工作
现在是时候详细研究父进程了;以下是它的工作方式:
- 它做的第一件事是waitpid,直到其子进程触发SIGTRAP
- 驱动进程检索子进程的CPU上下文,更具体地说是其程序计数器:$pc
- 然后我们有一个巨大的算术计算块。但在花了一些时间研究它之后,我们可以将这个巨大的块视为一个黑盒函数,它接受两个参数:子进程的程序计数器和某种计数器值(因为这段代码将在循环中执行,对于每个SIGTRAP,这个变量将递增)。它生成一个单一输出,这是一个32位值,我称之为第一个魔法值。
- 不过,让我们不要专注于这个块实际上在做什么,我们将在下一部分开发一些工具来处理这个问题 :-) 所以让我们继续前进!
- 然后,这个魔法值用于在QWORDs数组(606个QWORD,是子进程中断指令数量的6倍——稍后您会理解这一点,别担心)中找到一个特定条目。基本上,