24

I gave a talk at Recon in 2011 ("Practical C++ Decompilation") on this exact topic. Slides and video (mirror) are available. The basic approach is simple: represent classes as structures, and vtables as structures of function pointers. There are some tricks I described that allow you to handle inheritance and different vtables for the classes in the same ...


9

The easiest way to find out the function in question would probably be by dynamic analysis. You can easily do this by placing a breakpoint on that instruction in a debugger and examining the registers. A more general solution would probably involve some scripting to record all calls and add that information to the IDA database. Funcap plugin does something ...


7

According to documentation the first one is base object destructor and the second one is deleting destructor. Constructors and destructors are simply special cases of <unqualified-name>, where the final <unqualified-name> of a nested name is replaced by one of the following: <ctor-dtor-name> ::= C1 # complete object constructor ...


6

As far as I know, everything you've said is 100% correct. I've experienced the same issues. In fact, I was working on this exact problem in the background when a friend sent me a link to this post. There are actually three related issues here. First, prior to IDA 7.2, IDA's type system did not have a concept of a virtual function table per se. Meaning, ...


5

These are object virtual table entries used to implement multiple inheritance. The short story is, the sub instruction is to do with offsetting the correct derived class object size to the virtual table; but the following (long) article does a much better job of explaining than I could fit here : http://thomas-sanchez.net/computer-sciences/2011/08/15/what-...


5

I can think of 2 cases where a VMT is not in the first word of an object: using multiple inheritance when the an object has a member variable which has virtual methods multiple inheritance struct base1 { uint32_t x[12]; virtual void m1() { } }; struct base2 { virtual void m2() { } }; struct cls : base1, base2 { }; now the VMT of base2 is at ...


3

You can use Alt-K shortcut to fix the stack pointer. Its documentation is here.


2

Why do you think these values are "odd"? Odd in the sense of "strange", or "not divisible by 2"? The values in the vmt are pointers to the functions (or methods, thus vmt vs. vft) of the class object. These seem quite ok, because the vmt's address 0x611f77f8 is slightly above the methods 60986309, 60986325. As the compiler compiles all class methods first, ...


2

Two possibilities come to mind: These are slots for pure virtual methods. In many implementations the compiler provides something like __purecall or __cxa_pure_virtual to catch accidental calls, but since they are not supposed to happen anyway, a NULL works just as well on resource-constrained platforms. Itanium C++ ABI reserves two slots preceding the ...


2

HexRays doesn't call it because it doesn't know what is the value of g_lpDDSBack->QueryInterface in the common case. Generally speaking you can define a structure as a QueryInterface type, where members of this structure are named according to the related function names and than you'll see the call as g_lpDDSBack->QueryInterface->BltFast .


1

I've used IDA for this, it has ability to load VTBL structures and apply them to the assembler code. So, I could see "call [IDirect3DSurface9.LockRect]" instead of "call dword ptr [edx + 0x64]"


1

If I understand correctly, you already have the definition of your interface, so you can just create a structure with all fields having the names of the functions (or maybe even import it if your header file is simple enough), and then define the type of your variable to this structure (Edit->Set Type, or 'Y'). That way, the "v1+4" will appears as "...


1

The code to detect and print virtual function table pointers is: int isIdentifier(const char* s) { // true if points to [0-9a-zA-Z_]*\x00 if(!isValidPtr(s,0x10)) { return 0; } if(!s[0]) { return 0; } int i; for (i=0; s[i] && i<512; i++) { if( i/0x10 && i%0x10 == 0 && !isValidPtr(s,0x10)) { return 0; } ...


1

As to the 0 in the beginning of VFT, it must be the offset to top as described in http://mentorembedded.github.io/cxx-abi/abi.html#vtable-components . The value is used when a class is derived from several base classes. This 0 is vmt[-2] when you obtain the vmt address at run-time, but in the IDA disassembly it is the very first element of vtable. ; ...


Only top voted, non community-wiki answers of a minimum length are eligible