Hooking Code

Some old stuff, that I've written in 2008. Would be a shame if it gets lost somehow :) The code got updated a little, if I find the time I'll add the new stuff and try to format the text a little bit, so that it looks nicely on the blog

Hi,

i wanted to share some ideas and looking for ideas/comments.

Some of you might already have read about Hooking code (Detours,etc). PeterPan tries to install the Hook in a more generic&easier way.

The old approach It works like this: We take CreateFileA as an example. Looking at the disassembly you will see:

.text:77E48CA4                 mov     edi, edi
.text:77E48CA6                 push    ebp
.text:77E48CA7                 mov     ebp, esp

Mov has 2 bytes, Push has 1, so this makes a total of 5 Bytes for these 3 instructions.

Now, if we want to hook that routine, we have to get to our code, this is done by a jmp. And looking at the jmp instruction we see that it has 5 bytes (0xE9 and 4 bytes for relative jump address)

Now the "mov edi,edi" makes sense! Microsoft has introduced this to pad the Preamble of a function from 3 to 5 bytes, so that we can hook functions more easily (Yes, no joke...).

Ok, so to hook the function we need to do the following:

Manually check the function, see how many bytes we need to save for later use. Copy the bytes and put at the end a jump to the original function back (not directly to the function beginning, but

to the address that is after our evil jmp) Put our jmp code at the beginning of the original function.

In the section where we jump to, do some stuff, and then jmp to our saved bytes.

Ok, let's do this at our example:

.text:77E48CA4                 mov     edi, edi
.text:77E48CA6                 push    ebp
.text:77E48CA7                 mov     ebp, esp
.text:77E48CA9                 push    [ebp+lpFileName]
.text:77E48CAC                 call    sub_77E48C56
.text:77E48CB1                 test    eax, eax

So, we copy 5 bytes + jmp back. This will look like this:

SavedFunction:

mov edi,edi
push ebp
mov ebp,esp
jmp 77E48CA9

Our original function will look like this:

.text:77E48CA4                 jmp ourEvilCode
.text:77E48CA9                 push    [ebp+lpFileName]
.text:77E48CAC                 call    sub_77E48C56
.text:77E48CB1                 test    eax, eax

And ourEvilCode can look like this:

bla
bla
bla
jmp SavedFunction

This works nicely, but what are the downsides?

You have to check every function, for the size you need to save. For Windows API this is easy, since 99% have the 5 byte preambel... Let's insert a nop (1 byte length) at the beginning:

nop
mov edi,edi
push ebp
mov ebp,esp

If you now copy 5 bytes, you will break the mov ebp,esp. And the jmp back would jmp into the 2nd byte of the mov..

This will give you a protection fault sooner or later.

The second thing is, if you want to hook more functions, you have to create a ourEvilCode for every function you're hooking (Because you need to jmp to a different SavedFunction, and probably want to have a different Payload for every function)

Here's my idea of PeterPan:

We have a table that gives us the length of an opcode, with this we can analyze how many bytes we have to save, and where to jmp back in the code instead of jmp ourEvilCode, we do a call ourEvilCode. This puts eip onto the stack. with pop eax, we now have the eip of the calling code, so we can have a lookup table for which Payload we want to execute, and which SavedFunction we need to call. Some party of my code (i'm thinking about releasing the whole code, but i need to clean it up a little more first) It's a proof-of-concept, so there's plenty of room for improvements and cleanups...

How it's used

HMODULE mylo=LoadLibrary("kernel32.dll");
DWORD add=(DWORD)GetProcAddress(mylo,"CreateFileA");
doHook(add,(DWORD)&payload);

Build the stuff we insert into targetFunction

char *jmpcode=(char*)malloc(50);

memset(jmpcode,0x90,50);

jmpcode[0]=0xE8;            // call XX XX XX XX

DWORD reljmp;
reljmp= (DWORD)&myLoad-(targetFunction+5);

memcpy(jmpcode+1,&reljmp,4);

DWORD OLD;
VirtualProtectEx(GetCurrentProcess(),(void*)targetFunction,50,PAGE_EXECUTE_READWRITE,&OLD); 
memcpy((void*)targetFunction,jmpcode,copysize-1);

Calculate how many bytes we need to save

int copysize=-1;

for(int i=0;i<30;i++) {            // 30 bytes should be enough
    p=(char*)(targetFunction+i);

    DWORD in=(DWORD)*p;
    in=in & 0xFF;                

    if(step[in]!=-1)         //in step[] we have the length of each opcode
    {
        i+=step[in];
    } else {
        return -1;        //Damn... unknown opcode, let's fail :(
    }
    if(i>=4) {             
        copysize=i+1; break;    //Ok, we have at least 5 bytes 
    }

}

this is the function we call from targetFunction

yolo
__declspec (naked) void myLoad() {
__asm {        
        nop            // i like to have nops, easier to find code in disassembly :)

        pop eax            // get calling address & save it
        mov meax,eax

        push eax        // do we have a Payload?
        call getPay
        add esp,4

        cmp eax,0
        je rock_on
        call eax        // Call it...
rockon:


        mov eax,meax        // eax=Address of Caller
        push eax
        call getBack        // Get adress of backjump
        add esp,4

        mov eax,eax        // just ignore this line :) 
        jmp eax            
}
}