日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

个简单C++程序反汇编解析 (Rev. 3)

發布時間:2025/6/15 c/c++ 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 个简单C++程序反汇编解析 (Rev. 3) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如果想要了解C++內部的實現原理,沒有什么比觀察C++代碼對應的匯編代碼來的更直接了。本系列主要從匯編角度研究C++代碼和匯編的對應關系,揭示C++內部的機制和原理。在第一篇文章中我將從一個簡單的C++程序著手快速解釋一下C++反匯編代碼的基本的結構和內容,相當于一個簡單的Preview。而在后續的文章中,我將根據不同的Topic,詳細解釋C++代碼對應的反匯編代碼。

一個簡單的C++程序示例如下:

class my_class

{

public :

????my_class()

????{

????????m_member = 1;

????}

?

????void method(int n)

????{

????????m_member = n;

????}

?

????~my_class()

????{

????????m_member = 0;

????}

?

private :

????int m_member;

};

?

int _tmain(int argc, _TCHAR* argv[])

{

????my_class a_class;

????a_class.method(10);

?

????return 0;

}

可以直接Debug的時候看到Assembly代碼,不過這樣獲得的代碼注釋比較少。比較理想的方法是利用VC編譯器的一個選項/FAs來生成對應的匯編代碼。/FAs還會在匯編代碼中加入注釋注明和C++代碼的對應關系,十分有助于分析。在VS2005中可以這樣打開/FAs:

Build代碼,可以在輸出目錄下發現對應的.ASM文件。本文將逐句分析匯編代碼和C++的對應關系。

首先是WinMain:

_TEXT?SEGMENT

_wmain??????PROC

??????push??ebp?????????????????????????????????;?保存舊的ebp

??????mov???ebp, esp????????????????????????????; ebp保存當前棧的位置

??????push??-1??????????????????????????????????;?建立SEH(Structured Exception Handler)

????????????????????????????????????????????????; -1表示表頭,沒有Prev

??????push??__ehhandler$_wmain??????????????????; SEH異常處理程序的地址

??????mov???eax, DWORD PTR fs:0?????????????????; fs:0指向TEB的內容,頭4個字節是當前SEH鏈的地址

??????push??eax?????????????????????????????????;?保存起來

??????sub???esp, d8H????????????????????????????;?分配d8H字節的空間

??????push??ebx

??????push??esi

??????push??edi

??????lea???edi, DWORD PTR [ebp-e4H]????????????; 確定局部變量的起始地址。e4H = d8H + 4 * 3,跳過之前建立SEH鏈所用的3個Push指令所占用的棧的空間,以及sub esp, d8h為局部變量分配的d8H字節空間

??????mov???ecx, 36H????????????????????????????; 36H*4H=d8H,也就是用36HccccccccH填滿剛才分配的d8H字節空間

??????mov???eax, ccccccccH

??????rep stosd

??????mov???eax, DWORD PTR ___security_cookie??

??????xor???eax, ebp???

??????push??eax?????????????????????????????????; ebp ^ __security_cookie壓棧保存

??????lea???eax, DWORD PTR [ebp-0cH]????????????; ebp-0cH是之前main的起始代碼中在堆棧中建立的SEH結構的首地址

??????mov???DWORD PTR fs:0, eax?????????????????;?設置到TEB中作為當前ActiveSEH鏈表末尾

到此為止棧的內容是這樣的:

低地址

Security cookie after XOR

Edi

Esi

Ebx

Local stack: d8H

Old fs:0

__ehhandler$_wmain

ffffffffH

Old ebp

高地址

main接著后面調用my_class的構造函數

??????lea???ecx, DWORD PTR [ebp-14H]

??????call????0my_class@@QAE@XZ?????????????????;?調用my_class::my_class, ??my_class@@QAE@XZ是經過Name Mangling后的名字

??????mov???DWORD PTR [ebp-4], 0????????????????;?進入__try塊,在Main中有一個隱式的__try/__except

接著調用my_class::method:

??????push??10??????????????????????????????????;?參數入棧

??????lea???ecx, DWORD PTR [ebp-14H]????????????;?遵循thiscall調用協定,ecx存放的是this指針

??????call???method@my_class@@QAEXH@Z???????????;?調用子程序my_class:method(10)

之后是析構:

??????mov???DWORD PTR [ebp-e0H], 0??????????????;?用來放置返回值

??????mov???DWORD PTR [ebp-4], -1???????????????;?標記TRY的正常結束

??????lea???ecx, DWORD PTR [ebp-14H]????????????; a_class的地址作為this存入ECX

??????call????1my_class@@QAE@XZ?????????????????; my_class::~my_class

??????mov???eax, DWORD PTR [ebp-e0H]????????????;?返回值按照約定放入eax

Main函數退出代碼如下:

??????push??edx

??????mov???ecx, ebp

??????push??eax

??????lea???edx, DWORD PTR $LN7@wmain

??????call??@_RTC_CheckStackVars@8??????????????;?檢查棧

??????pop???eax

??????pop???edx

??????mov???ecx, DWORD PTR [ebp-0cH]????????????;?取出之前保存的舊的fs:0,并恢復

??????mov???DWORD PTR fs:0, ecx

??????pop???ecx

??????pop???edi

??????pop???esi

??????pop???ebx

??????add???esp, e4H????????????????????????????;?退掉分配的d8H +?建立SEH鏈所需的0cH字節

??????cmp???ebp, esp

??????call??__RTC_CheckEsp??????????????????????;?檢查esp值,這個時候esp應該和ebp匹配,否則說明出現了棧不平衡的情況,這種情況下調用子程序報錯

??????mov???esp, ebp????????????????????????????;?恢復ebpesp

??????pop???ebp?????????????????????????????????;?恢復原來的ebp

??????ret???0

_wmain??????ENDP

專門用于SEH的子程序。__unwindfunclet$_wmain$0當異常發生的時候被調,負責進行棧展開,主要是調用析構函數。__ehhandler$_wmain則是在exception被拋出的時候調用。

Text$x??????SEGMENT

__unwindfunclet$_wmain$0:???????????????????????;?SEH發生的時候會調用該函數,析購a_class

??????lea???ecx, DWORD PTR [ebp-14H]????????????; ecx = [ebp – 14H],也就是a_class的地址

??????jmp?????1my_class@@QAE@XZ?????????????????;?調用my_class::~my_class

__ehhandler$_wmain:

??????mov???edx, DWORD PTR [esp+8]??????????????; esp =?當前的fs:0, [esp + 8] =?之前的SEH結構,也就是main中建立的

??????lea???eax, DWORD PTR [edx+0cH]????????????; edx + 0Ch =?當前的ebp,也就是mainebp,此時不能直接使用ebp因為可能會從任意函數調過來,此時ebp是該函數的ebp,而不是mainebp

??????mov???ecx, DWORD PTR [edx-e0H]????????????;?之前存下去的__security_cookie ^ ebp

??????xor???ecx, eax????????????????????????????;?再次和ebp相異或

??????call??@__security_check_cookie@4??????????;?此時ecx應該等于__security_cookie,否則說明棧的內容被惡意改動(或者編程錯誤)

??????mov???eax, OFFSET __ehfuncinfo$_wmain

??????jmp???___CxxFrameHandler3

text$x??????ENDS

My_class::my_class構造函數如下。構造函數本質上就是一個全局函數,名字是經過打亂的(Name Mangling),這樣可以和同一Class和其他Class的同名方法區別開來。不同編譯器有不同規則,因此不必過于深究。

_TEXT?SEGMENT

??0my_class@@QAE@XZ PROC

??????push??ebp?????????????????????????????????;?保存舊的ebp

??????mov???ebp, esp????????????????????????????; ebp保存當前棧的位置

??????sub???esp, ccH????????????????????????????;?給棧分配ccH個字節

??????push??ebx?????????????????????????????????;?保存常用寄存器

??????push??esi

??????push??edi

??????push??ecx

??????lea???edi, DWORD PTR [ebp-ccH]????????????;?從分配的位置開始

??????mov???ecx, 33H????????????????????????????;?33HccccccccH

??????mov???eax, ccccccccH??????????????????????;?也就是33H*4H=ccH,正好是分配的大小

??????rep stosd?????????????????????????????????;?從而把整個棧上當前分配的空間用ccH填滿

??????pop???ecx

??????mov???DWORD PTR [ebp-8], ecx??????????????;?按照約定,一般用ECX保存this指針

????????????????????????????????????????????????;?this存入到ebp-8,并不是很必要,因為這是Debug版本

???????????????????????????????????????????????

?

; 10???:?????{

; 11???:?????????m_member = 1;

?

??????mov???eax, DWORD PTR [ebp-8]??????????????; eax中存放this

??????mov???DWORD PTR [eax], 1??????????????????; this的頭四個bytem_member的內容

?

; 12???:?????}

?

??????mov???eax, DWORD PTR [ebp-8]??????????????;?多余的一句話,可以優化掉

??????pop???edi

??????pop???esi

??????pop???ebx

??????mov???esp, ebp????????????????????????????;?恢復esp,因此就算是中間棧運算出錯,最后也不會導致災難性的結果,只要ebp還是正確的

??????pop???ebp

??????ret???0

??0my_class@@QAE@XZ ENDP

My_class::method的實現如下:

_TEXT?SEGMENT

?method@my_class@@QAEXH@Z PROC??????????????????; my_class::method

?

; 15???:?????{

?

??????push??ebp

??????mov???ebp, esp

??????sub???esp, ccH

??????push??ebx

??????push??esi

??????push??edi

??????push??ecx

??????lea???edi, DWORD PTR [ebp-ccH]

??????mov???ecx, 33H

??????mov???eax, ccccccccH

??????rep stosd

??????pop???ecx

??????mov???DWORD PTR [ebp-8], ecx

?

; 16???:?????????m_member = n;

?

??????mov???eax, DWORD PTR [ebp-8]??????????????; eax中存放this

??????mov???ecx, DWORD PTR [ebp+8]??????????????; ebp -> ebp

????????????????????????????????????????????????; ebp + 4 -> IP

????????????????????????????????????????????????; ebp + 8 -> n

????????????????????????????????????????????????;?n存入ecx

??????mov???DWORD PTR [eax], ecx????????????????; this頭四個字節是m_member,?因此這句話就是m_member = n

?

; 17???:?????}

?

??????pop???edi

??????pop???esi

??????pop???ebx

??????mov???esp, ebp

??????pop???ebp

??????ret???4???????????????????????????????????;?等價于

????????????????????????????????????????????????; ret?恢復EIP,返回調用地址

????????????????????????????????????????????????; add esp, 4 ->?n從棧上Pop

?method@my_class@@QAEXH@Z ENDP

最后的析構函數,和前面的代碼并無區別。

_TEXT??SEGMENT

??1my_class@@QAE@XZ PROC????????????????????????; my_class::~my_class

?

; 20???:?????{

?

???????push???ebp

???????mov????ebp, esp

???????sub????esp, 204?????????????????????????

???????push???ebx

???????push???esi

???????push???edi

???????push???ecx

???????lea????edi, DWORD PTR [ebp-204]

???????mov????ecx, 33H?????????????????????????

???????mov????eax, ccccccccH???????????????????

???????rep stosd

???????pop????ecx

???????mov????DWORD PTR _this$[ebp], ecx

?

; 21???:?????????m_member = 0;

?

???????mov????eax, DWORD PTR [ebp-8]

???????mov????DWORD PTR [eax], 0

?

; 22???:?????}

?

???????pop????edi

???????pop????esi

???????pop????ebx

???????mov????esp, ebp

???????pop????ebp

???????ret????0

??1my_class@@QAE@XZ ENDP????????????????????????; my_class::~my_class

_TEXT??ENDS

?

總結

以上是生活随笔為你收集整理的个简单C++程序反汇编解析 (Rev. 3)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。