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的虛...