由于UPack会将 IMAGE_OPTIONAL_HEADER
中的 NumberOfRvaAndSizes
值设置为 0Ah
(默认值为 10h
),所以使用OllyDbg打开notepadupack.exe文件时,初始检查过程中会弹出错误消息对话
最新的这个吾爱Dbg倒是没有弹出这个错误
如果不是最新版本的Ollydbg那么这个错误会让调试器无法跳转到EP入口位置。停留在ntdll.dll
区域
该现象是由OllyDbg的Bug(或者严格的PE检查)引起的,所以需要强制设置EP。首先要查找EP位于何处。下面使用Stud_PE查找EP的虚拟地址。
如图所示,ImageBase
为 01000000
,EP的RVA为 1018
,经过计算可知EP的VA值为 01001018
。
在OllyDbg的代码窗口中转到 01001018
地址处,使用Neworiginhere命令强制更改EIP寄存器中的值,如图所示。
所有压缩器中都存在解码循环(DecodingLoop)。如果明白压缩/解压算法本身就是由许多条件分支语句和循环构成的,那么可能就会理解为何解码循环看上去如此复杂。
调试这样的解码循环时,应适当跳过条件分支语句以跳出某个循环。有些情况下循环较为复杂,无法迅速把握。调试中要仔细观察寄存器,注意相应值被写人哪些地址(其实这也需要丰富的经验)。
Upack把压缩后的数据放到第二个节区、然后运行解码循环将这些数据解压缩后放到第一个节区。我们从EP代码开始调试
前2条指令用于从 010011B0
地址读取4个字节,然后保存到EAX。EAX拥有值 0100739D
,它是原本notepad的OEP(分析一下 LODS DWORD PTR DS:[ESI]
指令可知,该指令从ESI所指的地址处读取4字节存储到EAX寄存器)。
事实上,如果事先知道该值是OEP,那么可以直接设置硬件断点,再按F9键运行,就会在OEP处暂停。
此时ESI的值为 0101FCCB
,该地址就是 decodeO
函数的地址,后面会反复调用执行该函数。接下来略看一下 decodeO
函数(101FCCB),如图所示。
但是现在看不明白这个函数的意思,我们继续跟踪调试
0101FE57
与 0101FE5D
地址处有“向EDI所指位置写人内容”的指令。此时EDI值指向第一个节区中的地址。也就是说,这些命令会先执行解压缩操作,然后写人实际内存。在 0101FE5E
与 0101FE61
地址处通过 CMP/JB
指令继续执行循环,直到EDI值为 01014B5A
([ESI+34]=01014B5A)。
地址 0101FE61
即是解码循环的结束部分。实际上,在循环反复执行时跟踪,可以随时看到向EDI所指地址写入了什么值。
一般而言,压缩器执行完解码循环后会根据原文件重新组织IAT,Upack也有类似的过程
如图所示,UPack会使用导人的2个函数(LoadLibraryA
与 GetProcAddress
)边执行循环边构建原本notepad的IAT(先获取notepad中导人函数的实际内存地址,再写人原IAT区域)。该过程结束后,由 0101FEAF
地址处的RETN命令将运行转到OEP处,如图所示。