Skip to content

Finding Class virtual tables

Sandy edited this page Aug 25, 2024 · 1 revision

Example finding the virtual table for GData.

Needed:

  • a no-cd version of runblack.exe for x86
  • the Mac ppc version of Black__White
  • ghidra

Steps

  1. Search GData in strings. If I get something that looks like .?AV----@@ then I know that's part of the RTTI information

image

  1. From the base of the GData::RTTI_Type_Descriptor I want to fix xrefs to it. A lot of times the xrefs are already there. In this case, there are none found, so I do a memory search for 00be8988

image

  1. I go to both addresses and convert them to pointers What I'm looking for is data that looks like RTTICompleteObjectLocator. This pointer will be at the +0xc offset of it and will be followed by another pointer.

image

  1. So this data looks like a match.

image

  1. If I go to an offset of -0xc I can set the type to RTTICompleteObjectLocator and it indeed looks correct.

image

  1. With this, you can follow the pointer pClassDescriptor and set that address as type RTTIClassHierarchyDescriptor

image

  1. Now, back at the RTTICompleteObjectLocator for GData, you want to follow the xref to it. If there are none, do a memory search for the address.

image

  1. There will be a pointer to the RTTICompleteObjectLocator which is followed by a list of function addresses at +0x4. The list of is the virtual table for GData (__vt__5GData as it's called on mac)

image

  1. Since we know that GData subclasses Base, we can set the vtable as type BaseVftable. Any unnamed function is a new function that's unique to GData, in this case it's only the destructor.

image

  1. Now in the mac ppc version, I usually look in strings first because sometimes it doesn't find the function by name

image

  1. As you can see in this case, the debug info wasn't fully parsed and the function isn't defined but if you scroll up you can find it

image

  1. Once defined you can see it gets the right name. And you can compare with win x86 version. If you're satisfied that it's the same function, you can go and name the x86 version accordingly

image

  1. Another really important thing here is that the struct size is sometimes in the destructor.
.__dl__4BaseFPvUl(param_1,0x28);

There the size is 0x28. This is the size of GData. Note that sometimes it's different between x86 and ppc

Clone this wiki locally