Windows API Hooking – by Code Overwrite

If you don’t know what hooking is, Wikipedia will help you out.

In this article, we’re going to hook/redirect calls to the well-known API function MessageBoxA. The technique is actually fairly simple and short, and I will keep it that way.

In order to overwrite it, we need to find where the function resides in memory. I created a test project in Visual Studio, and wrote:

// Get address for MessageBoxA
FARPROC addr = GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA"); 

// Print address to debugger
char buf[16];
sprintf(buf, "%08x\n", addr);
OutputDebugStringA(buf);

It said “7691fd1e” in the debugger output window. This address could change from time to time though, if for example the DLL is forced by the PE loader to relocate.

Okay? That was easy! So let’s write some machine code to MessageBoxA to jmp to our function instead. Since arguments are put on the stack, we can mess with EAX as much as we want (thanks to stdcall!).

For simplicity’s sake, I used the following code to jump to our code:

mov eax, our_address
jmp eax

Or, when converted to binary machine code it is B8 AABBCCDD FFE0, where AABBCCDD is our address.

// Overwrite stuff!
unsigned char* func = (unsigned char*) addr;
func[0] = 0xb8; // mov eax, our_addr
func[1] = our_addr & 0xff;
func[2] = (our_addr >> 8) & 0xff;
func[3] = (our_addr >> 16) & 0xff;
func[4] = (our_addr >> 24) & 0xff;
func[5] = 0xff; // jmp eax
func[6] = 0xe0;

Run it, and WHAT?! It raised an exception. Windows has some memory protection flags we need to fix before our writes:

// Make sure we have READ + WRITE at address!
DWORD oldProtection;
VirtualProtect(addr, 1024, PAGE_EXECUTE_READWRITE, &oldProtection);

To my suprise, it’s working perfectly! The whole code is below. Note that it is very important that our proxy function has the same calling convention as the original function, namely  __stdcall, otherwise the stack will get messed up.

int __stdcall OurMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
 // All redirected calls will land here!
 OutputDebugStringA("Intercepted call:");
 OutputDebugStringA(lpText);
 return 0;
}
void hook() {
 // Get address for MessageBoxA
 FARPROC addr = GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
    
 // Print address to debugger char buf[16];
 sprintf(buf, "%08x\n", addr);
 OutputDebugStringA(buf);

 // Unprotect 1024 bytes
 DWORD oldProtection;
 VirtualProtect(addr, 1024, PAGE_EXECUTE_READWRITE, &oldProtection);

 DWORD our_addr = (DWORD) &OurMessageBoxA;

 // Write some code to address!
 unsigned char* func = (unsigned char*) addr;
 // mov eax, our_addr
 func[0] = 0xb8;
 func[1] = our_addr & 0xff;
 func[2] = (our_addr >> 8) & 0xff;
 func[3] = (our_addr >> 16) & 0xff;
 func[4] = (our_addr >> 24) & 0xff;
 // jmp eax
 func[5] = 0xff;
 func[6] = 0xe0; 
    
 // Restore protection
 VirtualProtect(addr, 1024, oldProtection, NULL);
    
 MessageBoxA(0, "Test", "Test", 0);
}

I hope you enjoyed this as much as I did. There are still some challenges left for the reader, including figuring out how to return back to the original function after the call has been intercepted (this might be tricky since we’ve overwritten the beginning of the function).

About these ads

4 thoughts on “Windows API Hooking – by Code Overwrite

  1. Can you go into more detail about converting assembly instructions to binary.. how is this done? I assume you get a list of opcodes from intel manual and string them together in little endian ?

    • Pretty much. You can also use an assembler like NASM to speed up the process (especially if you’re dealing with more than 2 instructions!). It is not too difficult to figure out where the operands go.

  2. Excellent blog you have here but I was curious
    if you knew of any community forums that cover the same topics discussed here?
    I’d really like to be a part of online community where I can get suggestions from other knowledgeable people that share the same interest. If you have any suggestions, please let me know. Thank you!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: