Raised This Month: $12 Target: $400
 3% 

New Virtual function table hook - worlds better, linux compa


Post New Thread Closed Thread   
 
Thread Tools Display Modes
Ruckus
Junior Member
Join Date: Feb 2005
Old 03-28-2005 , 19:03  
#11

Quote:
Originally Posted by vancelorgin
You have to now either do HDEVFUNC and DEFVFUNC with the same params or DEFVFUNC_ - I made it this way so original functions may be exported to other source files (put HDEFVFUNC in a header and DEFVFUNC in *one* source file - the one with your function to be called in it). If you don't need to export it just add the _ on the end and it'll be equivilant to HDEFVFUNC and DEFVFUNC.

Long story short, add a _ to DEFVFUNC.
Didn't get a chance to try again until now but things are working great, thanks
Ruckus is offline
theqizmo
Member
Join Date: Oct 2004
Old 03-29-2005 , 02:38  
#12

Quote:
Originally Posted by Ruckus
Didn't get a chance to try again until now but things are working great, thanks
Elaborate.
theqizmo is offline
Send a message via ICQ to theqizmo Send a message via AIM to theqizmo Send a message via MSN to theqizmo
XAD
Senior Member
Join Date: Mar 2004
Location: Sweden
Old 04-19-2005 , 02:53  
#13

Well I just add a new version with the Linux code.
(Gizmo, do I recognize the malloc code? )

Lance, I assume you want to protect after the changes (so I changed in the windows section too).
_WIN32 and _LINUX are the defines Valve is using in their code (but for some reason Valve put WIN32 in the sample project file but not the rest).

Code:
/********************************************************************
Virtual function table hook mechanism
written by LanceVorgin aka stosw aka like 90 other names
ty to qizmo for helping and uni for owning me
oh and go play in traffic trimbo - real mature eh - I blame the drugs.
********************************************************************/

#ifndef _VFNHOOK_H
#define _VFNHOOK_H

/*
class someinterface {
public:
	virtual void somefunc(char* somearg) = 0;
};

class someclass : public someinterface {
public:
	void somefunc(char* somearg){
		printf("someclass::somefunc: %x %s\n", someval, somearg ? somearg : "NULL");
	}

	int someval;
};


DEFVFUNC(someclass_somefunc, (someclass* pa, char* somearg));

void VFUNC hookedsomefunc(someclass* pa, char* somearg){
	printf("hooked it:  %s\n", somearg ? somearg : "NULL");
	someclass_somefunc(pa, "lol owned");
	printf("leaving hook\n");
}

someclass q;
someclass w;

void main(){
	q.someval = 0xdeadbeef;
	w.someval = 0xc0defeed;

	HOOKVFUNC(&q, 0, someclass_somefunc, hookedsomefunc);
	
	dynamic_cast<someinterface*>(&q)->somefunc("testing"); //forces vtable lookup
	
	someclass_somefunc(&w, "should be codefeed yo");
}
*/

#define ADDRTYPE unsigned long

#define VTBL( classptr ) (*(ADDRTYPE*)classptr)
#define PVFN_( classptr , offset ) (VTBL( classptr ) + offset)
#define VFN_( classptr , offset ) *(ADDRTYPE*)PVFN_( classptr , offset )
#define PVFN( classptr , offset ) PVFN_( classptr , ( offset * sizeof(void*) ) )
#define VFN( classptr , offset ) VFN_( classptr , ( offset * sizeof(void*) ) )

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

#if defined _WIN32 || defined WIN32

	#define WIN32_LEAN_AND_MEAN
	#define WIN32_EXTRA_LEAN
	#include <windows.h>

	class CVirtualCallGate
	{
	public:

		void Build(void* pOrigFunc, void* pNewFunc, void* pOrgFuncCaller)
		{
			BYTE szGate[] =
			{
				//pop a	push c	push a	mov a, <dword>	jmp a
				0x58,	0x51,	0x50,	0xB8, 0,0,0,0,	0xFF, 0xE0,
				//pop a	pop c	push a	mov a, <dword>	jmp a
				0x58,	0x59,	0x50,	0xB8, 0,0,0,0,	0xFF, 0xE0
			};

			memcpy(m_szGate, &szGate, sizeof(szGate));

			*(ADDRTYPE*)&m_szGate[4]   = (ADDRTYPE)pNewFunc;
			*(ADDRTYPE*)&m_szGate[14]  = (ADDRTYPE)pOrigFunc;
			
			*(ADDRTYPE*)pOrgFuncCaller = (ADDRTYPE)&m_szGate[10];
		}

		ADDRTYPE Gate()
		{
			return (ADDRTYPE)&m_szGate[0];
		}

	private:
		char m_szGate[20];
	};

	inline bool DeProtect( void* pMemory, unsigned int uiLen, bool bLock = false )
	{
		DWORD dwIDontCare;
		
		if ( ! VirtualProtect( pMemory, uiLen, ( (bLock) ? PAGE_READONLY : PAGE_EXECUTE_READWRITE ), &dwIDontCare ) )
		{
			if ( bLock )
				perror( "Virtual Class memory protect failed (using VirtualProtect)" );
			else
				perror( "Virtual Class memory unprotect failed (using VirtualProtect)" );
			return false;
		}
		return true;
	}

	#define VFUNC __stdcall

	#define DEFVFUNC( funcname , returntype , proto ) \
		funcname##Func funcname = NULL; \
		void* funcname##Raw_Org = NULL; \
		CVirtualCallGate funcname##Gate;
	
	#define HOOKVFUNC( classptr , index , funcname , newfunc ) \
		DeProtect((void*)VTBL( classptr ), ( index * sizeof(void*)) + 4, false ); \
		funcname##Raw_Org = (void*)VFN( classptr , index ); \
		funcname##Gate.Build( funcname##Raw_Org , newfunc , & funcname ); \
		*(ADDRTYPE*)PVFN( classptr , index ) = funcname##Gate.Gate(); \
		DeProtect((void*)VTBL( classptr ), ( index * sizeof(void*)) + 4, true );

	#define UNHOOKVFUNC( classptr , index , funcname ) \
		DeProtect((void*)VTBL( classptr ), ( index * sizeof(void*)) + 4, false ); \
		*(ADDRTYPE*)PVFN( classptr , index ) = (ADDRTYPE) funcname##Raw_Org ; \
		DeProtect((void*)VTBL( classptr ), ( index * sizeof(void*)) + 4, true );

#elif defined _LINUX

	#ifndef PAGESIZE
	#define PAGESIZE 4096
	#endif
	
	inline bool DeProtect(void* pMemory, unsigned int uiLen, bool bLock = false)
	{
	    ADDRTYPE p = (ADDRTYPE) pMemory & ~(PAGESIZE-1);
		if ( mprotect( (void*)p, (ADDRTYPE) pMemory - p + uiLen, PROT_READ | PROT_EXEC | ( (bLock) ? 0 : PROT_WRITE ) ) )
		{
			if ( bLock )
				perror( "Virtual Class memory protect failed (using mprotect)" );
			else
				perror( "Virtual Class memory unprotect failed (using mprotect)" );
			return false;
		}
		return true;
	}

	#define VFUNC

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

	#define HOOKVFUNC( classptr , index , funcname , newfunc ) \
		DeProtect((void*)VTBL( classptr ), ( ( index + 1 ) * sizeof(void*)), false ); \
		funcname = ( funcname##Func )VFN( classptr , index ); \
		*(ADDRTYPE*)PVFN( classptr , index ) = (ADDRTYPE)newfunc ; \
		DeProtect((void*)VTBL( classptr ), ( ( index + 1 ) * sizeof(void*)), true );

	#define UNHOOKVFUNC( classptr , index , funcname , newfunc ) \
		DeProtect((void*)VTBL( classptr ), ( ( index + 1 ) * sizeof(void*)), false ); \
		*(ADDRTYPE*)PVFN( classptr , index ) = (ADDRTYPE)funcname ; \
		DeProtect((void*)VTBL( classptr ), ( ( index + 1 ) * sizeof(void*)), true );

#else

	#error "Unsupported Platform."

#endif

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

#endif // _VFNHOOK_H
*** edit, the VirtualProtect returns non zero if OK... changed... thanks Mani ***
XAD is offline
XAD
Senior Member
Join Date: Mar 2004
Location: Sweden
Old 04-19-2005 , 02:56  
#14

... double post ...
XAD is offline
BeetleFart
SourceMod Donor
Join Date: Apr 2004
Old 11-16-2005 , 13:38  
#15

I got this working with Spraying Decals...

Does anyone know what system and what offset I would have to use to trap
radio commands? and stop them if needed?
__________________
CSource Server:
69.90.34.10:27015 Beetlesmod.com And CS-Addicts{US}



http://www.clanuseast.com
BeetleFart is offline
BAILOPAN
Join Date: Jan 2004
Old 11-17-2005 , 01:47  
#16

If you do any sort of virtual function table hacking like this, you are directly breaking compatibility with SourceHook, which is a safe managed system for hooking virtual functions. You're also introducing race conditions of hooking with other Server Plugins.

You should either warn your users of possible conflicts/crashes due to other plugins or use SourceHook.

That said, I'm locking this thread so I get the last word and people aren't encouraged to further break each other's compatibility with this sort of thing. It's interesting code and certainly useful if you don't care about the issues involved, so I'm leaving the thread available.
__________________
egg
BAILOPAN is offline
Closed Thread


Thread Tools
Display Modes

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 04:17.


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