编辑: 会说话的鱼 2019-07-04
逆向一个简单的虚拟机-教程 Reverser:Maximus 获得指令和寄存器 好,今晚太累了,我下载了很多我喜欢的好歌,该是逆向的时间了.

我听人谈起HyperUnpackMe2这个crackme很多次,于是我找到了它.我打开了我的IDA 4.3-是的,我不用破解的那个…工具而已,只是给那些如果没有就什么都做不了的… 我打开了这个crakeme.它使用了很多丑陋的反IDA的技巧,这需要很多时间使用U快捷 键去取消 跳转/函数调用 的指针, 然后使用C快捷键, 重新定义代码. 它隐藏了LoadLibrary 和字符串的指针如 VirtualAlloc .好了,可笑但并不有趣,我要开始看这个虚拟机了.希 望它没有加密,否则我不得不使用OLLY解压脱壳直到虚拟机在代码中呈现出来. 那么, 我们如何使用IDA4.3在代码中找到一个虚拟机呢?很简单: 使用你的滚动条和最 古老有效的逆向工具:第六感. 我们到底该找些什么呢?我们的 灵感 点在哪里呢?当我浏览aspr1.2dll的时候,我发 现在Push序列之后的RET就是关键所在-它确实是,那么虚拟机呢?一个虚拟机由一个指令 仿真器构成,它通常是一个公共的代码循环跳转到一系列函数和地址.在本例中,我们查找 指针/函数列表.是的,这种列表可能是别的东西,例如,对象(objects)也是这样放置的. 我们如何把他们和虚拟机区别开来,或是如果是一个使用高级语言带有对象的虚拟机呢? 答案很简单,查看这些过程,需找重复的代码格式.例如,如果它们使用相同的参数, 并且这些相同的参数在多个使用它的函数中使用同样的格式, 那它可能就是一个虚拟机. 就 我个人而言, 我总是试着找共有的攻击点, 如程序计数器 (等效EIP) . 这并不总是简单的事. 如像*F(译者加:可能是一种虚拟机)的binded flow虚拟机通常就非常复杂(顺便说一下, 你可以使用很多方法来记录) . 让我们回到这个crackme,滚动屏幕,寻找并跟随那些随机跳转和过程,我们发现一个 有趣的列表,就像下面这样. ww PDF created with pdfFactory Pro trial version www.pdffactory.com 它看上去是不是有点意思,一个堆满指针的大表.我们查看一下这些多级指针(第一张 表的链接指向第二张表的头部)的其中一个. IDA给出了如上一堆数据,当我们使用C键把它们标记为代码后,就会变成: ww PDF created with pdfFactory Pro trial version www.pdffactory.com 有趣吧!在一个异或操作紧跟着一个跳转,我们在所有的这些地方使用快捷键,然后再 看看发生了什么. . . 这些是我最初使用C的位置.查看一下代码,所有的片段都跳到相同的地址,这似乎意 味着所有的片段都有一个相同的收场. 注意它们的第一条指令: 在所有的入口均使用了mov ecx, esi这个指令! 这不正是相同的 格式片段吗-或许相同的逻辑参数被送入esi中?很明显,这是在下一条移位指令中是使用的 移位计数,一个SHL.在这些的代码片段中,它们使用[edi]寄存器来保存结果.这三个代码 片段都是相同的结构,只是改变了核心指令存储参照:字节指针,字指针,双字指针.这就 是虚拟移位指令的三种方式.太好了! 我们已经知道了在这里SHL的源操作数被传递给esi,目的地址是edi,并且我们找出了 字节移位、字移位、双字移位这几个移位指令. 我们很幸运, 通常虚拟机的指令结构要比这复杂. 这个虚拟机没有应用那些复杂的技术 如指令内不同种类的寄存器/存储器/偏移参考等, 它似乎在指令中使用了一个固定的源/目的 地址:ESI是常规的源头指针,EDI是常规的目的结果指针(我们逆向更多后我们可以看出, 通用寄存器通过内存参考传递给虚拟指令-例如,如果SHL目标是一个通用寄存器R1,edi将 包含R1的指针) . 虚拟机的一个通常的非常标准的攻击点是等效的NOP指令,你如何能发现它们?简单. 它们除了更新虚拟机的内部状态之外,什么都不做.因此,一个只是更新似乎是被用来作为 程序计数器的寄存器极有可能就是我们这个虚拟机的NOP指令.然而这个crackme的虚拟机 非常简洁,因此我们直接去识别那些复杂指令. 现在,是我们逆向所有指令并重命名它们的时候了.结果就像下面这样: ww PDF created with pdfFactory Pro trial version www.pdffactory.com 所有这些指令都与SHL指令非常相似(或多或少) .你会注意到,IDIV指令有点特别, 它被分为IDIV和IDIV_REST两条指令.不知你是否记得,IDIV还要返回余数.如果你仔细 看一下这两条指令,你会发现: ww PDF created with pdfFactory Pro trial version www.pdffactory.com IDIV在EDI中返回不同的寄存器.你会想-为什么?简单,一个是结果,一个是余数. 由于虚拟机指令是二元设置(源/目的)结构,所以对三元指令,作者需要重复一次操作. 注意,在我们重构一个虚拟机之前,我通常翻看所有的指令,以查找是不是还有我们没 有谈过的的重要的东西.我总是寻找关于虚拟机寄存器结构的线索.例如,当我发现下面的 指令,我首先想到: PHUSF ??为什么它需要一个PHSHF指令?它在一个比较操作后保存标志位.呵呵… 之后把他们弹送到一个EAX寄存器相关的结构,EAX被用来和其它虚拟机代码段交互吗? 是的,当然. [EAX+0Ch]很明显指向了一个虚拟EFLAGS结构.于是我们打开IDA的结构页,创建 VM_EFLAGS结构并增加双字参数知道我们创建 Field_0Ch ,我们把它重命名为 VM_EFLAGS. 结果如上. 现在我们识别了我们第一个虚拟机寄存器! 我们再继续, 当我们在指令中逆向操作代码 时,我们发现了下面这个: 当我看到这个,我注意到:它取了一个固定寄存器(因为它相对于一个VM结构中的基 址,EAX,的偏移10h是固定的)并把它减去4.从edi中取出操作数,并截取其低两个字节,再 保存它们.你了解的什么汇编操作是当写入的时候减少寄存器数值? 或许这样会更清晰一些: ww PDF created with pdfFactory Pro trial version www.pdffactory.com 我想我不需要再解释什么了,这是一个PHSH双字的操作. 又搞定一个虚拟机寄存器.我们继续,我们还没有找到EIP这个通用寄存器…让我们找 到它们.浏览这个指令,我们会看到: 现在这个指令,与CMP指令类似,但它是一个JZ指令.它是个跳转,好,EIP肯定会被 使用,如果我们跳到某处,我们必定要改变EIP寄存器.我们已经知道EAX+0cH是我们的 VM_EFLAGS.因此,这里虚拟标志位送到CPU标志eflags里,JZ被执行.如果跳转没有发 生,EDI参数被移到EAX+8.我们知道EAX包含VM_CONTEXT,因此我们猜想这个被拷贝 的指令参数就是-跳转之后的新的EIP(这说明这个指令是JNZ而不是JZ) , 于是: 我们也找到了EIP寄存器.现在,试着识别一下下面这条指令吧: 除了它使用ESP和EIP外,我不会再给任何提示,想想吧. 另一个需要注意的是,你应该始终记住,虚拟机的作者在编制虚拟机时,不会严格遵守 ww PDF created with pdfFactory Pro trial version www.pdffactory.com 常规 .因此,指令不需要 标准 ,他们可以依照创造者的意愿做任何事情.如,有条指 令是这样的: 你应该注意到:它使用了真实ESP寄存器!为什么?它保存真实的ESP,并把用虚拟堆栈 设定为真实堆栈. 接着通过EDX调用一个函数. 这意味着这个虚拟机能在真实CPU空间中进 行函数调用,它把虚拟参数压入虚拟堆栈再调用这条 交换堆栈 的指令(如果你了解处理 器,它让我想起了一点在内部权限门之间通过参数拷贝的进行堆栈交换) ,还要注意执行函 数的真实返回值被保存到我们的虚拟机环境(VM_context)中的某处… 我在半个小时内几乎逆向了全部指令和寄存器,只要付出点努力,你也可以做到.只有 少数指令比较复杂,但对虚拟机逆向并不重要(我的意思是,对理解整个结构来说) 好了,该去睡觉了,非常非常晚了!希望你有所收获.Maximus

下载(注:源文件不在本站服务器,都将跳转到源网站下载)
备用下载
发帖评论
相关话题
发布一个新话题