程序的OEP,一开始以 push ebp 和mov ebp esp这两句开始。

 
原因:c程序的开始是以一个主函数main()为开始的,而函数在访问的过程中最重要的事情就是要确保堆栈的平衡,而在win32的环境下保持平衡的办法是这样的: 
1.让EBP保存ESP的值。
2.在程序运行完毕的时候调用 
 
mov esp,ebp 
pop ebp 
retn
或者是 
leave
retn
通过EBP保存程序运行前ESP的值,那么程序运行过程中,不管ESP被Push还是Pop多少次,最终都可以通过EBP还原最开始的值。
 
我们下面使用gcc编译的stackframe函数为例:
 
 
void stackframe(int a,int b,int c){  
    int x=c;  
    char buffer[64];  
    int y=b;  
    int z=10;  
    buffer[0]='A';  
    bar(z,y);  
}  
这个函数对应的反汇编代码如下:
 
.text:0040153C                   ; =============== S U B R O U T I N E =======================================  
.text:0040153C  
.text:0040153C                   ; Attributes: bp-based frame  
.text:0040153C  
.text:0040153C                   _text_40153C proc near        ; CODE XREF: _text_40157A  
.text:0040153C  
.text:0040153C                   var_60= dword ptr -60h        ;z  
.text:0040153C                   var_5C= dword ptr -5Ch        ;y  
.text:0040153C                   var_58= dword ptr -58h        ;buffer  
.text:0040153C                   var_C= dword ptr -0Ch         ;x  
.text:0040153C                   arg_4= dword ptr  0Ch         ;b  
.text:0040153C                   arg_8= dword ptr  10h         ;c  
.text:0040153C  
.text:0040153C                   push    ebp  
.text:0040153D                   mov     ebp, esp  
.text:0040153F                   sub     esp, 78h  
.text:00401542                   mov     eax,[ebp+arg_8]  
.text:00401549                   mov     [ebp+var_C],eax  
.text:0040154B                   mov     eax,[ebp+arg_4]  
.text:0040154F                   mov     [ebp+var_5C],eax  
.text:00401551                   mov     [ebp+var_60],0Ah  
.text:00401554                   mov     [ebp+var_58],41h  
.text:00401557                   mov     eax,[ebp+var_5C]  
.text:0040155A                   mov     [esp+4],eax      ;y入栈  
.text:0040155D                   mov     eax,[ebp+var_60]  
.text:00401561                   mov     [esp],eax        ;z入栈  
 
从 var_60= dword ptr -60h开始,IDA提供了一个摘要栈视图,其中与指针EBP偏移距离为负的代表着四个局部变量x,buffer,y,z入栈,偏移距离为正的代表着用到 的两个形参b,c入栈。之后就是push ebp 和mov ebp esp以及函数体内部的赋值操作。最后要说明的是函数体最后调用了bar(z,y),这里需要将z,y压栈到esp中,因为z在前,所以[esp]存放 z,[esp+4]存放y,之后就是bar函数开始前的push ebp 和mov ebp esp操作了。

基于EBP的栈帧的更多相关文章

  1. X86-64寄存器和栈帧

    简介 通用寄存器可用于传送和暂存数据,也可参与算术逻辑运算,并保存运算结果.除此之外,它们还各自具有一些特殊功能.通用寄存器的长度取决于机器字长,汇编语言程序员必须熟悉每个寄存器的一般用途和特殊用途, ...

  2. X86-64寄存器和栈帧--牛掰降解汇编函数寄存器相关操作

    X86-64寄存器和栈帧 概要 说到x86-64,总不免要说说AMD的牛逼,x86-64是x86系列中集大成者,继承了向后兼容的优良传统,最早由AMD公司提出,代号AMD64:正是由于能向后兼容,AM ...

  3. 汇编3栈帧,参数传递,串操作,混合汇编,x64,asm文件

    基础知识2 选择结构 通过判断 + 条件跳转指令来实现 循环结构 通过判断 + 条件跳转指令来实现(会有一个向上跳转的语句) 函数调用约定 C调用约定: 由外部平衡栈 标准调用约定 : 由函数内部平衡 ...

  4. 栈帧%ebp,%esp详解

    首先应该明白,栈是从高地址向低地址延伸的.每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部( ...

  5. 使用gdb查看栈帧的情况,有ebp

    0x7fffffffdb30:    0x00000000    0x00000000    0xf7ffe700    0x0000001a0x7fffffffdb40:    0xffffdc98 ...

  6. [反汇编] 获取上一个栈帧的ebp

    使用代码 lea ecx, [ebp+4+参数长度] 就可以实现. 如下图,理解栈帧的结构,很好理解. 虽然也是 push param的,但这部分在恢复时被调用函数会恢复的,因此这并不算esp的值. ...

  7. 使用gdb查看栈帧的情况, 没有ebp

    0x7fffffffdb58: 0x004005ba  0x00000000  0x00000000  0x00000000 <-----funcb的栈帧 [0x7fffffffdb60, 0x ...

  8. c函数调用过程原理及函数栈帧分析

    转载自地址:http://blog.csdn.net/zsy2020314/article/details/9429707       今天突然想分析一下函数在相互调用过程中栈帧的变化,还是想尽量以比 ...

  9. Linux - 函数的栈帧

    栈帧(stack frame),机器用栈来传递过程参数,存储返回信息,保存寄存器用于以后恢复,以及本地存储.为单个过程(函数调用)分配的那部分栈称为栈帧.栈帧其实是两个指针寄存器, 寄存器%ebp为帧 ...

随机推荐

  1. 【学习笔记】【C语言】自增自减

    1. 简单使用 ++  自增运算符.如a++,++a,都等价于a = a+1 --自减运算符.如a--,--a,都等价于a = a-1 5++是错误的,因为5是常量 2. ++a和a++的区别 int ...

  2. JS字符串截取

    substr 方法返回一个从指定位置开始的指定长度的子字符串. stringvar.substr(start [, length ]) 参数stringvar 必选项.要提取子字符串的字符串文字或 S ...

  3. Python-Day15 JavaScript/DOM

    JavaScript JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. ...

  4. javaScript中的数组迭代方法

    ECMAScript5为数组定义了5个迭代方法. 每个方法都接收两个参数:要在每一项上运行的函数  和  (可选的)运行该函数的作用域对象. 传入这些方法中的函数会接收三个参数:数组项的值,该项在数组 ...

  5. C++将类的构造函数、析构函数声明为private或者protected的用途

    如果将构造函数.析构函数声明为private或者protected,表示不能从类的外部正常调用构造和析构函数了. 这种用法的通常使用的场景如下: 1.如果不想让外面的用户直接构造一个类A的对象,而希望 ...

  6. iOS Foundation框架 -2.常用集合类简单总结

    Foundation框架中常用的类有:NSString.NSArray.NSSet.NSDictionary 以及它们对应的子类 NSMutableString.NSMutableArray.NSMu ...

  7. 把url后面的.html去掉

    $url = "http://haichuang1997.bmlink.com/supply/dc_355472.html";echo rtrim($url, '.html');

  8. 《APUE》第四章笔记(4)

    这算是在博客园写的第一篇文章啊,之前都在csdn写(虽然才写了几篇,因为开通也没多少天..),还是稍微期待下吧.我写博客的主要意图是一来能够记录下来自己所学过的东西,二来也想能够跟大家交流,能够得到更 ...

  9. [大牛翻译系列]Hadoop(3)MapReduce 连接:半连接(Semi-join)

    4.1.3 半连接(Semi-join) 假设一个场景,需要连接两个很大的数据集,例如,用户日志和OLTP的用户数据.任何一个数据集都不是足够小到可以缓存在map作业的内存中.这样看来,似乎就不能使用 ...

  10. CentOS中查看物理CPU信息的方法

    1.概念 [1]物理CPU:实际Server中插槽上的CPU个数.物理cpu数量:可以数不重复的 physical id 有几个.[2]逻辑CPULinux用户对 /proc/cpuinfo 这个文件 ...