解压 UPX 时出现的问题

逆向工程 开箱 倾倒
2021-07-06 14:10:10

由于我喜欢玩 WinAPI 或一般调试,因此我决定为今天的开源 PE 可执行打包程序UPX(Windows 版本)编写一个小型解包程序

为了实现这一点,我进行了如下操作:

  • CreateProcessAPI 全部带有DEBUGDEBUG_ONLY_THIS_PROCESS标志。
  • GetThreadContextAPI 调用以读取EIP.
  • ReadProcessMemoryAPI 调用循环搜索最后一条JMP指令。
  • 覆盖E9withCCINT3在地址上设置断点。
  • 进入DebugEvent循环等待断点。到达后,将字节重置回E9,减EIP一并跳转到OEP目标地址 ( )。

到达 后OEP,我按以下步骤操作以转储进程:

  • 从原始 PE 标头中读取 ImageBase、Base of code、ImageSize、...
  • ReadProcessMemory(hProcess, header32.ImageBase, buffer, header32.SizeOfImage, bytes_read)
  • 将缓冲区内容保存到 payload.bin,使用 new EntryPoint ( OEP)更新文件的 PE 标头,RawDataOffset并将RawDataSize每个部分的和 设置为其对应的VirtualAddress/ VirtualSize

OEP为这些部分创建具有固定和 RAW 偏移/大小的转储后,我使用 ImpREC 修复转储(现在手动,但我计划使用ImpREC.dllImpREC lite 源以便稍后将所有内容组装到一个工具中)。

但让我感到困惑的是,对于一个测试用例(一个小型​​的 hello world fasm 应用程序),生成的二进制文件运行得非常好(与 MUP 完全匹配),并且我的转储文件与我通过 OllyDump 收到的完全相同,但是当我尝试使用 UPX 打包版本进行相同的解包时putty.exe,我的转储内存与 OllyDump 从 RAW 偏移量开始转储的内存不同0x73970(在该地址之前完全匹配)。

但是 - 文件大小再次相同(以及该偏移量匹配之前的所有字节),就在该特定地址之后,字节神奇地不再匹配(尽管它们仍然非零)。

OllyDump.c彻底研究了有关这种差异的源代码,但至于现在我没有发现我的错误......在某些情况下,我的转储与 OllyDump 生成的相同,而在某些情况下则不然。或者我的方法中可能已经出现了错误?

注意:源代码故意省略,因为它有几百行长而且现在超级混乱。如果需要,可以/将添加更多详细信息,或者如果我错过了什么,请在评论中告诉我。

1个回答

如果没有真正看到差异,很难说出差异的原因是什么,但一个猜测是你正在做ReadProcessMemory(hProcess, header32.ImageBase, buffer, header32.SizeOfImage, bytes_read),而另一个工具可能正在做foreach(section) {ReadProcessMemory(hProcess, header32.ImageBase + section.RVA, buffer, section.VirtualSize, bytes_read)}这可能会导致部分之间的“洞穴”不同。

(顺便说一句,我假设您header32.ImageBase是内存中模块的实际基址,而不仅仅是来自 PE 标头的图像基址,因为 ASLR 可以在运行时重新定位它。)