Raised This Month: $ Target: $400
 0% 

VirtualTable pointer


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
kadet.89
Veteran Member
Join Date: Nov 2012
Location: Serbia
Old 05-27-2015 , 13:21   VirtualTable pointer
Reply With Quote #1

I'm trying to implement a global hook for TakeDamage:
https://wiki.alliedmods.net/SourceHook_Development

And I can't understand what is player_vtable?
I have the address of this function and the offset. What shall I pass to the SH_ADD_MANUALDVPHOOK macro ?
kadet.89 is offline
Send a message via Skype™ to kadet.89
donrevan
AlliedModders Donor
Join Date: Jul 2010
Old 05-27-2015 , 15:58   Re: VirtualTable pointer
Reply With Quote #2

You've 2 options as explained in the wiki:
Quote:
With this understanding in place, there are two separate syntaxes - one for simple hooks and one for manual hooks. Additionally, there are two ways of declaring the virtual interface to use:
  • An instance of the class can be passed. (SH_ADD_VPHOOK)
  • The direct address to the virtual table can be passed. (SH_ADD_DVPHOOK)
They are essentially equivalent, although one may be more advantageous than the other (for example, if no instances are known, but the vtable address can be extracted via pattern searching).
a) look for the vtable in the executable(that big table with all the virtual functions), sigscan references to it
--> use SH_ADD_DVPHOOK

b) get vtable from object
-> just use SH_ADD_VPHOOK on the object
-> code for reference(should work for msvc; not sure about gcc):
Code:
void *pObject = ...;
void *pVTable = *reinterpret_cast<void**>(pObject);
manual hooks should be straightforward..

Last edited by donrevan; 05-27-2015 at 16:07.
donrevan is offline
kadet.89
Veteran Member
Join Date: Nov 2012
Location: Serbia
Old 05-28-2015 , 12:06   Re: VirtualTable pointer
Reply With Quote #3

I don't quite understand what you mean.
There are a lot of vtables in the server_srv.so
If I pass a reference (008CC960) to `vtable for'CCSPlayer, for which I want to hook this function, how then the extension will find out which function it should hook from this table?
Is there a workable example with SH_ADD_DVPHOOK? I can't find any in the sourcemod sdk
Attached Thumbnails
Click image for larger version

Name:	??? ?????-2.png
Views:	253
Size:	76.0 KB
ID:	145329  

Last edited by kadet.89; 05-28-2015 at 12:07.
kadet.89 is offline
Send a message via Skype™ to kadet.89
donrevan
AlliedModders Donor
Join Date: Jul 2010
Old 05-28-2015 , 14:13   Re: VirtualTable pointer
Reply With Quote #4

I've never used a global hook but according to the wiki you just need to pass the vtable pointer to SH_ADD_DVPHOOK(same applies for a manual dvphook) ...

Code:
SH_ADD_DVPHOOK(Interface, Function, VirtualTable, Handler, Post)

The vtable for CCSPlayer is, as you pointed out, at
008CC960(+8).. the problem is that the binary where the vtable is located will (probably) be rebased to a different address next time you start the server thus 008CC960 will be no longer valid. What to do? sigscan references it!

Example of a (bad) sig for CCSPlayer's vtable for csgo server.so(check attached pic):
Code:
2C 8B 5D 08 8B B3 ? ? ? ? C7 03
Offset: 12
pseudocode(using manual hooks):
PHP Code:
SH_DECL_MANUALHOOK1_void(MHook_TakeDamage, ....);
//---------------
SH_MANUALHOOK_RECONFIGURE with the correct offset to the func you want to hook BEFORE SH_ADDing it
//---------------
pGameConf->GetMemSig("CCSPlayerVTable"vtable);
pGameConf->GetOffset("CCSPlayerVTableOffs"offsToVTable);

vtable = *reinterpret_cast<void**>(vtable offsToVTable);

SH_ADD_MANUALDVPHOOK(MHook_TakeDamagevtableSH_STATIC(Hook_TakeDamage), false); 
EDIT:
Instead of using a byte signature on linux(wtf) you should use symbols
Attached Thumbnails
Click image for larger version

Name:	dvphk.png
Views:	279
Size:	20.3 KB
ID:	145340  

Last edited by donrevan; 05-28-2015 at 15:04.
donrevan is offline
psychonic

BAFFLED
Join Date: May 2008
Old 05-28-2015 , 15:11   Re: VirtualTable pointer
Reply With Quote #5

As mentioned a few posts above, it would be easier to use a vphook, rather than dvphook. You would only need a CCSPlayer instance, which you could get upon first player connect.
psychonic is offline
kadet.89
Veteran Member
Join Date: Nov 2012
Location: Serbia
Old 05-29-2015 , 11:16   Re: VirtualTable pointer
Reply With Quote #6

If I use vphook, than when I load my extension, it must find all the players and make hooks for each of them, and when I reload the extension, I have to do it to. When I unload my extension, will it unhook all the hooks automatically, or I will have to find somehow all the hooks and unhook them manually?

I've hooked SetModel, it works, but how can I replace the modelname param:

PHP Code:
SH_DECL_MANUALHOOK1_void(SetModelHook000, const char *);

char *modelname "models/player/ct_gsg9.mdl";
void STools::SetModel( const char *pModelName ) {
    
    
g_pSM->LogMessage(myself"SetModel%s"pModelName);
    
RETURN_META_MNEWPARAMS(MRES_SUPERCEDESetModelHook, (modelname)); //Doesn't work
}


SH_ADD_MANUALHOOK_MEMFUNC(SetModelHookEnt, &g_interface, &STools::SetModeltrue); 
SH_MANUALHOOK_RECONFIGURE(SetModelHookOffset00); 

Last edited by kadet.89; 05-29-2015 at 11:17.
kadet.89 is offline
Send a message via Skype™ to kadet.89
donrevan
AlliedModders Donor
Join Date: Jul 2010
Old 05-29-2015 , 11:47   Re: VirtualTable pointer
Reply With Quote #7

1. Implement IClientListener
PHP Code:
virtual void OnClientPutInServer(int client);
virtual void OnClientDisconnecting(int client); 
2. Add your extension as a IClientListener:
PHP Code:
playerhelpers->AddClientListener(&g_interface); 
3. Reconfigure manual hook to correct offset
4. When a player connects for the first time -> create hook
PHP Code:
void Sample::SetModelHook(const char *model)
{
   
g_pSM->LogMessage(..);
   
RETURN_META_MNEWPARAMS(..);
}

void Sample::OnClientPutInServer(int client)
{
   if(
g_bIsHooked)
     return; 
// return if already hooked

   
CBaseEntity *pEntity gamehelpers->ReferenceToEntity(client);
   
int hook_id SH_ADD_MANUALVPHOOK(SetModelHookpEntitySH_MEMBER(&g_interface, &Sample::SetModelHook), false); //remember hook_id to remove it later
   
g_bIsHooked true;

You only need to unhook on extension unload via SH_REMOVE_HOOK_ID
sdkhooks is using vphooks if you need a working example.

Last edited by donrevan; 05-30-2015 at 10:11. Reason: only hook once
donrevan is offline
kadet.89
Veteran Member
Join Date: Nov 2012
Location: Serbia
Old 05-29-2015 , 12:15   Re: VirtualTable pointer
Reply With Quote #8

Thanks for the explanation.
What shall I use instead of RETURN_META_MNEWPARAMS to replace the modelname value?

Last edited by kadet.89; 05-29-2015 at 12:24.
kadet.89 is offline
Send a message via Skype™ to kadet.89
donrevan
AlliedModders Donor
Join Date: Jul 2010
Old 05-29-2015 , 12:51   Re: VirtualTable pointer
Reply With Quote #9

RETURN_META_MNEWPARAMS should work just make sure you use a prehook.
donrevan is offline
psychonic

BAFFLED
Join Date: May 2008
Old 05-29-2015 , 14:01   Re: VirtualTable pointer
Reply With Quote #10

Quote:
Originally Posted by kadet.89 View Post
If I use vphook, than when I load my extension, it must find all the players and make hooks for each of them
No, the whole point of a (d)vp hook is that the hook fires for any instance. There is only one CCSPlayer vtable shared by all of the players. You only need to hook the vtable once, and can just do it for the first player that you see or that connects.
psychonic is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 05:45.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode