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个字节
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: IDA 是一种广泛使用的反汇编工具,用于将机器码转换成相应的高级编程语言代码,例如 C 语言。通过反汇编 C 代码,我们可以更好地理解和分析程序的功能和逻辑。 使用 IDA 反汇编 C 代码的过程相对较简单。首先,我们将目标程序加载到 IDA 中,并选择以反汇编 C 语言的方式展示反汇编结果。接下来,在 IDA 的窗口中,我们将看到程序的汇编代码,以及与每个指令对应的注释和变量名。 通过分析反汇编结果,我们可以确定每个汇编指令对应的 C 代码,并进一步理解程序的结构和流程。通过添加注释、变量名和函数名,我们可以更方便地阅读和分析代码。 IDA 还提供了一些高级功能,例如交叉引用和反汇编图,这些功能能够帮助我们更全面地理解程序的各个部分和函数之间的联系。通过分析反汇编结果,我们可以发现任何隐藏的功能或安全漏洞,并进行修复或优化。 总而言之,IDA 是一款强大的反汇编工具,能够将机器码转换为易于理解的 C 代码,帮助我们更好地理解、分析和优化程序中的功能和逻辑。 ### 回答2: IDA是一款强大的反汇编软件,用于将机器码还原为可读的C语言代码。IDA具有简单易用的界面和丰富的功能,可以帮助逆向工程师分析和理解二进制文件的内容。 使用IDA反汇编C语言代码可以带来很多好处。首先,通过反汇编,可以获得更多关于程序的信息,如函数的调用关系、变量的使用方式等。这对于理解程序的功能和逻辑非常有帮助。 其次,IDA可以将反汇编的结果以C语言的形式呈现,使得代码更易读、易懂。这对于逆向工程师理解程序的逻辑和进行代码分析非常重要,有利于发现潜在的安全漏洞或程序的漏洞。 此外,IDA还提供了很多辅助功能,如交叉引用、调试器、动态分析等。这些功能能够帮助逆向工程师更方便地进行代码分析和调试,提高工作效率。 总之,IDA通过反汇编C语言代码,可以帮助逆向工程师深入理解程序的内部结构和工作原理,提高分析和逆向工程的效率。无论是进行安全评估、漏洞挖掘还是代码重用,IDA都是非常有用的工具。 ### 回答3: IDA是一款常用的反汇编工具,可以将机器码反汇编为C语言代码。使用IDA反汇编C代码可以帮助我们理解程序的功能和逻辑。 首先,我们需要将目标程序加载到IDA中。IDA会对目标程序进行静态分析,并将二进制代码转换为可读的汇编语言代码。对于C语言编写的程序,IDA会尽可能地还原出C代码的结构和逻辑。 在IDA中,我们可以看到反汇编后的代码,以及反汇编后所生成的控制流图。控制流图可以帮助我们了解程序的执行流程和函数调用关系。 如果反汇编出的代码是汇编语言的形式,我们可以通过IDA的辅助功能将其转换为C代码。IDA提供了一些工具和插件,可以将汇编代码转换为等效的C代码。这样,我们就能更方便地理解和分析程序的功能。 然而,需要注意的是,IDA的反汇编过程并不是100%准确的。原因是编译器在将C代码转换为机器码时会进行优化和重排指令,这会导致一些信息的丢失。因此,反汇编的结果可能不完全等同于原始的C代码。 总而言之,借助IDA的反汇编功能,我们可以更好地分析和理解目标程序的功能和逻辑。但是需要谨记反汇编结果并不完全准确,需要结合其他手段来进行分析和验证。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值