逆向分析一個完整的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( 3664);
    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( 3664);
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++反匯編代碼,應該可以對付一般的應用,如果大家還有什么問題,或者建議歡迎討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM