PDA

View Full Version : Tutorial Redirecting code execution using debug messages



ThatLameDude
03-12-2010, 09:34 AM
I recently wrote a bit of code that used tier0's debug message outputs to hook stuff. The reasons for this were to avoid using breakpoint hooks which VAC has begun to detect recently, along with the fact that the code I was interested in hooking just happened to be going through Msg before doing interesting stuff. This solution was made as a result. The downsides are that it sucks and is hard to use, but it is being provided here for anyone interested.

This is only useful for redirecting functions that output debug messages to custom code through Msg or other functions. If you're looking to hook a complete function, you're in the wrong place.

A bit of information first: Valve, in their infinite wisdom, allows us to access and change the function used for outputting debug messages. They assume that this will be handling debug messages; however, they don't assume that we'll be touching the stack to change return addresses.

The two functions we're interested in here are:
- SpewOutputFunc, which allows us to change the debug message output.
- GetSpewOutputFunc, which returns the current debug message output function.

First, you'll need to write a new function to handle the spew outputs. If the function outputs the message "hey there sexy", here's how to redirect it.



// NewCode is raw x86 code. Ideally, this should clean up the stack and jump into your
// custom function, or finish executing the function with something you want it to do,
// such as returning a certain value or setting different flags.
UINT8 NewCode[ ] {
// your code goes here
};

// the old spew function, set up below
SpewOutputFunc_t ZeOldSpewOutput = NULL;

static SpewRetval_t ZeNewSpewOutput( SpewType_t spewType, const tchar *msg ) {

if ( strstr(msg,"hey there sexy") ) {

// get the stack pointer
UINT32* theSp = GetStackPointer();

// Step over several stack frames and make sure that the message is being
// output by the function we're expecting to redirect. If the return address
// is on the stack, rewrite it so that it goes into our code.

for (int i = 0x1000; i > 0; i--) {
if (theSp[i] == HookedReturnAddress)) {
theSp[i] = (UINT32)NewCode;
break;
}
}
}

// jump off to the old spew output function
return ZeOldSpewOutput( spewType, msg );
}


Next, you'll need to set up the spew functions.



void HookSpew() {
ZeOldSpewOutput = GetSpewOutputFunc();

// Switch the output on us. All messages now go through our filter.
SpewOutputFunc( ZeNewSpewOutput );
}


When Msg returns from the function you want, your code should execute.

learn_more
03-12-2010, 10:05 AM
unstead of an array with the code, write a function that you declare with __declspec(naked) or even a normal __stdcall function without any arguments.

ThatLameDude
03-12-2010, 10:36 AM
Thanks, didn't know I could do that.