ESP定律和动态脱UPX壳
关于ESP定律
简单来说,给栈顶ESP下硬件断点,ESP被拿走的时候就会停住,而在ESP上面push值或者pop值都不会停住
1 |
|
注意栈底部大上面小,SP是栈顶指针,一有羽毛球进去就会减少4个大小
先放了一个球进栈,ESP值由开始的0012FFC4
减去4变成了0012FFC0
再放一个ESP又减去4
所有的步骤执行完,ESP变成了0012FFA4
现在正式开始ESP定律
在0012FFA4
下一个硬件访问断点
1 |
|
下列语句执行完后
上面语句执行完后,结果如下
1 |
|
现在给0012FFAC
处下了硬件访问断点,研究一下怎么才会停下
这两种都不会停下
在栈顶0012FFAC
上面加了两个新的羽毛球
又把刚才加的两个拿走了,也没有影响
这个才会停下,一定要把0012FFAC
位置上的给拿走了(pop),才会停住
堆栈平衡
1 |
|
upx加壳后的程序运行时会先加载upx加入的代码(我们叫它程序1),把压缩后的代码还原出来。程序1是一个完整的程序,作用是解码后面的代码
完整的程序什么时候结束?
当栈第一次回到初始状态的时候
没开始执行时栈是空的,程序开始执行后程序1入栈(想象push了很多值进栈)
现在栈还是空的,
程序1先入栈(push一些值进栈)
程序1.1入栈(又push了一些值进栈)
接着程序1.1和程序1陆续出栈,栈空了,解压代码执行结束。
程序1也就是解压代码执行完后,栈返回初始空状态,这里就是程序真正开始的地方,也就是我们要找的OEP
ESP定律的变形用法
初始状态的ESP地址为0012FFC4
,在它的上一个地址0012FFC0
下一个硬件访问断点
总结
1 |
|
动态脱upx壳
起点
接下来按f8单步执行pushad指令,再设置硬件读取断点
设置完按f9运行程序,再次中断在一个不同的地址。这里并不是真实的程序代码,而是一个将栈空间向上清零0x80长度的循环。后面跟着一个向前的远距离的跳转(0043208C跳到00404DDC),这个就是跳到源代码的跳转(壳程序一般与程序原来的代码在不同的区段,故相隔较远)。
接下来删除硬件断点,菜单栏选择调试->硬件断点
把光标移动到这个jmp,按f4使得程序执行到光标处,再按f8执行跳转
跳转后出现了正常的函数开头和结尾,判断这个代码片段属于原程序
开头
结尾
对程序进行Dump,在插件中选择脱壳程序
单击获取EIP作为OEP,再单击脱壳
保存脱壳后的文件,然后用ida打开,可以看到被完全还原
运行正常
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!