-
Notifications
You must be signed in to change notification settings - Fork 2
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
- Search GData in strings. If I get something that looks like
.?AV----@@
then I know that's part of the RTTI information
- 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 for00be8988
- 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.
- So this data looks like a match.
- If I go to an offset of
-0xc
I can set the type toRTTICompleteObjectLocator
and it indeed looks correct.
- With this, you can follow the pointer
pClassDescriptor
and set that address as typeRTTIClassHierarchyDescriptor
- Now, back at the
RTTICompleteObjectLocator
forGData
, you want to follow the xref to it. If there are none, do a memory search for the address.
- 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)
- Since we know that
GData
subclassesBase
, we can set the vtable as typeBaseVftable
. Any unnamed function is a new function that's unique to GData, in this case it's only the destructor.
- Now in the mac ppc version, I usually look in strings first because sometimes it doesn't find the function by name
- 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
- 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
- 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