《逆核》03-手脱UPX
UPX解码步骤
1.先初始化
2.进行代码还原
3.进行CALL修复
4.进行函数表还原
5.节表初始化
6.解码完毕飞向程序入口
方法
- 单步跟踪法
- ESP定律法
解释
单步跟踪法:基于UPX解压缩的步骤,ep开头会先push所有寄存器到栈,然后执行三个循环(见前一节),然后pop弹出所有寄存器后,重建表,进入程序oep。因此,只要一直f8,遇到循环就f4跳过,直到看到pop,然后跳过小循环,进入最后一个就,jmp即可进入oep,基于以上原理,由于upx解压部分和跳转都是连在一起的,所以直接alt+t搜索pop指令找到最后的位置(push对应pop,pusha或pushad对应popa和popad)
ESP定律法:根据原理push之后是解压,解压完为了跳回oep要获得之前的寄存器值即栈一定会平衡,开始时的栈和最后进入oep的栈状态相同,因此开始调试后先f8,使ESP(RSP)下浮一个值创建栈,如果之后的指令需要这时栈底的寄存器值,一定会回到这里读取这个值.然后复制这时栈顶的地址,G跳到那个地址,在这里下硬件断点,点f9后运行到硬件断点就是pop的位置之后的指令,然后如上即可.
实例
实例一(使用IDA)
1,脱一个x64程序的UPX壳,使用ida:
初始对比:
可以看出加壳之后比源程序小了约四分之三.用ida打开加壳程序:
可以看出,压缩后函数变得极少,可以作为判断是否有壳的方法.
在开始处点f2下断点并进行动态调试:
f8单步调试并观察栈:
复制栈对应地址并g跳转然后下硬件断点:
观察到栈已经下了断点,这时直接f9,弹出
跳转到
转换汇编视图可以发现
指针点击循环下面的位置点f4运行到对应位置,再几次f8进大跳转就进入oep了,这个地方注意要先把硬件断点删了,点击上面工具栏的断点列表del键删掉
实例2(使用OD)
这是一个x32程序,使用od
进入后发现:
和上面方法一样,先f8,然后对寄存器下断点(右键sep值复制,在下面的命令窗口输入hr (对应的地址))这表示是硬件读取断点.回车
然后直接f9,删掉硬件断点:调试-硬件断点-删除.就找到了pop,小循环,大跳转
之后与第一个写的相同
或者在开始的时候,ctrl+f搜索popad
然后找到对应位置:
然后直接f4即可