了解EBP指针
在寄存器里面有很多寄存器虽然他们的功能和使用没有任何的区别,但是在长期的编程和使用中,在程序员习惯中已经默认的给每个寄存器赋上了特殊的含义,比如:EAX一般用来做返回值,ECX用于记数等等。在win32的环境下EBP寄存器用与存放在进入call以后的ESP的值,便于退出的时候回复ESP的值,达到堆栈平衡的目的。
应用以前说过的一段话:
原程序的OEP,通常是一开始以 Push EBP 和MOV Ebp,Esp这两句开始的,不用我多说大家也知道这两句的意思是以EBP代替ESP,作为访问堆栈的指针。
为什么要这样呢?为什么几乎每个程序都是的开头能?因为如果我们写过C等函数的时候就应该清楚,程序的开始是以一个主函数main()为开始的,而函数在访问的过程中最重要的事情就是要确保堆栈的平衡,而在win32的环境下保持平衡的办法是这样的:
1.让EBP保存ESP的值;
2.在结束的时候调用
mov esp,ebp
pop ebp
retn
或者是
leave
retn
两个形式是一个意思。
这样做的好处是不用考虑ESP等于多少,PUSH了多少次,要POP多少次了,因为我们知道EBP里面放的是开始时候的ESP值。
2.推广的ESP定律
在寻找OEP的时候,往往下断HW ESP-4不成功,除了壳代码将硬件断点删除了以外,很可能的情况就是因为壳代码在运行到OEP的时候他的ESP已经不再是在EP时候的ESP(12FFC4)了,这样我们下断当然是不成功的。
那么如何找到在壳到达OEP的时候的堆栈的值将是关键。
在这里我们应用的关键是
Push EBP
MOV Ebp,Esp----》关键是这句
我来解释一下,当程序到达OEP的时候Push EBP这句对于ESP的值来说就是ESP-4,然后是ESP-4赋给了EBP,而做为保存ESP值作用的EBP寄存器在这个“最上层的程序”中的值将始终不会改变。虽然他可能在进入子call里面以后会暂时的改变(用于子程序的堆栈平衡)但是在退出了以后依*pop ebp这一句将还原原来的EBP的值。
以这句做为突破口,就是说只要我们能断在“最上层的程序”中,就能通过观察EBP的值得到壳在JMP到OEP的时候的ESP的值了。
3.实战
来看看pespin1.1的壳,在pespin1.0的壳中,我们使用HW 12FFC0能很容易的找到stolen code的地方,但是到pespin1.1的时候,我们就不行了。用HW 12FFC0根本断不下来。
现在我们就使用这个推广的ESP定律,载入程序后来到最后的一个异常
0040ED85 2BDB sub ebx,ebx //停在这里
0040ED87 64:8F03 pop dword ptr fs:[ebx]
0040ED8A 58 pop eax
0040ED8B 5D pop ebp
0040ED8C 2BFF sub edi,edi
0040ED8E EB 01 jmp short pespin1_.0040ED91
0040ED90 C466 81 les esp,fword ptr ds:[esi-7F]
我用使用内存断点办法来到FOEP处
004010D3 0000 add byte ptr ds:[eax],al
004010D5 0000 add byte ptr ds:[eax],al
004010D7 0000 add byte ptr ds:[eax],al
004010D9 0000 add byte ptr ds:[eax],al
004010DB 0000 add byte ptr ds:[eax],al
004010DD 0000 add byte ptr ds:[eax],al
004010DF 75 1B jnz short pespin1_.004010FC //这里是FOEP
004010E1 56 push esi
004010E2 FF15 99F44000 call dword ptr ds:[40F499]
004010E8 8BF0 mov esi,eax
004010EA 8A00 mov al,byte ptr ds:[eax]
好了,这里就是“最上层的程序”的地方了,看看寄存器
EAX 00141E22
ECX 0040C708 pespin1_.0040C708
EDX 0040C708 pespin1_.0040C708
EBX 0040C708 pespin1_.0040C708
ESP 0012F978
EBP 0012F9C0 //注意这里
ESI 00141EE0
EDI 0040E5CD pespin1_.0040E5CD
EIP 004010DF pespin1_.004010DF
看到了吧,EBP=0012F9C0,我们来想象一下这个值是怎么得到的。
首先肯定是通过MOV ESP,EBP这一句,也就是说ESP这时是0012F9C0的,然而上面还有一句PUSH EBP也就是说ESP在到达OEP的时候应该是0012F9C4的。好了得到这个结论我们就能很快的找到stolen code的所在了。
重来停在最后的异常
0040ED85 2BDB sub ebx,ebx //停在这里
0040ED87 64:8F03 pop dword ptr fs:[ebx]
0040ED8A 58 pop eax
0040ED8B 5D pop ebp
0040ED8C 2BFF sub edi,edi
0040ED8E EB 01 jmp short pespin1_.0040ED91
0040ED90 C466 81 les esp,fword ptr ds:[esi-7F]
然后下断HW 0012F9C0 ,F9运行,来到这里
0040D8FB 61 popad
0040D8FC 55 push ebp
0040D8FD EB 01 jmp short pespin1_.0040D900 //停在这里
0040D8FF 318B ECEB01AC xor dword ptr ds:[ebx+AC01EBEC],ecx
0040D905 83EC 44 sub esp,44
0040D908 EB 01 jmp short pespin1_.0040D90B
0040D90A 72 56 jb short pespin1_.0040D962
0040D90C EB 01 jmp short pespin1_.0040D90F
0040D90E 95 xchg eax,ebp
0040D90F FF15 6CF34000 call dword ptr ds:[40F36C]
0040D915 EB 01 jmp short pespin1_.0040D918
于是就很快的找到了stolen code的所在了。
4.总结
上面的这个办法大概可以总结以下的步骤:
(1).直接或间接的断在“最上层的程序”的地方。
(2).得到“最上层的程序”的EBP的值。
(3).利用程序初始化的两个固定语句找到壳JMP到OEP的堆栈值。这个办法有很大的局限性,因为只有VC和delphi程序使用这个初始化的开头。
但是找到“最上层的程序”的办法除了内存断点还有很多办法,例如对于VC来说使用 bp ExitProcess也是一个很好的断点,可以直接得到EBP的数值。
5.后话
原来这个办法有很强的前提条件,不是一个很具普遍性的办法,我原来也不想单独的提出来,但是对于jney2兄弟的anti-ESP定律来说这个办法却是一个解决之道。
当然还有更多的办法,在这里我只想说很多事情有矛就有盾,没有什么办法是一定没有漏洞的,只是希望这篇文章给大家阔宽思路,起到抛砖引玉的作用。
当调用函数时
原EBP值已经被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。
此时EBP寄存器就已经处于一个非常重要的地位,该寄存器中存储着栈中的一个地址(原EBP入栈后的栈顶),
从该地址为基准,向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数局部变量值,
而该地址处又存储着上一层函数调用时的EBP值!
总结一个for循环的反汇编结构如下:
mov <循环变量>,<初值>
jmp 检查循环条件B
A: (修改循环变量)
...
...
B: cmp <循环变量>,<限制条件>
jge 跳出循环
(循环体)
...
...
jmp 修改循环变量A
;if的模板如下
;
;cmp <各种条件>
;各种跳转跳到下一个分支
;else if模板
;
;jmp 跳出判断
;cmp <条件>
;各种跳转跳到下一个分支
;switch()的模板如下:
;
;cmp <条件1>
;je <case 分支1>
;cmp <条件2>
;je <case 分支2>
;...
;...
;jmp <default分支>
- zrong's blog
- mygeda
- http://rectius.com.br/blog/
- -------------
- AS3中文参考
- AS3开源大全
- Adobe Community Search
- wonderfl.net
- FlexExamples
- flex4examples
- Flex4fun
- blog.minidx.com
- kirupa.com/flash
- flex-blog
- myflexhero
- switchonthecode/flex
- stackoverflow
- Adobe CookBooks
- gotoandlearn.com
- actionscript.org
- flashandmath
- 在线繁简转换
- mobantop.com
- adobeevangelists
- 找图标的好网站
- iconfinder.com
- 找形状的好网站
- 设计小站1
- http://www.designkindle.com/
- http://www.brusheezy.com
- shutterstock.com(矢量图)
- zcool
- designingwebinterfaces
- more flex themes
- www.java2s.com/Flex
- 简单在线选色
- Adobe kuler 调色
- colorexplorer
- ---------
- mind hacks
- 词都
- http://www.matrix67.com
- http://blog.csdn.net/tomsoft
- http://www.dokuwiki.org
- http://www.cs.jhu.edu/~yairamir/
- http://www.cnds.jhu.edu/courses/cs437/
了解EBP指针的更多相关文章
- esp和ebp指针
gdb调试的时候会出现esp和ebp这两个指针,而这两个指针为我们查看栈的情况提供了方便. 简单点说,esp指向栈顶,而ebp指向栈底.例如一段程序: #include <stdio.h> ...
- [Android Pro] ESP和EBP 栈顶指针和栈底指针
cp: http://blog.csdn.net/hutao1101175783/article/details/40128587 (1)ESP:栈指针寄存器(extended stack poin ...
- 从汇编看c++中成员函数指针(一)
下面先来看c++的源码: #include <cstdio> using namespace std; class X { public: int get1() { ; } virtual ...
- ASM X86&&X64 Registers 对寄存器ESP和EBP的一些理解
ESP EIP EBP : frame pointer(base address of stack) Calling Convention: 调用约定 为什么fun调用之后 esp -ebp = 20 ...
- 对寄存器ESP和EBP的一些理解
PS:EBP是当前函数的存取指针.即存储或者读取数时的指针基地址:ESP就是当前函数的栈顶指针. 每一次发生函数的调用(主函数调用子函数)时,在被调用函数初始时,都会把当前函数(主函数)的EBP压栈, ...
- 汇编 EBP ,ESP 寄存器
知识点: CALL框架 EBP寄存器 栈底指针 ESP寄存器 栈顶指针 一.EBP栈底指针 EBP是一个特殊的寄存器,通过EBP+偏移量 可以访问CALL里边的局部变量.它的低16位叫BP ...
- 【转】 关于寄存器ESP和EBP的一些理解
原文: http://blog.csdn.net/zsJum/article/details/6117043 一直对寄存器ESP和EBP的概念总是有些混淆,查看定义ESP是栈顶指针,EBP是存取堆栈指 ...
- (转)对于ESP、EBP寄存器的理解
原文地址https://blog.csdn.net/yeruby/article/details/39780943 esp是栈指针,是cpu机制决定的,push.pop指令会自动调整esp的值: eb ...
- 使用gdb查看栈帧的情况,有ebp
0x7fffffffdb30: 0x00000000 0x00000000 0xf7ffe700 0x0000001a0x7fffffffdb40: 0xffffdc98 ...
随机推荐
- Scala:用于Java的轻量级函数式编程
Scala为Java开发提供了轻量级的代码选项,但是学习过程可能会很艰难.了解有关Scala的知识以及是否值得采用. 基于Java的语言通常涉及冗长的语法和特定于领域的语言,用于测试,解析和数值计算过 ...
- 开箱即用!使用Rancher 2.3 启用Istio初体验
本文来自Rancher Labs Rancher的理念是Run Kubernetes Everywhere,Rancher 2.3中许多重大更新,让这一理念的实现又向前一步. 其中,最重要的两个特性是 ...
- 20.用PyInstaller打包py程序的步骤及问题解决
最近写了一个移动和复制文件的代码,代码完成之后,想将其打包成一个可以在任何电脑上使用的软件, 于是在网上查找相关资料,可以用PyInstaller打包成.exe程序,以下是具体步骤: 1.安装PyIn ...
- 用户svn密码自定义
由于在linux系统Apache+svn服务器,用户需要自定义密码怎么办呢? 1.创建脚本目录 mkdir -p /var/www/svn/svntools 2.创建apache配置文件 touch ...
- css label两端对齐
上面这种效果很常见,实现的代码如下: html部分 <ul> <li class="detail_item"> <span class="d ...
- python条件(三元)运算符
条件运算符 是 三元运算符 语法: 语句1 if 条件表达式 else 语句2 执行流程: 条件运算符在执行时,会先对条件表达式进行求值判断 如果判断结果为True,则执行 ...
- 在Winform界面使用自定义用户控件及TabelPanel和StackPanel布局控件
在很多时候,我们做一些非常规化的界面的时候,往往需要创建一些用户控件,在其中绘制好一些基础的界面块,作为后续重复使用的一个单元,用户控件同时也可以封装处理一些简单的逻辑.在开发Winform各种类型项 ...
- ES6的Object.assign()基本用法
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target). 例如: const target = {a:1}, const source1 ...
- 一个命令解决linux重启nginx就丢失pid文件问题
sudo nginx -c /etc/nginx/nginx.conf
- 区间dp - 不连续的回文串
Long long ago, there lived two rabbits Tom and Jerry in the forest. On a sunny afternoon, they plann ...