Raised This Month: $ Target: $400
 0% 

Getting@funcs without sigs, offsets, dummy funcs or sdk .h's


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
robot
Junior Member
Join Date: Oct 2005
Old 01-13-2006 , 04:50   Getting@funcs without sigs, offsets, dummy funcs or sdk .h's
Reply With Quote #1

This is what I am using at the moment...It is linux only as I got frightened by how much work I would have to do scanning for sigs in pe's D: This method is signature free, as it seemed unnecessary for a linux only implementation. I've already taken a lot of abuse for this being linux only, so need need to tell me again!

To find the functions, I take several steps, firstly:

1) Identify the function and it's context within the Source SDK. Check the proto etc.
2) Find the symbols in the server object file. For example, CBE Teleport:

Code:
[robot@medic bin]$ cd  ~/srcds_l/cstrike/bin/
[robot@medic bin]$ nm -n server_i486.so | c++filt | grep CBaseEntity::Teleport
00616f80 T CBaseEntity::Teleport(Vector const*, QAngle const*, Vector const*)
3) Now the mangled name:

Code:
[robot@medic bin]$ nm -n server_i486.so | grep 00616f80
00616f80 T _ZN11CBaseEntity8TeleportEPK6VectorPK6QAngleS2_
4) In the plugin code, declare the prototype:

Code:
#define VFUNC

#define HDEFVFUNC( funcname , returntype , proto ) \
	typedef returntype ( VFUNC * funcname##_Function ) proto ; \
	extern funcname##_Function funcname ;

#define DEFVFUNC( funcname , returntype , proto ) \
	funcname##_Function funcname = NULL;

#define DEFVFUNC_( funcname , returntype , proto ) \
	HDEFVFUNC(funcname, returntype, proto); \
	DEFVFUNC(funcname, returntype, proto)

// forward decl
class CBaseEntity;
class CBasePlayer;
class CBaseAnimating;

DEFVFUNC_(Teleport, void, (CBaseEntity *, Vector *, QAngle *, Vector *)); 
DEFVFUNC_(Ignite, void, (CBaseEntity *, float, bool));
DEFVFUNC_(SetModel, void, (CBaseAnimating *, char const *));
DEFVFUNC_(CommitSuicide, void, (CBasePlayer *));
5) Get the function pointer from the symbol table and assign the function:

Code:
#define LINKVFUNC( symbol, func ) \
	sym_addr = dlsym(handle, symbol); \
	if (sym_addr == NULL) Msg("dlsym failure : Error [%s]\n", dlerror()); \
	else func = (func##_Function) sym_addr;


	void *handle;
	void *sym_addr;

	handle = dlopen("./cstrike/bin/server_i486.so", RTLD_NOW);
   
	if (handle == NULL)
	{
		Msg("Failed to open server image, error [%s]\n", dlerror());
	}
	else
	{
		Msg("server_i486.so = [%p]\n", handle);
		
		// virtual functions
		LINKVFUNC( "_ZN11CBaseEntity8TeleportEPK6VectorPK6QAngleS2_", Teleport )
		LINKVFUNC( "_ZN14CBaseAnimating6IgniteEfbfb", Ignite )
		LINKVFUNC( "_ZN14CBaseAnimating8SetModelEPKc", SetModel )
		LINKVFUNC( "_ZN11CBasePlayer13CommitSuicideEv", CommitSuicide )
		
		Msg( "linked vfuncs...\n" );	
			
		dlclose(handle);
6) Then call the functions to your hearts content i.e.

Code:
void CZHPlugin::Burninate(CPluginPlayer *player, float flTime)
{
    Ignite(player->GetBaseEnt(), flTime, false);
}
I do wonder if these are safer for linux, since they only rely on the return types and parameters being the same (highly likely)?? It is also trivial to get at the vtables and iterate through it, comparing your function pointers from the symbol table to the the addresses in the vtable for a particular class. This gives you a way to dynamically scan for vtable indexes, which makes for easier hooking ie

1) Get the unmangled symbol:

Code:
[robot@medic bin]$ nm -n server_i486.so | c++filt | grep CBaseEntity | grep vtable
....blah
....blah
00988520 V vtable for CBaseEntity   <-- we are interested in this one!
....
....
....
2) Now the mangled name:

Code:
[robot@medic bin]$ nm -n server_i486.so | grep 00988520
00988520 V _ZTV11CBaseEntity
3) Getting vtables symbol names like that allows you to get indexes for stuff...

Code:
<--snip-->
// virtual tables
void *vtblCBaseEntity = NULL;
void *vtblCBaseCombatCharacter = NULL;
void *vtblCCSPlayer = NULL;

// virtual function table indice
unsigned long idxTraceAttack = NULL;
unsigned long idxEvent_Killed = NULL;
unsigned long idxWeapon_Switch = NULL;
<--snip-->

<--snip-->
#define ADDRTYPE unsigned long

#define LINKVTABLE( symbol, table ) \
	table = dlsym(handle, symbol); \
	if (table == NULL) Msg("dlsym failure : Error [%s]\n", dlerror());

#define SCANVFUNC( index, table, func ) \
	for ( index = 0; index < 256; index++) { \
  		void * vfnaddr = *((ADDRTYPE *)table + index); \
  		if (vfnaddr == func) { \
  			index -= 2; \
  			Msg("ZH: Got Index %d | table %p | func %p\n", index, table, func); \
  			break; } }
<--snip-->

<--snip-->
		// virtual function tables
		LINKVTABLE( "_ZTV11CBaseEntity", vtblCBaseEntity )
		LINKVTABLE( "_ZTV20CBaseCombatCharacter", vtblCBaseCombatCharacter )		
		LINKVTABLE( "_ZTV9CCSPlayer", vtblCCSPlayer )

	  	SCANVFUNC( idxTraceAttack, vtblCCSPlayer, TraceAttack )
	  	SCANVFUNC( idxEvent_Killed, vtblCBaseCombatCharacter, Event_Killed )
	  	SCANVFUNC( idxWeapon_Switch, vtblCBaseCombatCharacter, Weapon_Switch )
<--snip-->
btw, i am working on moving my plugin over to source:mm so sorry if some of this is irrelevant code

Thanks vancelorgin, bailopan, xad and mani and co!

robot
robot is offline
BAILOPAN
Join Date: Jan 2004
Old 01-13-2006 , 05:38  
Reply With Quote #2

Most people do this for linux already instead of using signatures (except me).

I don't do this because the symbol table can be stripped.
__________________
egg
BAILOPAN is offline
SeLfkiLL
Member
Join Date: Nov 2005
Old 01-13-2006 , 16:57  
Reply With Quote #3

Nice job! I did not know you could do this under Linux.
SeLfkiLL is offline
Send a message via AIM to SeLfkiLL
c0ldfyr3
AlliedModders Donor
Join Date: Aug 2005
Location: Ireland
Old 01-21-2006 , 13:46  
Reply With Quote #4

This ONLY works for linux though, thats the catch.

FindAddress only gets exported functions on Win32.
__________________
c0ldfyr3 is offline
Send a message via MSN to c0ldfyr3 Send a message via Yahoo to c0ldfyr3
cybermind
Senior Member
Join Date: Oct 2004
Old 01-21-2006 , 15:05  
Reply With Quote #5

Quote:
Originally Posted by c0ldfyr3
This ONLY works for linux though, thats the catch.

FindAddress only gets exported functions on Win32.
Linux's dlsym only works on entries in the symbol table, but unlike Windows, every function is placed in the symbol table by default.
cybermind is offline
c0ldfyr3
AlliedModders Donor
Join Date: Aug 2005
Location: Ireland
Old 01-22-2006 , 11:03  
Reply With Quote #6

Unless they build with -s, then your screwed.

And IMO coming up with a solution to a problem on linux isnt a solution at all.
Windows is and always has been the thorn in our side so im waiting on the windows breakthroughs.
__________________
c0ldfyr3 is offline
Send a message via MSN to c0ldfyr3 Send a message via Yahoo to c0ldfyr3
robot
Junior Member
Join Date: Oct 2005
Old 01-25-2006 , 21:14  
Reply With Quote #7

coldfyre wrote:
Quote:
This ONLY works for linux though, thats the catch.
even though i had already stated...
Quote:
I've already taken a lot of abuse for this being linux only, so need need to tell me again!
yes i know! im just sharing code....
robot is offline
cybermind
Senior Member
Join Date: Oct 2004
Old 01-26-2006 , 00:54  
Reply With Quote #8

Quote:
Originally Posted by c0ldfyr3
Unless they build with -s, then your screwed.
Which would be a non-default setting.
cybermind is offline
c0ldfyr3
AlliedModders Donor
Join Date: Aug 2005
Location: Ireland
Old 01-26-2006 , 00:56  
Reply With Quote #9

Quote:
Originally Posted by CyberMind
Quote:
Originally Posted by c0ldfyr3
Unless they build with -s, then your screwed.
Which would be a non-default setting.
__________________
c0ldfyr3 is offline
Send a message via MSN to c0ldfyr3 Send a message via Yahoo to c0ldfyr3
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 07:33.


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