Hot answers tagged

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

If the binary itself has RTTI info compiled in it then you can get at least the names for the vftables, and to some degree a class/struct hierarchy. For Windows x86 you can use my IDA plug-in "Class Informer". Also see for reference Reversing Microsoft Visual C++ Part II: Classes, Methods and RTTI by igorsk. Otherwise AFAIK (and know the area well) I doubt ...


8

If it is ARM architecture that may use THUMB encoding it can be result of the following issue: If I remember correctly, calls to the virtual functions can be executed with assembly command similar to BLX as indirect jump, which allows switching between ARM and THUMB encoding. In this case this + 1 means that the target of the jump is encoded in THUMB. See ...


8

This is compiler dependent - the compiler may place the vtable wherever it wants to, as long as it does it consistently. However, in most cases, the vtable pointer is the first element (at offset 0) of the generated structure. class test { int a; int b; test() { ...; } ~test() { ...; } void somefunc() { ...; } int c; ...


7

Note that not every C++ compiler neccesarily uses a vtable pointer at all. For example, the Watcom C++ compiler, 20 years ago, implemented method calls by reserving a function pointer for each method within the object itself; the new operator initialized each of these function pointers separately, every time it generated a new object. The very idea of the ...


6

There is a great IDA plugin called HexRaysCodeXplorer that does automatic type reconstruction for C++ objects . It should do what you need.


4

In the next version, 6.5, it should be as easy as selecting the corresponding VTable area, right click and selecting the menu option "Create struct from data" (leak from IDA Beta testing). In the meantime, you can use this IDAPython script I use myself. I hope you'll find it helpful.


4

You're correctly interpreting C++'s way of implementing class inheritance, however your assumption that the "subobject" is a member object of the class may be incorrect. Through compiled code alone, It is impossible to completely distinguish member objects from additional inheritance in multiple inheritance classes as both appear the same. As a matter of ...


3

Could it be multiple inheritance? That could explain why the vptr of the supposed subobject is overwritten by ctor_2 without having to assume the compiler to inline anything. The derived class might actually have two base classes, the "base" and the "subobject". If this is the case, it kinda makes sense why the compiler would make ctor_3 to change the vptr ...


3

You are absolutely on the right track But, A* a = new A(); ... a->doThing() Is not going to bother with the vtable at all. Because a can only be of A type. MSVC will still create the vftable, but in that context a->doThing() will just become A::doThing() Here, I fixed up your example into my own to demonstrate that you were correct, you just ...


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 .


2

In General, with modern operating systems, the order won't depend on the compiler, but it may depend on the operating system. Any modern operating system does not just define the operating system API, but also, lots of standard libraries that make it easier for programs to access that API. Also, there's a lot of libraries that offer services that don't ...


2

You could try the following heuristic: extend the vtable from its given base address until you reach an address that has already been classified as something else (e.g. the COL pointer of the next vtable) or you find something that is not the address of a known function in a known code segment. This analysis step should be deferred until after the full web ...


2

The order of virtual functions is significant; altering the order in the source code will alter the order in the generated machine code. In your example, the two source samples will generate different machine code. Edit: using the sample code provided by @tathanhdinh below, MSVC generates the two vtables as follows: ; COMDAT ??_7B@@6B@ CONST SEGMENT ??...


2

I believe that it is possible for both the vtable pointer to point to a different module, and for functions pointers in the vtable to point to a different module (at least indirectly.) The first will happen if you have a base class (with at least 1 virtual method) exported from a DLL and a class deriving from this in an executable (which will import the ...


2

I'll start with a few minor corrections and clarifications, just to make sure we're using the right terms and exact definitions. I used Cheat engine to find the address of the variable i in A::doThing First of all, i is not a variable of method A::doThing. It is a member of the A class. Then I used the option to find what writes to that address Doing ...


2

What you're looking it is actually a VTable. As you know, a VTable is a table of function pointers and as you can see, at address 0x19B64 you actually see a single function address (this looks like dd offset sub_XXXX). That is actually a virtual function table of a size of one. Since you only have one virtual function in your demo class. That offset points ...


2

As I guessed and was confirmed in the comments, this is apparently some compiler optimization reusing methods executing the same logic. This got clear to me when I reversed the methods of one of the more specific objects, like the data stream reader / writer here: seg002:008F4FC4 const DataStream::`vftable' dd offset DataStream__readByte ; DATA XREF: ...


1

You have here multiple inheritance where both base classes have virtual destructors. The pattern you see in dtor_derived_so is a so-called "non-virtual thunk", which adjusts this before calling the whole class destructor. Normally you should also see 0xFFFFFFE0 (offset to base) in the second dword before the secondary vtables. I was able to produce code and ...


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