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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

c++反汇编与逆向分析

發布時間:2025/3/20 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++反汇编与逆向分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. _cdecl: c\c++默認調用方式,調用方平衡棧,不定參數的函數可以使用??ret;?
2. _stdcall: 被調用方平衡棧,不定參數的函數不可以使用?????????ret 4;
3. _fastcall:寄存器方式傳參,被調用方平衡棧,不定參數的函數不可以使用, cx,dx分別存儲1,2參數,其余參數還是用棧

call 指令? 隱含push 函數返回下一條指令地址
_cdecl 函數的結束"}"?mov???????? esp,ebp?
???????????pop???????? ebp?
???????????ret?????//ret指令 會把當前esp指向值更新到eip,同時esp-4, 此時一個棧幀調用完成。
???????????//如果函數有返回值會先賦值給eax,再執行ret.
int _fastcall fun22(int a, int b, int c,int d)
{??????????????????F9???ecx = a, edx = b esp存儲函數返回下一條指令地址 esp+4 = c esp+8 = d?????
008613C0? push??????? ebp?
008613C1? mov???????? ebp,esp?
008613C3? sub???????? esp,0E4h????? F9???ecx = a, edx = b ebp+4存儲函數返回下一條指令地址 ebp+8 = c ebp+0xc = d?

第七章:變量在內存中的位置和訪問方式
作用域:全局變量屬于進程作用域;靜態變量屬于文件作用域;局部變量屬于函數作用域;

在大多數情況下,在PE文件中的只讀數據節中,常量的節屬性被修飾為不可寫;而全局變量和靜態變量則在屬性為可讀寫的數據節中。
全局變量和常量類似,被寫入文件中,當用戶執行該文件,OS分析并加載各節到虛擬內在地址,這是全局變量已經存在了,加載完才開始執行入口點代碼。
全局變量的內在地址在全局數據區中,通過棧指針是無法訪問到,訪問也與常量類似,都是通過立即數來訪問。局部變量使用ebp或esp間接訪問。
全局變量在內存中的地址順序是先定義的變量在低地址,后定義的在高地址,局部變量剛好相反。

靜態變量:全局靜態變量,局部靜態變量
?全局靜態變量和全局變量類似,只是編譯器限制外部源碼文件訪問的全局變量。
?局部靜態變量會預先被作為全局變量處理,和全局變量都保存在執行文件中的數據區中,只是被定義在某個作用域內;
??局部靜態變量的初始化只是在做賦值操作而已,c++語法規定局部靜態變量只被初始化一次。
?
?在第一個局部靜態變量附近分配一個地址存放標志。

void InNumber(int var)
{
??? static int nInt = var;
??? static int nInt2 = var+2;
??? static int nInt3 = var+3;
??? printf("%d,%d,%d",nInt, nInt2, nInt3);
}
static int nInt = var;
00AC1003? mov???????? eax,dword ptr ds:[00AC3370h]?
00AC1008? and???????? eax,1?
00AC100B? jne???????? InNumber+25h (0AC1025h)?
00AC100D? mov???????? ecx,dword ptr ds:[0AC3370h]?
00AC1013? or????????? ecx,1?
00AC1016? mov???????? dword ptr ds:[0AC3370h],ecx?
00AC101C? mov???????? edx,dword ptr [var]?
00AC101F? mov???????? dword ptr ds:[0AC337Ch],edx?
??? static int nInt2 = var+2;
00AC1025? mov???????? eax,dword ptr ds:[00AC3370h]?
00AC102A? and???????? eax,2?
00AC102D? jne???????? InNumber+4Ah (0AC104Ah)?
00AC102F? mov???????? ecx,dword ptr ds:[0AC3370h]?
00AC1035? or????????? ecx,2?
00AC1038? mov???????? dword ptr ds:[0AC3370h],ecx?
00AC103E? mov???????? edx,dword ptr [var]?
00AC1041? add???????? edx,2?
00AC1044? mov???????? dword ptr ds:[0AC3374h],edx?
??? static int nInt3 = var+3;
00AC104A? mov???????? eax,dword ptr ds:[00AC3370h]?
00AC104F? and???????? eax,4?
00AC1052? jne???????? InNumber+6Fh (0AC106Fh)?
00AC1054? mov???????? ecx,dword ptr ds:[0AC3370h]?
00AC105A? or????????? ecx,4?
00AC105D? mov???????? dword ptr ds:[0AC3370h],ecx?
00AC1063? mov???????? edx,dword ptr [var]?
00AC1066? add???????? edx,3?
00AC1069? mov???????? dword ptr ds:[0AC3378h],edx?
??? printf("%d,%d,%d",nInt, nInt2, nInt3);
00AC106F? mov???????? eax,dword ptr ds:[00AC3378h]

如果如下
void InNumber(int var)
{
??static int nn = 33;???//nn將不再使用標志,直接當作全局變量處理,但作用域還是局部。
??? static int nInt = var;

通過名字粉碎來區別作用域,UE打開.obj文件如下:
nInt3@?1??InNumber@@YAXH@Z@4HA
$?nInt@?1??InNumber@@YAXH@Z@4HA

void Show(char szBuffer[])?//數組傳參
{
??? int wrongSize = sizeof(szBuffer);?//此時szBuffer為指針類型,并非數組, 4
??? int rightSize = strlen(szBuffer);?//取決外部傳入
??? strcpy_s(szBuffer, 20, "hello, my sunny!");
}

局部靜態數組和局部靜態變量有些不同,無論局部靜態數組有多少個元素,也只會檢查一次初始標志位。
數組的下標尋址比指針尋址高效。數組名本身就是常量地址。而指針需要取其指向的地址值。

第九章:結構體和類
空類實際長度為1字節,如果不占內存,則無法得到空類實例的地址,this指針失效,因此不能被實例化;沒有數據成員,還可以有成員函數。

結構體和類中的數據成員分配內存時,結構體中的當前數據成員類型長度為M,指定的對齊值為N,那么實際對齊值為q=min(M,N),其成員的地址安排在q的倍數上。
結構體中數據成員類型最大值為M,指定的對齊值為N,那么實際對齊值為min(M,N). 結構體整體大小為min(M,N)的整數倍。
#pragma pack(N) //調整對齊大小。
當結構體中以數組作為成員時,將根據數組元素的長度計算對齊值,而不是按數組的整體大小去計算。
struct STR{
?char cChar;
?char cArray[4];
?short sShort;
};???
??STR ss = {'y',"and",4};
????//79 61 6e 64 00 cc 04 00
????//y??a? n? d??????? 4
void *pp = &((STR*)NULL)->sShort;?//取相對地址。

類的成員函數默認是thiscall調用方式,與_stdcall相同,被調用方負責平衡棧,但傳參不同,第一參數(this)使用寄存器ecx傳遞,而非棧頂。
thiscall不是關鍵字,不能顯示調用。

靜態數據成員和靜態變量原理相同(有作用域的特殊全局變量),初值會寫入編譯鏈接后的執行文件后。所以不參與對象size計算。

類對象作為參數,如果只是簡單變量,真依序壓棧對象的成員變量,最先定義的最后壓棧。如果沒有構造函數,也不會調系統默認的構造函數。

class CRet
{
public:
??? int a;
??? int b[8];
};

CRet GetReturn()
{
??? CRet temp;
??? temp.a = 3;
??? for (int i = 0; i < 8; ++i)
??? {
??????? temp.b[i] = i + 6;
??? }
??? return temp;
}

int _tmain(int argc, _TCHAR* argv[])
{
??? CRet mobj;
??//1.此時main函數已經臨時對象temp
??? mobj = GetReturn();?//2.GetReturn函數結束,棧幀關閉,所以棧幀關閉前會復制到temp,3. 再次temp賦值給mobj,過了這條語句作用域,temp消失。//如果重載了“=”,這里會調用=
???
??? 如果為如下://定義時賦初值才會調用拷貝構造
??? CRet mobj = GetReturn(); //不會有臨時對象,而是直接把mobj的地址作為隱含的參數傳遞給GetReturn(),在GetReturn()函數內部完成拷貝構造的過程。
???
//note:
1. mobj = GetReturn(); ";"后會析構
2. mobj = GetReturn(),
?printf("hell");??則是在這里的";"后才會析構這個temp對象。
3. 當引用這個temp對象時,生命期與引用相同。
?
//下面兩個有錯誤,不要返回局部變量
CRet* GetAA()
{
??? CRet temp;
??? return &temp;
}
CRet& GetBB()
{
??? CRet temp;
??? return temp;
}

thiscall 使用ecx傳this指針, __fastcall使用ecx用來傳第一個參數,所以不能作為唯一識別特征。


局部對象
堆對象??new成功后再會調構造函數
參數對象?調用拷貝構造函數,該構造函數只有一個參數,類型為對象的引用
返回對象
全局對象??//main函數退出后調用析構函數?
靜態對象??//main函數退出后調用析構函數

定點斷點, tools->options->debugging->symbols select Microsoft Symbols Servers to download symbols.
Ctrl+B than put in function name.
Ctrl+Alt+B list and edit all breakpoint, Condition and Hit Count.
編譯器在以下兩種情況下會提供默認的構造函數:
1.本類、本類中定義的成員對象或者父類中有虛函數存在;
2.父類或本類中定義的成員對象帶有構造函數;
如果沒有這兩種情況,默認構造函數已經沒有存在的意義,只會影響效率。

delete p; delete []p; 釋放對象類型標志,1為單個對象,3為釋放對象數組,0表示僅僅執行析構函數。
申請對象數組時,由于對象都在同一個堆空間中,編譯器使用了堆空間的前4字節數據來保存對象的總個數。

析構順序,調用自身的析構函數->聲明倒序調用成員對象的析構函數->調用基類析構函數

基類聲明為虛析構
CBase *psub = new CSub;
delete psub;
?????mov???????? edx,dword ptr [ebp-0ECh]? //傳遞this
0039183E? mov???????? eax,dword ptr [edx]? ???//取得虛表指針
00391840? mov???????? ecx,dword ptr [ebp-0ECh]? //傳遞this
00391846? mov???????? edx,dword ptr [eax]? ???//間接調用虛析構函數
00391848? call??????? edx?

基類聲明為虛析構
CBase *psub = new CSub;
delete psub;
?????mov???????? ecx,dword ptr [ebp-0ECh]? ??????//傳遞this
012A183C? call??????? CBase::`scalar deleting destructor' (012A124Eh)??//直接調用基類析構函數

要習慣給析構函數加virtual

總結

以上是生活随笔為你收集整理的c++反汇编与逆向分析的全部內容,希望文章能夠幫你解決所遇到的問題。

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