Welcome to hackvshack.net Forum!
Download Free HvH CS2/CS:GO Cheats, CFG, LUA/JS Scripts, and More!
Register

Miscellaneous Core Logic Beginner Source Engine Getting VFTs from RTTI with only classnames

  • Thread starter Thread starter franz
  • Start date Start date

franz

Dilly-dallying Enthusiast
User ID:
138768
Messages:
3
Reactions:
27
Badges:
4
REP:
−0/0+
Level:
53
A while ago I stumbled upon an uc thread while I was working on a Half-Life 2 trainer, browsing for clues how virtual function tables work. I had a basic understanding of them before, but wanted to dive a bit deeper. I found Hinnie's thread from ~2020ish iirc, about a RTTI Virtual Function Table scanner.

And honestly, getting a VFT like this looks very nice:
Expand Collapse Copy
const auto cmodelrender_vftable = utils::get_vftable( "engine.dll", "CModelRender" );


0a52b36a-0078-4254-a694-464705c0c425

Figure 1. A long long time ago.


Since I was keen to try and figure it out myself, the only thing I took from Hinnie's thread was how RTTI mangles the classnames.

f537bf11-e371-4da7-b8d2-c16ec25936d6

Figure 2. This helped (from ).


Also, I recommend you check out reading links before continuing with the post, and have them open in parallel afterwards.

They will give you a quick understanding of what we're doing here.

So, let's start.

When we search for a classname in the strings of a module (when the class vft exists), we can find this.

8718f384-5f61-4b25-bb24-382d2c30e61d

Figure 3. Searching for `CEngineClient`.


RTTI stores a funny string in the format of ".?AV{classname}@@".
(Since it's a string, we can search for it in the module but that will come in handy later)

What if we follow the string in IDA?

3650b0e4-0f2a-4390-bd23-e91b71ab30f4

Figure 4. Following the mangled classname string.


We find the class's type_info object. From the ROP blog, we can recall that the Complete Object Locator stores a pointer to the type descriptor.

72af1523-674f-4d65-b57f-969e983a2c5d

Figure 5. COL Structure.


Now let's try to find the COL of CEngineClient in IDA. We can do this by searching for xrefs for the typeinfo object. We can find this.

5f85667c-6d4a-4e82-91eb-4699390d7b43

Figure 6. CEngineClient COL.


So, what can we note? COL starts off with a signature (ROL blog mentions this), then follows up with a offset in class, an offset to base class, a pointer to type info. So something like this.

COL Structure:
Expand Collapse Copy
00 00 00 00   - signature
?? ?? ?? ??   - offset
?? ?? ?? ??   - offset to base class, if inherited
Dd Cc Bb Aa   - ptr to type info (le)

If we find the COL, we can find the vftable, since the vftable starts with a reference to the COL, pretty simple :).

d7ad1780-bbd4-4469-b03f-d79321d2e385

Figure 7. In action.


e466a197-1039-46c5-bdee-6f5fad24e198

Figure 8. Offset in IDA.


And do they match? Yes! (check for the "col ref" log line, offset).

I hope this helps, frank out.



Oh also, a question for the reader

What if there are multiple COLs matching the pattern? (it is possible)
Look at the COL structure to see what differs on multiple matches.
 
A while ago I stumbled upon an uc thread while I was working on a Half-Life 2 trainer, browsing for clues how virtual function tables work. I had a basic understanding of them before, but wanted to dive a bit deeper. I found Hinnie's thread from ~2020ish iirc, about a RTTI Virtual Function Table scanner.

And honestly, getting a VFT like this looks very nice:
Expand Collapse Copy
const auto cmodelrender_vftable = utils::get_vftable( "engine.dll", "CModelRender" );


0a52b36a-0078-4254-a694-464705c0c425

Figure 1. A long long time ago.


Since I was keen to try and figure it out myself, the only thing I took from Hinnie's thread was how RTTI mangles the classnames.

f537bf11-e371-4da7-b8d2-c16ec25936d6

Figure 2. This helped (from ).


Also, I recommend you check out reading links before continuing with the post, and have them open in parallel afterwards.

They will give you a quick understanding of what we're doing here.

So, let's start.

When we search for a classname in the strings of a module (when the class vft exists), we can find this.

8718f384-5f61-4b25-bb24-382d2c30e61d

Figure 3. Searching for `CEngineClient`.


RTTI stores a funny string in the format of ".?AV{classname}@@".
(Since it's a string, we can search for it in the module but that will come in handy later)

What if we follow the string in IDA?

3650b0e4-0f2a-4390-bd23-e91b71ab30f4

Figure 4. Following the mangled classname string.


We find the class's type_info object. From the ROP blog, we can recall that the Complete Object Locator stores a pointer to the type descriptor.

72af1523-674f-4d65-b57f-969e983a2c5d

Figure 5. COL Structure.


Now let's try to find the COL of CEngineClient in IDA. We can do this by searching for xrefs for the typeinfo object. We can find this.

5f85667c-6d4a-4e82-91eb-4699390d7b43

Figure 6. CEngineClient COL.


So, what can we note? COL starts off with a signature (ROL blog mentions this), then follows up with a offset in class, an offset to base class, a pointer to type info. So something like this.

COL Structure:
Expand Collapse Copy
00 00 00 00   - signature
?? ?? ?? ??   - offset
?? ?? ?? ??   - offset to base class, if inherited
Dd Cc Bb Aa   - ptr to type info (le)

If we find the COL, we can find the vftable, since the vftable starts with a reference to the COL, pretty simple :).

d7ad1780-bbd4-4469-b03f-d79321d2e385

Figure 7. In action.


e466a197-1039-46c5-bdee-6f5fad24e198

Figure 8. Offset in IDA.


And do they match? Yes! (check for the "col ref" log line, offset).

I hope this helps, frank out.



Oh also, a question for the reader

What if there are multiple COLs matching the pattern? (it is possible)
Look at the COL structure to see what differs on multiple matches.
best dev on the scene smart boi
 

Who has read this thread (Total: 0) in last 1 hours View details