推荐阅读:

C++反汇编代码分析–函数调用

C++反汇编代码分析–循环结构

C++反汇编代码分析–偷调函数

走进内存,走进汇编指令来看C/C++指针

  代码如下:

    #include "stdlib.h"

    int sum(int a,int b,int m,int n)

    {

         return a+b;

    }

    void main()

    {

         int result = sum(1,2,3,4);

         system("pause");

    }

  有四个参数的sum函数,接着在main方法中调用sum函数。在debug环境下,单步调试如下:

11:   void main()

12:   {

00401060   push        ebp

;保存ebp,执行这句之前,ESP = 0012FF4C EBP = 0012FF88

;执行后,ESP = 0012FF48 EBP = 0012FF88,ESP减小,EBP不变

00401061   mov         ebp,esp

;将esp放入ebp中,此时ebp和esp相同,即执行后ESP = 0012FF48 EBP = 0012FF48

;原EBP值已经被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。

;此时EBP寄存器就已经处于一个非常重要的地位,该寄存器中存储着栈中的一个地址(原EBP入栈后的栈顶),

;从该地址为基准,向上(栈底方向)能获取返回地址、参数值(假如main中有参数,“获取参数值”会比较容易理解,

;不过在看下边的sum函数调用时会有体会的),向下(栈顶方向)能获取函数局部变量值,

;而该地址处又存储着上一层函数调用时的EBP值!

00401063   sub         esp,44h

;把esp往上移动一个范围

;等于在栈中空出一片空间来存局部变量

;执行这句后ESP = 0012FF04 EBP = 0012FF48

00401066   push        ebx

00401067   push        esi

00401068   push        edi

;保存三个寄存器的值

00401069   lea         edi,[ebp-44h]

;把ebp-44h加载到edi中,目的是保存局部变量的区域

0040106C   mov         ecx,11h

00401071   mov         eax,0CCCCCCCCh

00401076   rep stos    dword ptr [edi]

;从ebp-44h开始的区域初始化成全部0CCCCCCCCh,就是int3断点,初始化局部变量空间

;REP           ;CX不等于0 ,则重复执行字符串指令

;格式: STOS OPRD

;功能: 把AL(字节)或AX(字)中的数据存储到DI为目的串地址指针所寻址的存储器单元中去.指针DI将根据DF的值进行自动

;调整. 其中OPRD为目的串符号地址.

;以上的语句就是在栈中开辟一块空间放局部变量

;然后把这块空间都初始化为0CCCCCCCCh,就是int3断点,一个中断指令。

;因为局部变量不可能被执行,执行了就会出错,这时候发生中断提示开发者。

13:       int result = sum(1,2,3,4);

00401078   push        4

0040107A   push        3

0040107C   push        2

0040107E   push        1

;各个参数入栈,注意查看寄存器ESP值的变化

;亦可以看到参数入栈的顺序,从右到左

;变化为:ESP = 0012FEF8-->ESP = 0012FEF4-->ESP = 0012FEF0-->ESP = 0012FEEC-->ESP = 0012FEE8

00401080   call        @ILT+15(boxer) (00401014)

;调用sum函数,可以按F11跟进

;注:f10(step over),单步调试,遇到函数调用,直接执行,不会进入函数内部

;f11(step into),单步调试,遇到函数调用,会进入函数内部

;shift+f11(step out),进入函数内部后,想从函数内部跳出,用此快捷方式

;ctrl+f10(run to cursor),呵呵,看英语注释就应该知道是什么意思了,不再解释

00401085   add         esp,10h

;调用完函数后恢复/释放栈,执行后ESP = 0012FEF8,与sum函数的参数入栈前的数值一致

00401088   mov         dword ptr [ebp-4],eax

;将结果存放在result中,原因详看最后有关ss的注释

14:       system("pause");

0040108B   push        offset string "pause" (00422f6c)

00401090   call        system (0040eed0)

00401095   add   esp ,4

;有关system(“pause”)的处理,此处不讨论

15:   }

00401098   pop         edi

00401099   pop         esi

0040109A   pop         ebx

;恢复原来寄存器的值,怎么“吃”进去,怎么“吐”出来

0040109B   add         esp,44h

;恢复ESP,对应上边的sub esp,44h

0040109E   cmp         ebp,esp

;检查esp是否正常,不正常就进入下边的call里面debug

004010A0   call        __chkesp (004010b0)

;处理可能出现的堆栈异常,如果有的话,就会陷入debug

004010A5   mov         esp,ebp

004010A7   pop         ebp

;恢复原来的esp和ebp,让上一个调用函数正常使用

004010A8   ret

;将返回地址存入eip,转移流程

;如果函数有返回值,返回值将放在eax返回(这就是很多软件给秒杀爆破的原因了,因为eax的返回值是可以改的)

-------------------------------------------------------------------------------------------------------------------------------------------------------------------

;以上即是主函数调用的反汇编过程,下边来看调用sum函数的过程:

;上边有说在00401080   call        @ILT+15(boxer) (00401014)这一句处,用f11单步调试,f11后如下句:

00401014   jmp         sum (00401020)

;即跳转到sum函数的代码段中,再f11如下:

6:    int sum(int a,int b,int m,int n)

7:    {

00401020   push        ebp

00401021   mov         ebp,esp

00401023   sub         esp,40h

00401026   push        ebx

00401027   push        esi

00401028   push        edi

00401029   lea         edi,[ebp-40h]

0040102C   mov         ecx,10h

00401031   mov         eax,0CCCCCCCCh

00401036   rep stos    dword ptr [edi]

;可见,上边几乎与主函数调用相同,每一步不再赘述,可对照上边主函数调用的注释

8:        return a+b;

00401038   mov         eax,dword ptr [ebp+8]

;取第一个参数放在eax

0040103B   add         eax,dword ptr [ebp+0Ch]

;取第二个参数,与eax中的数值相加并存在eax中

9:    }

0040103E   pop         edi

0040103F   pop         esi

00401040   pop         ebx

00401041   mov         esp,ebp

00401043   pop         ebp

00401044   ret

;收尾操作,比前边只是少了检查esp操作罢了

有关ss部分的注释:

;一般而言,ss:[ebp+4]处为返回地址

;ss:[ebp+8]处为第一个参数值(这里是a),ss:[ebp+0Ch]处为第二个参数(这里是b,这里8+4=12=0Ch)

;ss:[ebp-4]处为第一个局部变量(如main中的result),ss:[ebp]处为上一层EBP值

;ebp和函数返回值是32位,所以占4个字节

《完》

C++反汇编代码分析--函数调用的更多相关文章

  1. C++反汇编代码分析–函数调用

    转载:http://shitouer.cn/2010/06/method-called/ 代码如下:#include “stdlib.h” int sum(int a,int b,int m,int ...

  2. 恶意代码分析实战四:IDA Pro神器的使用

    目录 恶意代码分析实战四:IDA Pro神器的使用 实验: 题目1:利用IDA Pro分析dll的入口点并显示地址 空格切换文本视图: 带地址显示图形界面 题目2:IDA Pro导入表窗口 题目3:交 ...

  3. JQuery data API实现代码分析

    JQuery data 接口是什么? .data() Store arbitrary data associated with the matched elements or return the v ...

  4. Linux内核启动代码分析二之开发板相关驱动程序加载分析

    Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c  start_ke ...

  5. 阅读代码分析工具Understand 2.0试用

    Understand 2.0是一款源码阅读分析软件,功能强大.试用过一段时间后,感觉相当不错,确实能够大大提高代码阅读效率. 因为Understand功能十分强大,本文不可能详尽地介绍它的全部功能,所 ...

  6. 手机自动化测试:Appium源码分析之跟踪代码分析八

    手机自动化测试:Appium源码分析之跟踪代码分析八   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家 ...

  7. 20165223《网络对抗技术》Exp4 恶意代码分析

    目录 -- 恶意代码分析 恶意代码分析说明 实验任务目标 实验内容概述 schtasks命令使用 实验内容 系统运行监控 恶意软件分析 静态分析 virscan分析和VirusTotal分析 PEiD ...

  8. 2018-2019-2 网络对抗技术 20165336 Exp4 恶意代码分析

    2018-2019-2 网络对抗技术 20165336 Exp4 恶意代码分析 1.实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行. 1.2是分析一个恶意软件,就分析Exp2或E ...

  9. 2018-2019-2 网络对抗技术 20165305 Exp4 恶意代码分析

    Exp4 恶意代码分析 1.实践目标 1.1是监控你自己系统的运行状态,看有没有可疑的程序在运行. 1.2是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sysi ...

随机推荐

  1. 浅析Java hashCode()方法

      散列码(hash code)是由对象导出的一个整数值. 散列码没有规律,两个不同的对象x和y,x.hashCode()与y.hashCode()基本上不会相同. public static voi ...

  2. Java网络编程——UDP聊天程序

    UDP简介 UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据报.在OSI模型中,UDP位于第四层--传输层,处于IP协议额上一层.UDP有不提供数据报分组.组装以及不能对数据报排序 ...

  3. Web漏洞总结: OWASP Top 10

    本文原创,更多内容可以参考: Java 全栈知识体系.如需转载请说明原处. 开发安全 - OWASP Top 10 在学习安全需要总体了解安全趋势和常见的Web漏洞,首推了解OWASP,因为它代表着业 ...

  4. 什么是 Google Play服务

    Google Play服务用于更新Google应用和Google Play提供的其他应用. 此组件可提供多种核心功能,例如对您的Google服务进行身份验证.同步联系人信息.提供最新的用户隐私设置,以 ...

  5. React Native的缓存和下载

    一般我们有3种数据需要缓存和下载:纯文本(比如API返回,状态标记等),图片缓存和其他静态文件. 纯文本 纯文本还是比较简单的,RN官方模块AsyncStorage就够了.它就跟HTML5里面的Loc ...

  6. 别再埋头刷LeetCode之:北美算法面试的题目分类,按类型和规律刷题,事半功倍

    算法面试过程中,题目类型多,数量大.大家都不可避免的会在LeetCode上进行训练.但问题是,题目杂,而且已经超过1300道题. 全部刷完且掌握,不是一件容易的事情.那我们应该怎么办呢?找规律,总结才 ...

  7. JPA或Hibernate中使用原生SQL实现分页查询、排序

    发生背景:前端展示的数据需要来自A表和D表拼接,A表和D表根据A表的主键进行关联,D表的非主键字段关联C表的主键,根据条件筛选出符合的数据,并且根据A表的主键关联B表的主键(多主键)的条件,过滤A表中 ...

  8. linux入门系列5--新手必会的linux命令

    上一篇文章"linux入门系列4--vi/vim编辑器"我们讨论了在linux下如何快速高效对文本文件进行编辑和管理,本文将进一步学习必须掌握的linux命令,掌握这些命令才能让计 ...

  9. linux死机解决办法

    linux死机后不要长按电源建强制关机,容易对损坏系统配置或者电脑硬件,导致重启后产生不必要的麻烦 如果是在图形界面下死机的话,不要再依赖任何图形界面的工具,解决方法如下: 1.一种方式是进入终端界面 ...

  10. 你的应用安全吗? ——用Xray和Synk保驾护航

    一.背景 在当下软件应用的开发过程当中,自研的内部代码所占的比例逐步地减少,开源的框架和共用库已经得到了广泛的引用.如下图所示,在一个Kubernetes部署的应用当中,我们自己开发代码所占的比例可能 ...