C 虛函式系列之三 虛函式呼叫的另類 注入

2021-04-02 05:42:43 字數 2731 閱讀 6495

author

:jeff2005-12-7

關鍵字:

c++

虛函式注入

環境:window xp professional + sp2, vc6.0

在用組合語言呼叫

class

的private

虛函式outp()

時,注意到在呼叫之前先

push 23

,而在呼叫後並沒有

pop清棧。如果畫蛇添足,加上

pop語句,反而導致棧的崩潰。因為

c++成員函式的呼叫約定為

thiscall

。從網上摘錄的關於函式呼叫約定:1、

_stdcall

是pascal

程式的預設呼叫方式,通常用於

win32 api

中,函式採用從右到左的壓棧方式,自己在退出時清空堆疊。

vc將函式編譯後會在函式名前加上下劃線字首,在函式名後加上

"@"和引數的位元組數。2、

_cdecl是c

和c

++程式的預設呼叫方式。每乙個呼叫它的函式都包含清空堆疊的**,所以產生的可執行檔案大小會比呼叫

_stdcall

函式的大。函式採用從右到左的壓棧方式。

vc將函式編譯後會在函式名前面加上下劃線字首。是

mfc預設呼叫約定。3、

__fastcall

呼叫約定是"人

"如其名,它的主要特點就是快,因為它是通過暫存器來傳送引數的(實際上,它用

ecx和

edx傳送前兩個雙字(

dword

)或更小的引數,剩下的引數仍舊自右向左壓棧傳送,被呼叫的函式在返回前清理傳送引數的記憶體棧),

vc將函式編譯後會在函式名前面加上

"@"字首,在函式名後加上

"@"和引數的位元組數。4、

thiscall

僅僅應用於

"c++"

成員函式。

this

指標存放於

ecx暫存器,引數從右到左壓。

thiscall5、

naked call

採用1-4

的呼叫約定時,如果必要的話,進入函式時編譯器會產生**來儲存

esi,

edi,

ebx,

ebp暫存器,退出函式時則產生**恢復這些暫存器的內容。

c++成員函式的呼叫約定為

thiscall

,意味著

ecx中存放著

this

指標。如果讓

ecx存放別的

class

指標,會有什麼後果呢?修改

c001

::outp()

的**為:

class

c001

……};

另外再定義乙個

class

:class

c003

;virtual

~c003

() ;

private

:virtual

void

output

(void

) };

main()

也改改:

intmain

(void);

return0;

}編譯,執行,輸出為:

number = 23

haha, it's turn to me!

本應該執行

c001::display()

,輸出為

display

c001

的,結果怎麼不是?

分析一下,可以判定,在

c001::outp()

函式體內,控制權被

c003

奪取,轉而執行

c003::output()

。為什麼呢?細心之下會發現,

c003::output()

是c003的第2

個虛函式,

c001::display()

為c001的第2

個虛函式,即它們在各自

virtual table

中的位置相同。

在呼叫c001::outp()

函式中的

display()

時,先通過

ecx取

this

指標,ecx

已被偷梁換柱儲存的是指向物件

c003

的指標,然後到

virtual table找第2

個虛函式

(找第幾個在編譯期間決定

),當然就呼叫了

c003的第2

個虛函式

output()。(

盡量保證相同位置虛函式的引數對齊,否則棧可能會崩潰

)。執行成功

~~~總之,在編譯期間沒有確定位址的

class

虛函式,都可以這樣偷梁換柱地注入~~當

class

的虛函式的呼叫約定為

__stdcall

,呼叫時除要

push

引數外,在最後還需要讓

ecx儲存

this

指標並push

這個指標,呼叫後不需要清棧。呼叫約定為

__cdecl

,呼叫時除要

push

引數外,需要直接

pushthis

指標,呼叫後需自己

pop清棧。

手撕虛函式,虛函式呼叫虛函式

乙個類的記憶體分布,虛函式表指標,普通成員變數,sizeof a 為乙個虛表指標 32位是4位元組 普通成員變數 靜態什麼的都不是 虛函式本身也是函式,相當於乙個指標,虛函式表裡面含有虛函式,相當於乙個二級指標,虛函式表指標指向虛函式表,相當於乙個 指標,所有可以通過乙個 指標直接訪問某個虛函式。見...

c 基礎系列 虛函式 虛表

歡迎來到c 基礎系列的部落格 我們剛才例項化物件的時候,示例一直豬是這樣寫的 pig pig new pig 但因為其是繼承animal動物類的,所以說我們其實也可以這樣寫 animal pig new pig 這種寫法一般情況下沒有毛病,但是如果子類重寫了基類的方法時,就會出現問題 呼叫的還是基類...

C 虛函式 三

三.虛函式使用技巧 3.1 private的虛函式 考慮下面的例子 class a private virtual void bar class b public a 在這個例子中,雖然bar 在a類中是private的,但是仍然可以出現在派生類中,並仍然可以與public或者protected的虛...