我发现越来越多的二进制文件被 exe 保护程序打包,例如 upx、aspack 等。我尝试遵循一些关于如何解压缩它们的教程,但示例通常很容易,而我的目标则不然。
我正在寻找好的资源以及有关如何解压缩目标的任何提示/技巧。
我发现越来越多的二进制文件被 exe 保护程序打包,例如 upx、aspack 等。我尝试遵循一些关于如何解压缩它们的教程,但示例通常很容易,而我的目标则不然。
我正在寻找好的资源以及有关如何解压缩目标的任何提示/技巧。
解包通用包装器或加密器通常涉及以下步骤:
这对于简单的打包程序来说并不困难,但对于更高级的打包程序可能会很棘手。它们可能会使用时序检查 ( rdtsc
)、基于异常的控制传输、使用调试寄存器进行计算等。在这里使用 VM 或仿真器通常有助于对抗其中的大多数。
有很多方法可以做到这一点。有时,当它跟随一大块循环代码并且没有任何合理的关注时,跳转到 OEP 是显而易见的。或者,如果您熟悉不同编译器生成的入口点,您可能会认出 OEP 中的代码。其他几个技巧:
如果打包程序在解包之前保存了原始寄存器,请在它们在堆栈中的位置设置一个硬件断点 - 这样您就可以在跳转到 OEP 之前恢复它们时立即中断。
如果在跟踪期间您可以识别正在写入解包代码的内存,请在该内存范围内设置页面执行断点 - 它将在跳转后触发。IDA 允许你设置这样的断点,我认为 OllyDbg 也是如此。
在启动代码使用的常见 API 上设置断点,例如GetCommandLine
或GetVersionEx
。这不会让您获得确切的 OEP,但您通常可以返回调用堆栈并或多或少地轻松找到它。
如果您使用的是 IDA,则实际上不需要将文件转储到单独的文件中 - 拍摄内存快照就足够了,将字节从内存复制到数据库,以便您稍后分析它们。这里要记住的一件事是,如果打包程序使用动态分配的内存,则需要将其标记为“加载程序”,以便将其包含在快照中。更多在这里。
我不太熟悉它是如何在 Olly 或其他调试器中完成的,但是 AFAIK 您需要在转储中使用 ImpREC 之类的工具,并在内存中使用该进程的副本。
在 IDA 中它更简单(IMO)。您只需要找到导入表并根据指针当前指向的函数重命名指针(这应该在调试器处于活动状态时完成)。您可以使用renimp.idc
脚本或 UUNP“手动重建功能”(请参阅此处)。
为了查找导入表,我有时会使用两个技巧:
在 OEP 的启动代码中进行一些调用以查找外部 API,这将引导您进入导入表。通常表的开始和结束是显而易见的。
在解包过程中,在 GetProcAddress 上设置断点并查看结果写入的位置。但是,这不适用于使用导出目录手动导入结果的打包程序。将读取 BP 放在 kernel32 的导出表上可能会有所帮助。
这是可选的,但它可能有助于删除只会分散您注意力的打包程序代码的剩余部分。在 IDA 中,如果您识别使用的编译器,您还应该应用编译器 FLIRT 签名。
我不执行此步骤,因为我很少需要运行解压文件,但通常您通常需要修复 PE 标头,以便文件中该部分代码的偏移量与转储中的偏移量相匹配。
现在,上面的步骤没有涵盖许多变化和技巧。例如,一些加壳器最初并没有完全解析导入,而是跳转到在第一次调用时解析导入的存根,然后修补它,以便下次直接进入目标。然后是“被盗代码”方法,这使得查找和恢复 OEP 变得更加困难。有时,打包程序会运行自己的副本并对其进行调试,因此您无法将自己的调试器附加到它(这可以通过使用模拟器或不使用调试 API 的调试器(如英特尔 PIN)来解决)。尽管如此,概述的步骤可以涵盖相当多的内容。
我将以 Elias 制作的视频结束,该视频展示了打开 Lighty Compressor 的过程:https : //www.hex-rays.com/video/bochs_video_2.html
伊戈尔的回答非常好。然而,概述的技术依赖于这样的假设,即在某个时候可执行文件在内存中解压缩。这并不总是正确的。当由模拟器在运行时执行时,虚拟化混淆器将原始二进制文件编译成自定义指令集。如果您遇到以这种方式混淆的二进制文件,您别无选择,只能从自定义指令集编写反汇编程序到您理解的指令集。
Blackstorm 门户有大量开箱教程 Blackstorm 门户教程
一开始我花了很长时间,但随着时间的推移,打开包装变得容易多了,但需要很多耐心和练习。