继续来学习关于upx手脱的技巧
ESP定律法
ESP定律的原理就是“堆栈平衡”原理。
还是老样子的程序
首先程序执行了pushad 指令
将所有的寄存器压入栈中
一开始观察寄存器中的值
这里我们选择步入
也就是执行pushad指令后观察寄存器的值
可以发现只有esp变化了
那么
何为esp?何为eip?程序在执行的时候函数栈的调用是什么样子的呢?
这里我们要来探究一下
函数调用栈
何为函数调用?
调用的时候栈的分布是如何的?
https://blog.csdn.net/baidu_33751906/article/details/121642391
详情见我另一篇文章
在程序运行的时候 分为被调用函数和主动调用函数 也就是caller和Callee
栈在内存空间中是由高地址向低地址也就是自上而下的 从栈底到栈顶
首先在caller调用call指令的时候,进行两步操作
push eip
jmp near ptr add
也就是先把call指令的下一条指令放到栈中(这条指令存在ip寄存器里)
后进行跳转到地址处。
而在执行ret&&retf类型的指令时
会将当前的ESP寄存器中的地址出栈,然后进行跳转
简单了解即可,毕竟咱做的目前是逆向不是pwn
那么我们该如何利用ESP守恒定律来进行脱壳呢?
简单来说。我们来梳理一下:
加壳的程序在运行开始的时候 会进行解密 ,我们来思考一下
在解密的时候 ESP指针的内容 是不是一定会有两次重复的时候?
意思就是说,在解密完成之后esp寄存器里的值会变回最初的值
这就叫ESP平衡定律
因此我们只要找到ESP两次值相同的时候,也就是对ESP进行追踪,ESP指针归为的那一刻,就是找到了EP(入口点)
我们来实战吧
老样子
先在运行开始步入
找到ESP的值
这个时候是在pushad之后进行的
因此此时保存的sp寄存器里的值到最后解密完成后会回到最初的值,因此对这里的ESP进行追踪即可
在此处对ESP指针所指的地址进行数据访问后,加一下内存访问断点
随后运行程序
很熟悉,跟上一篇文章中手动进行的调试结果是一样的
也是找到了push ebp
结束了 这篇文章利用了esp守恒定律对upx进行脱壳
下一篇文章继续讲解 其他upx的脱壳手段