(简称《逆向工程核心原理》第十四章和第十五章学习)
X.exe与X_upx.exe的比较
- PE头的大小一样(0~400h)
- 节区名称改变(“.text” -> “UPX0”, “.data” -> “”UPX1)
- 第一个节区的RawDataSize = 0(文件中的大小为0)
- EP位于第二个节区(原nodepad.exe的EP在第一个节区)
- 资源区(.rsrc)大小几乎无变化
可以发现Size of Raw Data为0,可Virtual Size设置为10000,说明在运行瞬间讲代码压缩到第一个节区
两种方法找到OEP
首先可以看下OEP的位置在100739Dh
10073B4处与10073C0地址处是比较MZ与PE签名
单步跟踪法
这两条指令设置了upx1和upx0的起始位置
1001000是upx0 待解压缩区
1011000是upx1 资源区
(跟踪UPX文件,遇到LOOP时,先了解作用再跳出)
1. 循环#1(初始化)
从EDX(1001000)中读取一个字节写入EDI(1001001)
(感觉就是初始化upx0节区)
2. 循环#2(解压缩循环)
这个循环比较大,一共有三处从upx1放入upx0
第一处放入
第二处放入
(这里有点不理解edx指向的也是upx0的区域,然后又放入upx0,为什么是upx1解压到upx0)
第三处放入
(和第二处同疑问)
3. 循环#3(修复重定位)
恢复E9的重定位,低八位直接舍弃了,减原来基地址,再加当前upx0的基地址
4. 循环#4(恢复IAT)
从upx1存放的API函数名称,GetProcAddress获取IAT地址再放到nodepad的IAT地址
5. 跳转到OEP
再往下一点就是跳转到OEP的位置了
ESP定律法
1. 设置内存断点
pushad是把八个通用寄存器放入堆栈,这样不会影响寄存器初始状态
所以当upx恢复完了,会有对应的popad,那么在这八个寄存器的数据下个断点
F9直接运行,当dbg断下来,说明已经恢复完了
2. 找到OEP
可以发现已经快到跳OEP的位置了
🍬
🍪
About this Post
This post is written by P.Z, licensed under CC BY-NC 4.0.