ESP定律脱压缩壳

    什么是压缩壳呢?这个和我们的压缩文件做法很类似,就是将代码加密压缩。经过压缩壳处理的程序,由操作系统载入后先执行的不是真正的程序代码,而是一段解压缩算法,这段代码会将压缩的程序代码在内存中还原,就类似我们将压缩文件在当前目录展开一样,当解压缩代码执行完成,原本的程序代码也已经在内存中完全展开了,这个时候解压缩代码最后会有一个跳转语句,跳转到原本程序的真正入口地址。

   怎么脱壳呢?既然解压缩代码完成后,真正的程序代码会完整的出现在内存中,我们只要在这个时候暂停程序,把整个程序内存dump下来保存成可执行文件,那么我们不就获得了没加壳的源程序了吗?那么怎么知道解压缩代码什么时候执行完呢?这就要用到ESP定律了,什么是ESP定律呢?我们知道函数调用完成后会平衡堆栈,即压入多少个输入参数,当函数返回的时候就要弹出多少个参数,保证函数调用前后ESP指针不变。我们可以把整个解压缩代码当做一个函数,因为它要保证加壳的程序和没加壳的程序运行时要一模一样,所以在最开始的时候会使用PUSHAD将所有寄存器的值都保存到栈中(这也是压缩壳的特征之一:开头的第一条指令一般是PUSHAD,或者使用PUSH XX+RET的方式,XX处才是PUSHAD指令),然后在解压缩完成后再使用POPAD还原,所以我们只要找到POPAD指令,就找到了解压缩代码结束的位置。

    直接搜索POPAD指令是不太恰当的做法,因为程序可能有多处POPAD指令,那么怎么办呢?PUSHAD和POPAD操作的肯定是同一块内存,我们在PUSHAD指令执行后,在栈顶设置一个硬件访问断点,那么再次访问这块内存的指令就只有解压缩代码末尾的POPAD指令了,这个时候CPU会自动帮我们中断下程序,这样我们就找到了解压缩代码的结束位置了。具体操作如下(本例使用FreeUPX对crackme.chm的figugegl.1.exe程序加壳来做测试):

    首先载入有压缩壳的程序,先单步执行第一条PUSHAD指令(有时候压缩壳的开头可能是PUSH XX+RET的格式,这个时候单步步入跟踪几下就可以看到PUSHAD指令)

    然后在寄存器的ESP寄存器上右键,选择数据窗口跟随

    选中栈顶的四个字节,然后右键断点->硬件访问->DWORD,然后F9运行程序,程序很快会自动暂停

    选择调试->硬件断点,删除刚才添加的断点,然后在代码窗口找到JMP指令,让程序执行到JMP指令处

    这个就是压缩壳程序的另一个特征,就是POPAD后会跟着一条JMP指令,这条指令跳转的地址就是我们真正程序的入口地址,按下F8不过进入程序的真正入口地址处,然后右键将程序DUMP下来

    选择脱壳,然后保存文件便大功告成了~



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值