ESP详细说明定律原理
合天智汇 首发
0x00 前言
闲着也闲着,在逆向软件时深入了解ESP定律,然后想写一篇文章来记录和分享。
ESP定律,又称堆栈平衡定律,是最常用的脱壳方法之一 ,新手和老手都经常使用。据我所知,ESP一位外国大牛发现了定律,但目前还没有办法研究(没有找到相关信息)。
0x01 前置知识
栈
栈(stack)是内存中分配的空间。 将新元素插入一个栈也称为入口(push)放在栈顶元素上,使之成为新的栈顶元素; 从栈中删除元素也称为栈(pop),它删除了栈顶元素,使其相邻元素成为新的栈顶元素。
call
相当于高级语言中的函数调用。 当执行call两步操作: 将下一个指令的地址压入栈中,然后跳转到地址。 相当于:
push ip jmp near ptr 地址
ret && retf
与call对应指令,对应当前指令ESP寄存器中指向的地址出栈,然后跳转到地址。 相当于:
pop ip #ret
pop IP pop CS #retf
0x02 操作示例
这是我写的一个带壳的32个小程序,用作esp定律应用的一个例子。这是一种更机械的方法,但可以esp对定律有感性的理解。
- 首先用Exeinfo Pe查壳,发现是nspack壳。
- 接下来用od单步进入程序后,如箭头所示ESP寄存器变红了。
- 此时,单击右键选择寄存器。然后在数据窗口的任何字符下选择硬件断点(byte,word,dword均可)。
- f9运行后,f8连续单步找到OEP( 程序入口点 )。单击右键选择地址OllyDump脱壳调试进程,然后进行脱壳(如果发现程序不能打开,可以试试勾选重建输入表)。
- 接着用Exeinfo Pe检查壳,壳已被移除。
0x03 原理详解
首先,壳本质上是一个子程序,它在程序运行时首先获得控制权并压缩程序。 同时,隐藏程序是真实的OEP。基于这一原理,大多数病毒可以防止被杀毒软件扫描。
壳的类型:
? 解压->运行 ? 解压->运行->解压.->运行 ? 解压 decoder|encoded code->decode ->exc ? Run the virtual machine
脱壳的目的是找到真正的OEP(入口点)。
我们说的ESP定律的本质是堆栈平衡,具体如下:
- 让我们来看看这个小程序入口的寄存器。
EAX 00000000 ECX 004E820D offset r1.<ModuleEntryPoint> EDX 004E820D offset r1.<ModuleEntryPoint> EBX 0036C000 ESP 0072FF74 EBP 0072FF80 ESI 004E820D offset r1.<ModuleEntryPoint> EDI 004E820D offset r1.<ModuleEntryPoint> EIP 004E820D r1.<ModuleEntryPoint>
- 然后是到OEP每个寄存器的情况
EAX 0072FFCC ECX 004E820D offset r1.<ModuleEntryPoint> EDX 004E820D offset r1.<ModuleEntryPoint> EBX 0036A000 ESP 0072FF74 EBP 0072FF80 ESI 004E820D offset r1.<ModuleEntryPoint> EDI 004E820D offset r1.<ModuleEntryPoint> EIP 00401500 r1.00401500
我们发现只有EIP和EAX寄存器的值发生了变化,EAX保存的是OEP地址,什么?
在程序自解密或自解压过程中, 大多数壳首先将当前寄存器状态压栈, 如使用
pushad
, 解压后, 将以前的寄存器值出栈, 如使用popad
. 所以寄存器出栈时, 程序代码通常被恢复, 此时,硬件断点触发(这就是为什么要下硬件断点),然后在程序的当前位置, 只需要一些单步操作, 它将达到正确OEP位置.
0x04 适用范围
我自己总结了一个相对较小的白色方法,也就是说,在输入程序后,只有esp如果寄存器内容发生变化,这个程序大多可以使用ESP定律(如有错误,请指正)。
几乎所有的压缩壳, 一些早期的加密壳 (这是在网上收集到的资料总结的,经过我自己的实践,基本准确)。
0x05 总结
以上是我的对ESP对定律的理解,如有错误,请轻喷 - ,我也只是一个刚刚进入二进制世界的菜鸟。我希望我的文章能帮助刚刚开始的小白>_<
最后加一句找OEP不是最难的,最难的是修复。如果是对的OEP如果你对识别有疑问,你可以问我,你也可以在网上收集相关信息比较多的。
- ——— by TDfoil