1

Assuming the standard VC++ vTable layout:

  Heap-Addr           TableAddr
+-----------+       +-----------+
| TableAddr | ----> | Funcion-1 | ----> Exec region of module
+-----------+       +-----------+
| a         |       | Funcion-2 | ----> Exec region of module
+-----------+       +-----------+
| b         |       | Funcion-3 | ----> Exec region of module
+-----------+       +-----------+
| c         |       |    ...    |
+-----------+       +-----------+

Is TableAddr guaranteed to always be inside a module or can it be anywhere in the address space, if so, what are the conditions that would make TableAddr be outside a module.

For clarity: A module is any .exe or .dll which has read-only or executable regions of memory allowing functions to be called. From my experience I've only seen TableAddr reside inside read-only sections of modules.

  • The import/export address mechanism of Windows is robust enough to allow this, but I think noone ever would bother to actually try it. Mainly because "why?". – usr2564301 Oct 11 '15 at 9:08
  • I'm not sure I understand your question. What do you mean by "outside of a module" ? If the executable is loaded, everything is inside of (some) module according to your definition. Did you mean "inside the same module" ? – w s Oct 11 '15 at 14:58
  • Well you could have regions of memory which don't correspond to any module such as the heap. I'm wondering if the compiler would generate vTable pointers to those regions as opposed to always being in a region which is part of a module. – Dave Oct 11 '15 at 15:23
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 vtable is to optimize this. At the time an object is generated, its exact class is known. The vtable allows the compiler to assign all those "function pointers" at once (by putting the address of the vtable in the object), at the cost of one more indirection every time a method is called. But anyway, the vtable for any class that may be instantiated is known at compile time*. Which means the vtable can be pre-initialized at compile time, which means it's bound to be put into some initialized data segment.

So for code that was generated by a current C++ compiler, you should be able to assume that all vtables reside in an initialized segment, not the heap or the stack.

However, if you're trying to write a decompiler, or a tool that automates dynamic analysis in some way, you should at least check for this condition. If i wanted to obfuscate my code, i could easily implement a function in assembly, that takes an input pointer to an object, generates a copy of that object's vtable, possibly modifies a vtable entry or two, and adjusts the vtable pointer to reference the copy. If you write an analysis tool that becomes well-known, this might even be a technique an obfuscator uses to specifically defeat your tool.

So while there shouldn't be a reason why vtables might be put anywhere but in initialized segments now, i wouldn't want to rely on this in a general case.

(*) I haven't used C++ for a long time, which means i haven't followed the newer specifications closely. I can't guarantee that C++11, or C++14, haven't introduced some weird construct that would need to construct vtables on the fly. But i'd be quite astonished if that was the case.

  • Thank you for your in-depth explanation. Luckily the tool I'm building is mainly for applications compiled with MSVC, which has remained consistent across many years. Knowing this property allows me to cache only the module memory rather than the entire address space of the application. But you're right, more robust obfuscation may change this in the future. – Dave Oct 12 '15 at 7:50
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 DLL.)

When a derived class object is constructed in the exe module, it will first be constructed as a base class object (by calling the base constructor in the DLL) and so the vtable pointer for the object will point into the DLL module. This will only be for a very short period of time as, soon after, the derived class constructor in the executable will update the object's vtable pointer to point to the derived class vtable which will be in the executable module.

The second can happen if the derived class doesn't override all the base class virtual methods. For these methods, the correct implementation will be the base class methods residing in the DLL. Hence, the relevent vtable entries will need to end up at the methods in the base class DLL. This will probably be via an import stub function in the executable itself.

  • You're right, I didn't even think of cross-module inheritance. This might be especially problematic if the software uses a lot of modules or plugins which can be swapped in and out. – Dave Oct 13 '15 at 6:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.