2013-05-15 60 views
1

我正在使用IDA Pro 6.3對Win32.dll進行靜態分析,並使用Hex-Rays反編譯器與IDA反彙編程序一起使用。我想了解這條線是幹什麼的。被反編譯__thiscall表達式指向函數的指針?

v4 = (*(int (__thiscall **)(int, int))(*(_DWORD *)dword_10087418 + 4))(dword_10087418, v11); 

它被格式化爲函數調用。這是在子例程調用中使用指向函數的指針時反編譯的代碼的樣子嗎?

謝謝。

+0

哇..我認爲這是我避免C-Style塑造如此之多的原因之一.. – Brandon

回答

0

這是將地址* dword_10087418 + 4轉換爲函數並調用它。

所以它將dword_10087418轉換爲dword指針,然後解引用它,然後將4添加到該結果中。得到的地址被轉換爲它的聲明如下功能:

int __thiscall foo(int, int) 

int (__thiscall **)(int, int)使得雙指針與__thiscall調用約定採用兩個整數參數的函數。然後圍繞所有的將*()解引用到一個單一的函數指針。所以最後你要把一些結果地址轉換成一個函數指針。

dword_10087418和v11是傳遞給此函數的整數。函數調用的結果保存在v4中。 C代碼是這樣的:

int v4 = foo(dword_10087418, v11); 
1

這很可能是C++,不是純C.這正是VISUAL C++ - 生成的虛擬方法調用的樣子。我會這樣說:

  • dword_10087418是一個指向對象的指針。它可以是全局變量或靜態變量,不是本地變量。
  • 該對象有一個虛擬方法表,並且該代碼正在調用該表中的第二個函數。
  • 假設Hex-Rays已正確識別函數參數,被調用的函數將採用一個32位參數。返回類型不明確。
  • C++調用很可能非常簡單,類似於SomeClass::Instance->func(arg)

如果你不熟悉C++對象佈局,你應該閱讀C++ Under the HoodReversing: Secrets of Reverse EngineeringInside the C++ Object Model。 IDA Pro Book也有一個關於這個主題的簡短部分。


如果你想要一個簡短的總結,請繼續閱讀。請記住,所有這些都是MSVC的實現細節,其他編譯器會以不同的方式執行,並且可以隨意更改它們。 (另外,我通過不提及虛擬/多重繼承來簡化事物)。當一個類使用虛函數時,編譯器會在該類中構建一個包含所有這些函數的表,並將該表的指針作爲該類的每個對象的第一個隱藏成員。然後,從表中調用虛函數是簡單的:

mov ecx, esi ; pretend that esi contains a pointer 
       ; to the object whose method is being called 
       ; also known as "this" 
       ; __thiscall functions expect to find this pointer in ecx 
       ; and all later arguments on the stack 
mov edx, [ecx] ; get the vtable address 
push edi  ; set up some integer-sized argument 
call [edx + 4] ; call the second function in the vtable 

這基本上就是該行代碼是這樣做的:

(*(int (__thiscall **)(int, int))(*(_DWORD *)dword_10087418 + 4))(dword_10087418, v11) 
            ^-----------------------^ 
            dereference pointer to get the address of the vtable 
            (it's the first piece of data in the object) 
           ^-----------------------------^ 
           add 4 bytes to get address of the second function 
^------------------------------------------------------------------------------------^ 
cast that pointer to a particular function pointer and call it 
(cast is invisible in assembler code, so it's just a call) 

注意,由於成員函數需要訪問this ,編譯器也必須通過它。這是C++中不可見的細節,但this被視爲函數的附加參數 - 因此您會看到兩個參數,但該函數只需要一個參數(MSVC的thiscall約定命令this指針在ecx中傳遞)。國際開發協會並不打算隱藏那個指針,因爲這會讓人困惑。


更多建議:獲取ms_rtti腳本IDA並運行它來查找DLL中的虛方法表,然後搜索其它引用dword_10087418,看看有什麼值寫入它 - 你應該能夠確定哪個vtable與該對象相關聯,然後確定哪個函數正在被調用。

如果爲類和所討論的vtable定義存根結構類型,那麼可以使Hex-Rays以更易讀的方式顯示代碼,然後告訴IDA指針使用該結構類型。