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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

12.IDA-虚函数和虚表

發布時間:2024/4/11 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 12.IDA-虚函数和虚表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

vtable

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

__vfptr

每個包含虛函數的類對象都獲得__vfptr指針,并且是對象的第一個數據成員

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

在計算對象的總大小時,也必須考慮到虛表指針。比如new,傳遞給new的大小值不僅包括類(以及任何超類)中的所有顯式聲明的字段占用的空間,而且包括虛表指針所需的任何空間?
示例代碼:

class Base { public: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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

IDA分析如下:?

值得注意的是,虛表索引操作非常類似于結構體引用操作。實際上,它們之間并無區別?
。因此,我們可以定義一個結構體來表示一個類的虛表的布局,然后利用這個已定義的結構體來提高反匯編代碼清單的可讀性?
?
這個結構體允許將虛表引用操作重新格式化成以下形式:?
?
注意:

C++虛函數絕不會被直接引用,也絕不應成為調用交叉引用的目標。所有C++虛函數應由至少一個虛表條目引用,并且始終是至少一個偏移量交叉引用的目標。

我們隨便找到 vf1函數定義,然后點擊它的交叉引用:?
?
從而跳轉到虛表,其顯示如下:

.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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以看到,類構造函數Sub:: Sub(void)使用了虛表的地址Sub::Sub(void)+12↑o, 那是因為new sub 調用了sub的隱式構造函數?

windbg觀察:?


注意,Base的虛表第一個是002816e4 Test!purecall,這時因為在Base中,沒有針對純虛函數vf1的實現,所以在Base的虛表中并沒有存儲vf1的地址,這時,編譯器會插入一個錯誤處理函數的地址,通常,該函數名為purecall,一旦它被調用,程序就會被終止

附?
可以觀察到:

1.new指針不為空,才會調用構造函數,這是由Visual C++的內部機制來保證的?
2.函數的虛表位置一般都可以在構造函數中找到(很明顯,this指針指向的地址就是虛表的位置)

總結

以上是生活随笔為你收集整理的12.IDA-虚函数和虚表的全部內容,希望文章能夠幫你解決所遇到的問題。

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