Hooking Jmp Tables

On sábado, 22 de enero de 2011 0 comentarios

Hooking Jmp Tables

So what this post will cover is a method I've been using for quite a while to hook functions while remaining undetected, It isn't scanned for by Punkbuster and I'm sure is not caught by VAC.. yet. If you have a background with Punkbuster this should be familiar to you. I am posting this because I haven't found too many posts around showing off this method, if any at all.


Now, Let's start with an example for Battlefield Play4Free/Refactor 2 engine it's Reset function and Jmp table.

It's Reset Function looks like the following
It's Reset Function looks like the following
Code:
51               PUSH ECX
56               PUSH ESI
8BF1             MOV ESI,ECX
80BE 4A010000 00 CMP BYTE PTR DS:[ESI+14A],0
74 05            JE SHORT RendDX9.0837FE42
B0 01            MOV AL,1
5E               POP ESI
59               POP ECX
C3               RETN

Amongst the Jmp table at the beginning of the RendDx9.dll is a Jmp to this function that is used to call this function. Now we can find this by using some black magic in the form of a function like the following..
Code:
DWORD FindRelativeJmp( DWORD base, DWORD size, DWORD address )
{
 for (DWORD end = base + size; base < end; ++base)
 {
  if (*reinterpret_cast(base) != 0xE9) continue;

  if ((address - base) - 4 == *reinterpret_cast(base + 1))
   return base;
 }

 return NULL;

But it doesn't do much good if we don't know the address of the 
function, so let's just step along and assume we have a Pattern to 
search for with a Generic FindPattern function. Under the assumption 
you're still following (You should be..) here is an example of hooking 
Play4Free's Reset function.. 
Code:
DWORD dwResetTrampoline = NULL;
DWORD dwResetJmp = NULL;


void __stdcall __Reset( void )
{
 __asm PUSHAD;
 // TODO: Call OnLostDevice
 __asm POPAD;

 ((void (__stdcall *)(void))dwResetTrampoline)(); // Call the original Reset
 // TODO: Call OnResetDevice
}
void __stdcall Init( void )
{
 HMODULE RendDx9 = LoadLibrary(TEXT("RendDx9.dll"));
 CHAR ResetPattern[] = 
 {
  '\x51',
  '\x56',
  '\x8B', '\xF1',
  '\x80', '\xBE', '?', '?', '?', '?', '?',
  '\x74', '\x05',
  '\xB0', '\x01',
  '\x5E',
  '\x59',
  '\xC3', '\0'
 };

 while (dwResetJmp == NULL)
 {
  dwResetJmp = FindPattern(reinterpret_cast(RendDx9), 0x650000, ResetPattern);
  dwResetJmp = FindRelativeJmp(reinterpret_cast(RendDx9), 0x650000, dwResetJmp);
  Sleep(100);
 }

 dwResetTrampoline = reinterpret_cast
  ( DetourFunction(reinterpret_cast(dwResetJmp), reinterpret_cast(__Reset)) );
}
 
 
 What we are doing is..
  • Finding the function we want to hook by pattern searching
  • Finding a relative jmp to the specified function
  • Changing that jmp so it jmps to our function, by use of DetourFunction
  • ...
  • Profiting

The concept is straight forward and fairly clean.. But there are some problems. For example a game has a Jmp table, but it has x # of functions before it.. This can cause problems because a relative Jmp to our function may exist inside a function which would result in us Hooking the wrong relative Jmp. A game may also not make use of a Jmp table all of the time, this would cause problems because hooks wouldn't be getting "called".



Why should I use this method (For now at least..)?
> Because there aren't very many anti-cheats that can hash a Jmp table correctly without giving false-positives, but this can easily change.
> It's not much messier than your average Detour.
> It's easy to implement.

What is required for this method to be used?
> The game must obviously have a jmp table, and you HAVE to know the location of it.
> There can NOT be any functions etc. that come before the Jmp table otherwise you may end up hooking the wrong thing and cause problems.
> There is guarantee before hand that a Jmp table will be utilized every time the specified function is called, you'll have to investigate each case for yourself.



Hope this was at least a decent read for you and possibly informative for some. If you have any questions I'll do my best to answer them.

0 comentarios:

Publicar un comentario