Search code examples
c++reverse-engineeringida

Figuring out the memory layout of objects without debugging a running program?


I'm working on reverse engineering a program. I'm using IDA Pro and the Hex-Rays Decompiler. I'm coming up against chunks of code where I know there is an object and there is a method call on the object but it's shown in a way I'm not able to figure out. For example:

 if ( (*(*interfacePtr + 24))(interfacePtr, &v23) >= 0 )

I know here that interfacePtr is pointing to a ICLRRuntimeHost object. (C++, .NET CLR runtime) However.... I have no idea what is at *(*interfacePtr + 24). I can tell it's a method but how do I figure out what is sitting at +24?


Solution

  • The vtable of a class is just a list of pointers to functions. It contains one pointer for each virtual function, in the order: very, very top base class, next base class, subclass of that, . . . most derived class.

    Example:

    struct A {
        virtual ~A() {}
        virtual void foo() = 0;
    }
    struct B : public A {
        virtual void foo() { // do something }
        virtual void bar() { // do something else }
    }
    

    The vtable for B would contain, in this order:

    • ~A
    • foo
    • bar

    (The ones for A have to come first, so that the same vtable can be used by parts of the code that have a pointer of type A to this object; that code doesn't know that the underlying object is really B.)

    If you're looking at 32-bit source, pointers are 4 bytes, so 24 = 4 * 6, you're looking at the 7th virtual function (index starts at 0). If you're on 64-bit, pointers are 8 bytes, so 24 = 8 * 3, and you're looking for the 4th. Actually, I haven't used the IDA "convert to C++" functionality, so maybe 24 is actually the 24th entry in the table.

    Easy way to confirm: write your own program. Declare a variable of type ICLRRuntimeHost. Call the function you suspect (based on looking at the header file and counting to 7 or 4, depending on bitness, or 24, if I misunderstood your example). Look at the generated assembly code, and confirm whether your index is right. (I'm always off by one on that kind of thing, so this will provide a check.)