逆向分析一个完整的C++程序包含寄存器与参数传递详解

简介: 最近在分析C++ dump 文件的时候觉得有必要将一些必要的反汇编东西总结一下以备别人参考,自己有时间的时候也可以进行更多的改进。下面通过一个简单的C++代码转成汇编代码后的详细解释说明一下C++和汇编的对应关系,以及如何识别汇编代码中进行的一些操作的意义。

最近在分析C++ dump 文件的时候觉得有必要将一些必要的反汇编东西总结一下以备别人参考,自己有时间的时候也可以进行更多的改进。下面通过一个简单的C++代码转成汇编代码后的详细解释说明一下C++和汇编的对应关系,以及如何识别汇编代码中进行的一些操作的意义。代码的调用关系如下图所示:

完整C++代码下:

 

 

复制代码
int InternalFunctionA(int nSizeA1, int nSizeA2)
{
    int localnSizeA1 = nSizeA1;
    int localnSizeA2 = nSizeA2;

    int nFunctionA = localnSizeA1 + localnSizeA2;

    return nFunctionA;
}

int InternalFunctionB(int nSizeB1, int nSizeB2)
{

    int nFunctionA = InternalFunctionA(nSizeB1, nSizeB2);
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    
    int nFunctionVal = InternalFunctionB(36, 64);
    cout<<"Hello SolidMango!"<<endl;
    return 0;

}
复制代码

 

那么这段简单的C++代码在转换成汇编代码之后是什么样子的呢?让我们拭目以待,首先让我们看看main函数转换后的代码(debug版), 如下,我们逐条来进行分析,

 

复制代码
int _tmain(int argc, _TCHAR* argv[])
{
00411570  push        ebp  //栈底压栈
00411571  mov         ebp,esp //栈底下移,更详细的请参考我关于ebp,esp的解释
00411573  sub         esp,0CCh //局部变量预留空间
00411579  push        ebx  //保存ebx  
0041157A  push        esi  //保存esi  
0041157B  push        edi  //保存edi  
0041157C  lea         edi,[ebp-0CCh] //下移edi到栈顶
00411582  mov         ecx,33h //0CCh/4 = 33h
00411587  mov         eax,0CCCCCCCCh //eax赋值
0041158C  rep stos    dword ptr es:[edi] //从edi开始做33h次赋值0CCCCCCCCh ,初始化栈内存
    
    int nFunctionVal = InternalFunctionB(36, 64);
0041158E  push        40h  //参数64入栈,
00411590  push        24h  //参数36入栈
00411592  call        InternalFunctionB (41101Eh) );//到41101Eh处函数调用
00411597  add         esp,8 //函数调用后将参数弹出,清理栈
0041159A  mov         dword ptr [nFunctionVal],eax 
    cout<<"Hello SolidMango!"<<endl;
0041159D  mov         esi,esp 
0041159F  mov         eax,dword ptr [__imp_std::endl (41A338h)] 
004115A4  push        eax  
004115A5  push        offset string "Hello SolidMango!" (417800h) 
004115AA  mov         ecx,dword ptr [__imp_std::cout (41A33Ch)] 
004115B0  push        ecx  
004115B1  call        std::operator<<<std::char_traits<char> > (411163h) 
004115B6  add         esp,8 
004115B9  mov         ecx,eax 
004115BB  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (41A320h)] 
004115C1  cmp         esi,esp 
004115C3  call        @ILT+430(__RTC_CheckEsp) (4111B3h) 
    return 0;
004115C8  xor         eax,eax 

}
004115CA  pop         edi  //恢复edi
004115CB  pop         esi  //恢复esi
004115CC  pop         ebx  //恢复ebx
004115CD  add         esp,0CCh //栈顶上移
004115D3  cmp         ebp,esp //检查栈平衡
004115D5  call        @ILT+430(__RTC_CheckEsp) (4111B3h) 
004115DA  mov         esp,ebp //恢复上一个栈帧的ebp,esp
004115DC  pop         ebp  
004115DD  ret//函数返回
复制代码

 

 另外两层函数调用的汇编代码如下,感兴趣的读者可以对比一下,和main函数的过程相似,

 

复制代码
int InternalFunctionA(int nSizeA1, int nSizeA2)
{
004114C0  push        ebp  
004114C1  mov         ebp,esp 
004114C3  sub         esp,0E4h 
004114C9  push        ebx  
004114CA  push        esi  
004114CB  push        edi  
004114CC  lea         edi,[ebp-0E4h] 
004114D2  mov         ecx,39h 
004114D7  mov         eax,0CCCCCCCCh 
004114DC  rep stos    dword ptr es:[edi] 
    int localnSizeA1 = nSizeA1;
004114DE  mov         eax,dword ptr [nSizeA1] 
004114E1  mov         dword ptr [localnSizeA1],eax 
    int localnSizeA2 = nSizeA2;
004114E4  mov         eax,dword ptr [nSizeA2] 
004114E7  mov         dword ptr [localnSizeA2],eax 

    int nFunctionA = localnSizeA1 + localnSizeA2;
004114EA  mov         eax,dword ptr [localnSizeA1] 
004114ED  add         eax,dword ptr [localnSizeA2] 
004114F0  mov         dword ptr [nFunctionA],eax 

    return nFunctionA;
004114F3  mov         eax,dword ptr [nFunctionA] 
}
004114F6  pop         edi  
004114F7  pop         esi  
004114F8  pop         ebx  
004114F9  mov         esp,ebp 
004114FB  pop         ebp  
004114FC  ret   
int InternalFunctionB(int nSizeB1, int nSizeB2)
{
00411510  push        ebp  
00411511  mov         ebp,esp 
00411513  sub         esp,0CCh 
00411519  push        ebx  
0041151A  push        esi  
0041151B  push        edi  
0041151C  lea         edi,[ebp-0CCh] 
00411522  mov         ecx,33h 
00411527  mov         eax,0CCCCCCCCh 
0041152C  rep stos    dword ptr es:[edi] 

    int nFunctionA = InternalFunctionA(nSizeB1, nSizeB2);
0041152E  mov         eax,dword ptr [nSizeB2] 
00411531  push        eax  
00411532  mov         ecx,dword ptr [nSizeB1] 
00411535  push        ecx  
00411536  call        InternalFunctionA (411140h) 
0041153B  add         esp,8 
0041153E  mov         dword ptr [nFunctionA],eax 
    return 0;
00411541  xor         eax,eax 
}
00411543  pop         edi  
00411544  pop         esi  
00411545  pop         ebx  
00411546  add         esp,0CCh 
0041154C  cmp         ebp,esp 
0041154E  call        @ILT+430(__RTC_CheckEsp) (4111B3h) 
00411553  mov         esp,ebp 
00411555  pop         ebp  
00411556  ret
复制代码

 

总结:通过这几篇文章的总结,相信大家已经可以看懂一些常规的C++反汇编代码,应该可以对付一般的应用,如果大家还有什么问题,或者建议欢迎讨论。

目录
相关文章
|
25天前
|
存储 Serverless Python
函数调用的形式
在编程中,函数调用是一种基本且重要的操作,它允许我们执行预定义的代码块,并可能返回结果。函数调用有多种形式,每种形式都有其特定的用途和优势。本文将探讨函数调用的一些常见形式,并附上相应的代码示例。
16 1
|
7月前
第4章 MATLAB编程基础——4.6 M文件中变量的检测与传递
第4章 MATLAB编程基础——4.6 M文件中变量的检测与传递
|
10月前
|
存储 C语言 C++
Win32程序入口识别,定位回调函数,具体事件处理的定位,ESP寻址方式,压栈方式复习
Win32程序入口识别,定位回调函数,具体事件处理的定位,ESP寻址方式,压栈方式复习
|
存储 网络协议 C语言
【CSAPP】x86-64的机器代码和原始的C代码差别巨大,一些常在C语言中隐藏的处理器状态
【CSAPP】x86-64的机器代码和原始的C代码差别巨大,一些常在C语言中隐藏的处理器状态
56 0
|
存储 前端开发 rax
【CSAPP】x86-64的中央处理单元16个存储64位值的通用目的寄存器
【CSAPP】x86-64的中央处理单元16个存储64位值的通用目的寄存器
116 0
【CSAPP】x86-64的中央处理单元16个存储64位值的通用目的寄存器
西门子S7-1200移动指令编程实例,移动和块移动指令、填充指令、交换 指令的作用是什么?
西门子S7-1200的移动指令包括移动和块移动指令、填充指令、交换指令。
西门子S7-1200移动指令编程实例,移动和块移动指令、填充指令、交换 指令的作用是什么?
|
程序员 C语言 Python
维基百科中对函数的定义:子程序
维基百科中对函数的定义:子程序
|
Java Linux Android开发
【Android 逆向】函数拦截原理 ( 可执行程序基本结构 | GOT 全局偏移表 | 可执行程序函数调用步骤 )
【Android 逆向】函数拦截原理 ( 可执行程序基本结构 | GOT 全局偏移表 | 可执行程序函数调用步骤 )
212 0
【Android 逆向】函数拦截原理 ( 可执行程序基本结构 | GOT 全局偏移表 | 可执行程序函数调用步骤 )
|
Windows
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★
521 0
【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 数据查找技巧 | 地址访问调试 | 指令选择技巧 | MOV 汇编指令含义 | 基址值搜索 ) ★
|
存储 数据处理 Android开发
【Android 逆向】x86 汇编 ( call 子函数调用指令 | jmp 跳转指令 | lea 加载指令 | mov 数据传送指令 )
【Android 逆向】x86 汇编 ( call 子函数调用指令 | jmp 跳转指令 | lea 加载指令 | mov 数据传送指令 )
206 0