6 June 2016 - batuhan

Windows Api Hooking with x86 Assembly

What is hooking?

In computer programming, the term hooking covers a range of techniques used to alter or augment the behavior of an operating system, of applications, or of other software components by intercepting or function calls or events passed between software components. Code that handles such intercepted function calls, events or messages is called a “hook”.

There are too many reasons for hooking function calls. Most important one is evading the detection mechanisms. We will talk about others a little bit later. Lets introduce Api hooking:

In our scenario, We have gained code execution on a target computer and we wanted to inject our code to the running process in it. There are 2 options on user mode. DLL injection or Process injection. We wont talk about these techniques but after injected our code to the one of process we would want to intercept function calls or modify them.

An Example api we want to hook: MessageBoxA function as shown. MessageBox function takes 4 arguments as Microsoft described,

int WINAPI MessageBox( _In_opt_ HWND hWnd, _In_opt_ LPCTSTR lpText, _In_opt_ LPCTSTR lpCaption, _In_ UINT uType );

1

The simplest way to hook this function is place a unconditional jmp instruction. Unconditional jmp is 5 byte in length and it will jump to our function which we had designed to run before original function.

HookedMessageBoxA PROC ARG1 :DWORD,
ARG2 :DWORD,
ARG3 :DWORD,
ARG4 :DWORD
LOCAL argptr:DWORD
LOCAL hooked[10]:BYTE
mov dword ptr [hooked], 6C697349h
mov dword ptr [hooked+4],00000000h
push ecx
lea ecx,ARG1
mov argptr, ecx
pop ecx
lea edx,hooked ;we wanted to change Text in 2. parameter.
mov ARG2,edx ; we have done it.
mov ebx, 6973696Ch ; our magic dword ‘isil’: we will use it for calling
push ARG4 ; the original function
push ARG3
push ARG2
push ARG1
call ebx
pop ecx
pop ebx
mov esp, ebp
pop ebp
retn 10h
HookedMessageBoxA ENDP

This is enough for testing I think. Now, imagine the original function in memory when we place the unconditional jmp.

2

This is the tricky part. We will overwrite the first 5 bytes of the code. First we need to know the length of the code part which we want to overwrite because an instruction can have a length between 1 byte and 16 bytes. LDE Engine is suitable for this operation. It returns the length of the opcode.


invoke LoadLibraryA,DLL
mov h_Module,eax

invoke GetProcAddress, h_Module, Api
….
lea ebx,IRREVELENT
lea ecx,LocalApi
invoke ReadProcessMemory,pHandle,eax,ecx,40h,ebx ; read to the local buffer.

lea ecx,LocalApi; the local buffer.
LengthCalc:
add ecx,eax
invoke LDE,ecx
cmp eax , 5 ; length must be below or equal 5 byte.
jb LengthCalc
cmp eax,0Fh
ja Error

So what if the original instructions has 6 bytes or more? Answer is simple. Now we can return the original function + length we calculated.

Second, unconditional jmp is a little bit different from call instruction. We need to calculate the relative offset. HookedMessageBoxA – MessageBoxA then, we subtract 5 because that’s the length of the jmp instruction which the CPU adds when executing this instruction.

Then we need to Allocate 2 memory region. First for executing original instructions overwritten before and jmp to original function plus length we calculated.

Second for our HookedMessageBoxA function. If you remember, We had a magic dword “6973696Ch” in HookedMessageBoxA function. We are changing it now for calling the first allocated memory region.

xor eax,eax
Search: ;0x6973696c is our magic DWORD
cmp dword ptr[esi + eax],6973696Ch
jz Write
add eax, 1
jmp Search
Write:
push esi
mov DATAADD,edi
lea edi,DATAADD
add esi,eax
invoke WriteProcessMemory,pHandle,esi,edi,4,ebx

This is the how our HookedMessageBoxA function looks like in the memory:

3

And the original code we are reconstructing now

push 18h
push 90h
lea edx,OriginalCode
push edx
call memoryset
push ecx ; its the length we had calculated before
lea eax, LocalApi
push eax
push edx
call memorycopy
mov [OriginalCode + 0Fh], 0E9h ; unconditional jmp opcode
push edi
mov edx,APIADD
add edx,ecx
add edi,14h
sub edx,edi ; calculated relative offset

4

Complete source code written in masm Visual Studio 2015 project : rayondesoleil.zip

Future work:

There are too much options you can use instead of unconditional jmp. Like call and push then ret (ROP).

Malware

Leave a Reply

Your email address will not be published. Required fields are marked *

WordPress Anti-Spam by WP-SpamShield