1. 程式人生 > >第四章——64位軟體逆向技術-基本語法(下 虛擬函式)

第四章——64位軟體逆向技術-基本語法(下 虛擬函式)

虛擬函式    VC++實現虛擬函式的方式就是虛表,如果一個類至少要有一個虛擬函式,編譯器會為這個類產生一個虛表。不同的類虛表就不同,相同的類虛表就會共享     識別構造和析構 如果在函式入口有 lea reg,off_xxxxxx,  mov [reg],reg 初始化虛表,且返回值為this指標,我們就可以懷疑這是一個建構函式,同理我們發現同樣的彙編我們也可以懷疑這是解構函式,可以根據順序來區分。     有一種情況,我們寫了一個虛解構函式,但是編譯器生成了兩個解構函式,其中一個是普通的解構函式,物件出作用於時候呼叫,另一個放到虛表中,在delete物件時候呼叫。對比兩個解構函式,虛表中的析構多了一個delete this 操作。如果程式碼寫成如下         Cvtual * Object = new Cvtual();         Object ->~Cvtual();         delete Object; 因為Object ->~Cvtual();屬於多型呼叫所以會直接呼叫虛表中的析構,這時候物件就被釋放了,如果在呼叫了delete Object,這時候我們發現,物件空間被重複釋放,出現問題。為了解決這個問題,VC++編譯器會在Object ->~Cvtual();時候傳遞引數0,代表物件不被釋放,delete Object傳遞引數1 物件會被釋放,這樣就解決了上面的問題。gcc的編譯器會採用在虛表中存放兩個解構函式地址   總結一下虛表的特點:
  • 如果一個類至少一個虛擬函式,這個類起碼有一個虛表指標
  • 不同的類虛表不同,相同類物件公用一個虛表
  • 虛表指標存放物件首地址處
  • 虛表地址在全域性資料區
  • 虛表的每個元素都指向一個類成員函式指標
  • 虛表不一定以0結尾
  • 虛表成員函式順序是以類宣告的順序排列
  • 虛表在建構函式中會被初始化
  • 虛表在解構函式中會被賦值