从反汇编角度解密c函数调用过程

从反汇编角度解密c函数调用过程

ID:14183408

大小:73.00 KB

页数:37页

时间:2018-07-26

从反汇编角度解密c函数调用过程_第1页
从反汇编角度解密c函数调用过程_第2页
从反汇编角度解密c函数调用过程_第3页
从反汇编角度解密c函数调用过程_第4页
从反汇编角度解密c函数调用过程_第5页
资源描述:

《从反汇编角度解密c函数调用过程》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

1、从反汇编角度解密C函数调用过程这几天突然很想弄明白c函数调用时栈的使用情况,上网查了一下资料,自已也研究了一下,这篇blog就把我的所得记录下来吧。这篇blog试图讲明当一个c函数被调用时,一个栈帧(stackframe)是如何被建立,又如何被消除的。这些细节跟操作系统平台及编译器的实现有关,下面的描述是针对运行在Intel奔腾芯片上Linux的gcc编译器而言。c语言的标准并没有描述实现的方式,所以,不同的编译器,处理器,操作系统都可能有自己的建立栈帧的方式。一个典型的栈帧ESP==>

2、:

3、

4、.

5、+-------------------------+

6、被调用者保存

7、的寄存器现场

8、

9、EBX,ESI和EDI(根据需要)

10、+-------------------------+

11、临时空间

12、+-------------------------+

13、局部变量#2

14、[EBP-8]+-------------------------+

15、局部变量#1

16、[EBP-4]+-------------------------+EBP==>

17、调用者的EBP

18、+-------------------------+

19、返回地址

20、+-------------------------+

21、实际参数#1

22、[EBP+8]+-------------------------

23、+

24、实际参数#2

25、[EBP+12]+-------------------------+

26、实际参数#3

27、[EBP+16]+-------------------------+

28、调用者保存的寄存器现场

29、

30、EAX,ECX和EDX(根据需要)

31、+-------------------------+

32、:

33、

34、.

35、图1图1是一个典型的栈帧,图中,栈顶在上,地址空间往下增长。这是如下一个函数调用时的栈的内容:intfoo(intarg1,intarg2,intarg3);并且,foo有两个局部的int变量(4个字节)。在这个简化的场景中,main调用foo,而程序的控制仍在foo

36、中。这里,main是调用者(caller),foo是被调用者(callee)。ESP被foo使用来指示栈顶。EBP相当于一个“基准指针”。从main传递到foo的参数以及foo本身的局部变量都可以通过这个基准指针为参考,加上偏移量找到。由于被调用者允许使用EAX,ECX和EDX寄存器,所以如果调用者希望保存这些寄存器的值,就必须在调用子函数之前显式地把他们保存在栈中。另一方面,如果除了上面提到的几个寄存器,被调用者还想使用别的寄存器,比如EBX,ESI和EDI,那么,被调用者就必须在栈中保存这些被额外使用的寄存器,并在调用返回前回复他们。也就是说,如果被调用者只使用

37、约定的EAX,ECX和EDX寄存器,他们由调用者负责保存并回复,但如果被调用这还额外使用了别的寄存器,则必须有他们自己保存并回复这些寄存器的值。传递给foo的参数被压到栈中,最后一个参数先进栈,所以第一个参数是位于栈顶的。foo中声明的局部变量以及函数执行过程中需要用到的一些临时变量也都存在栈中。小于等于4个字节的返回值会被保存到EAX中,如果大于4字节,小于8字节,那么EDX也会被用来保存返回值。如果返回值占用的空间还要大,那么调用者会向被调用者传递一个额外的参数,这个额外的参数指向将要保存返回值的地址。用C语言来说,就是函数调用:x=foo(a,b,c);被转化

38、为:foo(&x,a,b,c);注意,这仅仅在返回值占用大于8个字节时才发生。有的编译器不用EDX保存返回值,所以当返回值大于4个字节时,就用这种转换。当然,并不是所有函数调用都直接赋值给一个变量,还可能是直接参与到某个表达式的计算中,如:m=foo(a,b,c)+foo(d,e,f);有或者作为另外的函数的参数,如:fooo(foo(a,b,c),3);这些情况下,foo的返回值会被保存在一个临时变量中参加后续的运算,所以,foo(a,b,c)还是可以被转化成foo(&tmp,a,b,c)。让我们一步步地看一下在c函数调用过程中,一个栈帧是如何建立及消除的。函数调

39、用前调用者的动作在我们的例子中,调用者是main,它准备调用函数foo。在函数调用前,main正在用ESP和EBP寄存器指示它自己的栈帧。首先,main把EAX,ECX和EDX压栈。这是一个可选的步骤,只在这三个寄存器内容需要保留的时候执行此步骤。接着,main把传递给foo的参数一一进栈,最后的参数最先进栈。例如,我们的函数调用是:a=foo(12,15,18);相应的汇编语言指令是:pushdword18pushdword15pushdword12最后,main用call指令调用子函数:callfoo当call指令执行的时候,EIP指令指针寄存器的内容被压入

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。