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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

12.IDA-虚函数和虚表(vf代表虚函数,vf3代表this指向第三个函数)

發(fā)布時(shí)間:2025/3/15 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 12.IDA-虚函数和虚表(vf代表虚函数,vf3代表this指向第三个函数) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

vtable

編譯器會(huì)為每一個(gè)包含虛函數(shù)的類(或通過(guò)繼承得到的子類)生成一個(gè)表,其中包含指向類中每一個(gè)虛函數(shù)的指針,這樣的表就叫做虛表(vtable)

__vfptr

每個(gè)包含虛函數(shù)的類對(duì)象都獲得__vfptr指針,并且是對(duì)象的第一個(gè)數(shù)據(jù)成員

編譯器必須要保證虛函數(shù)表的指針存在于對(duì)象實(shí)例中最前面的位置

在計(jì)算對(duì)象的總大小時(shí),也必須考慮到虛表指針。比如new,傳遞給new的大小值不僅包括類(以及任何超類)中的所有顯式聲明的字段占用的空間,而且包括虛表指針?biāo)璧娜魏慰臻g?
示例代碼:

class Base { public: (10個(gè)字節(jié),0,4,8,12,this)virtual void vf1() = 0;virtual void vf2(){ cout<<"Base::vf2"<<endl; }virtual void vf3(){ cout<<"Base::vf3"<<endl; }virtual void vf4(){ cout<<"Base::vf4"<<endl; } private:int x,y; };class Sub: public Base { public:virtual void vf1(){cout<<"Sub::vf1"<<endl; }virtual void vf3(){cout<<"Sub::vf3"<<endl; }virtual void vf5(){cout<<"Sub::vf5"<<endl; } private:int z; };void call_vf(Base* b) {b->vf3(); }int _tmain(int argc, _TCHAR* argv[]) {Base *b = new Sub;call_vf(b); }

IDA分析如下:?

值得注意的是,虛表索引操作非常類似于結(jié)構(gòu)體引用操作。實(shí)際上,它們之間并無(wú)區(qū)別?。因此,我們可以定義一個(gè)結(jié)構(gòu)體來(lái)表示一個(gè)類的虛表的布局,然后利用這個(gè)已定義的結(jié)構(gòu)體來(lái)提高反匯編代碼清單的可讀性?

這個(gè)結(jié)構(gòu)體允許將虛表引用操作重新格式化成以下形式:?

注意:

C++虛函數(shù)絕不會(huì)被直接引用,也絕不應(yīng)成為調(diào)用交叉引用的目標(biāo)。所有C++虛函數(shù)應(yīng)由至少一個(gè)虛表?xiàng)l目引用,并且始終是至少一個(gè)偏移量交叉引用的目標(biāo)。

我們隨便找到 vf1函數(shù)定義,然后點(diǎn)擊它的交叉引用:?

從而跳轉(zhuǎn)到虛表,其顯示如下:

.rdata:004031B8 const Base::`vftable' dd offset __purecall ; DATA XREF: Base::Base(void)+A↑o
.rdata:004031BC ? ? ? ? ? ? ? ? dd offset Base::vf2(void)
.rdata:004031C0 ? ? ? ? ? ? ? ? dd offset Base::vf3(void)
.rdata:004031C4 ? ? ? ? ? ? ? ? dd offset Base::vf4(void)
.rdata:004031C8 ? ? ? ? ? ? ? ? dd offset const Sub::`RTTI Complete Object Locator'
.rdata:004031CC const Sub::`vftable' dd offset Sub::vf1(void)
.rdata:004031CC ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; DATA XREF: Sub::Sub(void)+12↑o
.rdata:004031D0 ? ? ? ? ? ? ? ? dd offset Base::vf2(void)
.rdata:004031D4 ? ? ? ? ? ? ? ? dd offset Sub::vf3(void)
.rdata:004031D8 ? ? ? ? ? ? ? ? dd offset Base::vf4(void)
.rdata:004031DC ? ? ? ? ? ? ? ? dd offset Sub::vf5(void)

可以看到,類構(gòu)造函數(shù)Sub:: Sub(void)使用了虛表的地址Sub::Sub(void)+12↑o, 那是因?yàn)閚ew sub 調(diào)用了sub的隱式構(gòu)造函數(shù)?

windbg觀察:?

注意,Base的虛表第一個(gè)是002816e4 Test!purecall,這時(shí)因?yàn)樵贐ase中,沒(méi)有針對(duì)純虛函數(shù)vf1的實(shí)現(xiàn),所以在Base的虛表中并沒(méi)有存儲(chǔ)vf1的地址,這時(shí),編譯器會(huì)插入一個(gè)錯(cuò)誤處理函數(shù)的地址,通常,該函數(shù)名為purecall,一旦它被調(diào)用,程序就會(huì)被終止

附?
可以觀察到:

1.new指針不為空,才會(huì)調(diào)用構(gòu)造函數(shù),這是由Visual C++的內(nèi)部機(jī)制來(lái)保證的?
2.函數(shù)的虛表位置一般都可以在構(gòu)造函數(shù)中找到(很明顯,this指針指向的地址就是虛表的位置)

?

?

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的12.IDA-虚函数和虚表(vf代表虚函数,vf3代表this指向第三个函数)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。