由于我喜欢玩 WinAPI 或一般调试,因此我决定为今天的开源 PE 可执行打包程序UPX(Windows 版本)编写一个小型解包程序。
为了实现这一点,我进行了如下操作:
CreateProcessAPI 全部带有DEBUG和DEBUG_ONLY_THIS_PROCESS标志。GetThreadContextAPI 调用以读取EIP.ReadProcessMemoryAPI 调用循环搜索最后一条JMP指令。- 覆盖
E9withCC以INT3在地址上设置断点。 - 进入
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 生成的相同,而在某些情况下则不然。或者我的方法中可能已经出现了错误?
注意:源代码故意省略,因为它有几百行长而且现在超级混乱。如果需要,可以/将添加更多详细信息,或者如果我错过了什么,请在评论中告诉我。