19.Upack调试-查找OEP

1. OllyDbg运行错误

由于UPack会将 IMAGE_OPTIONAL_HEADER 中的 NumberOfRvaAndSizes 值设置为 0Ah(默认值为 10h),所以使用OllyDbg打开notepadupack.exe文件时,初始检查过程中会弹出错误消息对话

最新的这个吾爱Dbg倒是没有弹出这个错误

如果不是最新版本的Ollydbg那么这个错误会让调试器无法跳转到EP入口位置。停留在ntdll.dll区域
该现象是由OllyDbg的Bug(或者严格的PE检查)引起的,所以需要强制设置EP。首先要查找EP位于何处。下面使用Stud_PE查找EP的虚拟地址。
如图所示,ImageBase01000000,EP的RVA为 1018,经过计算可知EP的VA值为 01001018
Pasted image 20250402195134.png
在OllyDbg的代码窗口中转到 01001018 地址处,使用Neworiginhere命令强制更改EIP寄存器中的值,如图所示。
Pasted image 20250402200159.png

2. 解码循环

所有压缩器中都存在解码循环(DecodingLoop)。如果明白压缩/解压算法本身就是由许多条件分支语句和循环构成的,那么可能就会理解为何解码循环看上去如此复杂。
调试这样的解码循环时,应适当跳过条件分支语句以跳出某个循环。有些情况下循环较为复杂,无法迅速把握。调试中要仔细观察寄存器,注意相应值被写人哪些地址(其实这也需要丰富的经验)。

Upack把压缩后的数据放到第二个节区、然后运行解码循环将这些数据解压缩后放到第一个节区。我们从EP代码开始调试
Pasted image 20250403143242.png
前2条指令用于从 010011B0 地址读取4个字节,然后保存到EAX。EAX拥有值 0100739D,它是原本notepad的OEP(分析一下 LODS DWORD PTR DS:[ESI] 指令可知,该指令从ESI所指的地址处读取4字节存储到EAX寄存器)。
事实上,如果事先知道该值是OEP,那么可以直接设置硬件断点,再按F9键运行,就会在OEP处暂停。
Pasted image 20250403143455.png
此时ESI的值为 0101FCCB,该地址就是 decodeO 函数的地址,后面会反复调用执行该函数。接下来略看一下 decodeO 函数(101FCCB),如图所示。
Pasted image 20250403143552.png
但是现在看不明白这个函数的意思,我们继续跟踪调试
Pasted image 20250403144008.png
0101FE570101FE5D 地址处有“向EDI所指位置写人内容”的指令。此时EDI值指向第一个节区中的地址。也就是说,这些命令会先执行解压缩操作,然后写人实际内存。在 0101FE5E0101FE61 地址处通过 CMP/JB 指令继续执行循环,直到EDI值为 01014B5A([ESI+34]=01014B5A)。
地址 0101FE61 即是解码循环的结束部分。实际上,在循环反复执行时跟踪,可以随时看到向EDI所指地址写入了什么值。

3. 设置IAT

一般而言,压缩器执行完解码循环后会根据原文件重新组织IAT,Upack也有类似的过程
Pasted image 20250403144718.png
如图所示,UPack会使用导人的2个函数(LoadLibraryAGetProcAddress)边执行循环边构建原本notepad的IAT(先获取notepad中导人函数的实际内存地址,再写人原IAT区域)。该过程结束后,由 0101FEAF 地址处的RETN命令将运行转到OEP处,如图所示。
Pasted image 20250403145825.png