[C++] Writing your own detour functions

On lunes, 10 de enero de 2011 0 comentarios

[C++] Writing your own detour functions 

 by Sinner

I was gonna show nightghost how to make a detour func, but i might as well write it here so others can use it

Some constants:

#define JMP32_SZ 5 // the size of JMP

#define NOP 0x90 // opcode for NOP
#define JMP 0xE9 // opcode for JUMP


First thing you need to understand - to write a jump in binary it is NOT a simple case of doing: JMP in bytes!
To jump to the right address you must do:

address = (place_we_want_to_jump_to + start_of_memory_where_jump_is_at) - size_of_a_jmp_address

So lets say we want to jump to 0x12345678 and the jump is at 0x55555555:

address = (0x12345678 + 0x55555555) - JMP32_SZ

We need a pointer to the original, the hook, and the length:
1
2
3
void *DetourApply(BYTE *orig, BYTE *hook, int len)
{
    DWORD dwProt = 0;

Next we allocate a place in memory for the bytes we are going to overwrite in the original, plus the size of a jump
instruction:

BYTE *jmp = (BYTE*)malloc(len+JMP32_SZ);

Next we want to allow read & write access to the memory at the original function, and save the previous access to dwProt:

VirtualProtect(orig, len, PAGE_READWRITE, &dwProt);

Next we want to copy the bytes of original + length to the allocated memory place:

memcpy(jmp, orig, len);

Next we want to insert a jump back to the original + length at the end of those intructions we just copied over:
1
2
3
jmp += len; // increment to the end of the copied bytes
jmp[0] = JMP;
*(DWORD*)(jmp+1) = (DWORD)(orig+len - jmp) - JMP32_SZ;

For good practice we want to NOP out all the bytes at the original that we have saved to the memory allocated place:

memset(orig, NOP, len);

Now we want to write a jump at the original to the hooked function:

orig[0] = JMP;
*(DWORD*)(orig+1) = (DWORD)(hook - orig) - JMP32_SZ;

Next we want to put back the old protection flags:

VirtualProtect(orig, len, dwProt, 0);

And finally we want to return a pointer to the start of the memory allocated place (we incremented the pointer by length, so now we do jmp - length)
Code:
return (jmp-len);
}[/c]
Ok now what if we want to remove the detour? Well we have the original bytes copied to that memory allocated place so its a simple case of copying the bytes from there back to the original
1
2
3
4
5
6
7
void DetourRemove(BYTE *orig, BYTE *jmp, int len)
{
    DWORD dwProt = 0;
    VirtualProtect(orig, len, PAGE_READWRITE, &dwProt);
    memcpy(orig, jmp, len);
    VirtualProtect(orig, len, dwBack, 0);
}


Example:
1
2
3
4
DWORD dwLoadLibraryAddr = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dl  l"), "LoadLibraryA");
o_LoadLibraryA = (LoadLibraryA_t) DetourApply((BYTE*) dwLoadLibraryAddr, (BYTE*)h_LoadLibraryA, 5);
 
   DetourRemove((BYTE*) dwLoadLibraryAddr, (BYTE*)o_LoadLibraryA, 5);

0 comentarios:

Publicar un comentario