Results 1 to 2 of 2
  1. #1
    Dwar
    Dwar is offline
    Veteran Dwar's Avatar
    Join Date
    2010 Mar
    Posts
    2,221
    Thanks
    211
    Thanked 2,224 Times in 289 Posts
    Rep Power
    10

    [Asm] IAT Hooking

    IAT Hooking

    This tutorial teaches you how to do IAT hooking on your own module. Each module in a portable executable has its own IAT.
    Quote Originally Posted by wiki
    Import Table
    One section of note is the import address table (IAT), which is used as a lookup table when the application is calling a function in a different module. It can be in form of both import by ordinal and import by name. Because a compiled program cannot know the memory location of the libraries it depends upon, an indirect jump is required whenever an API call is made. As the dynamic linker loads modules and joins them together, it writes jump instructions into the IAT slots, so that they point to the memory locations of the corresponding library functions. Though this adds an extra jump over the cost of an intra-module call resulting in a performance penalty, it provides a key benefit: dynamic libraries are much more flexible and reduce code redundancy (which would occur if common libraries had to be linked statically to each program). If the compiler knows ahead of time that a call will be inter-module (via a dllimport attribute) it can produce more optimized code that simply results in an indirect call opcode.

    Texe and LordPE are tools that can be used to view the Import and Export tables of PE Files.
    In fact, it is not that hard to hook the IAT of another module if you have a good knowledge of the PE format.
    Quote Originally Posted by wiki
    The Portable Executable (PE) format is a file format for executables, object code and DLLs, used in 32-bit and 64-bit versions of Windows operating systems. The term "portable" refers to the format's versatility in numerous environments of operating system software architecture. The PE format is a data structure that encapsulates the information necessary for the Windows OS loader to manage the wrapped executable code. This includes dynamic library references for linking, API export and import tables, resource management data and thread-local storage (TLS) data. On NT operating systems, the PE format is used for EXE, DLL, OBJ, SYS (device driver), and other file types. The Extensible Firmware Interface (EFI) specification states that PE is the standard executable format in EFI environments.
    Straight into it :
     .486
    .model flat,stdcall
    option casemap:none
    option epilogue:none
    option prologue:none
    include masm32includewindows.inc
    include masm32includeuser32.inc
    include masm32includekernel32.inc
    includelib masm32libuser32.lib
    includelib masm32libkernel32.lib

    myfunc proto :DWORD, :DWORD, :DWORD, :DWORD

    .DATA

    Caption db "Success !",0
    Text db "Called successfully via trampoline",0

    .DATA?

    fxn_addr dword ?

    .CODE

    start:

    xor ebx,ebx
    mov eax,[MessageBox]
    add eax,2
    mov eax,[eax]
    mov eax,[eax]
    add eax,5
    mov fxn_addr, eax

    invoke myfunc, ebx, addr Text, addr Caption, ebx
    invoke ExitProcess, ebx

    myfunc proc w:DWORD,x:DWORD,y:DWORD,z:DWORD

    push ebp
    mov ebp,esp
    jmp fxn_addr

    myfunc endp

    end start

    Here I show you a way to trampoline over first 5 bytes of MessageBox without ever calling GetModuleHandle/LoadLibrary and GetProcAddress
    Instead I use my understanding of the MASM32 linker to read the current address of the IAT via the thunk table Read on !
     .486
    .model flat,stdcall
    option casemap:none
    option epilogue:none
    option prologue:none
    include masm32includewindows.inc
    include masm32includeuser32.inc
    include masm32includekernel32.inc
    includelib masm32libuser32.lib
    includelib masm32libkernel32.lib

    Making declarations, etc. etc. Important things to note are these two lines:

    option epilogue:none
    option prologue:none


    Usually when you are making a call to your own defined function, it will add some code at the start that sets up stack frame and some code that pops EBP back off. That is, your function will automatically set up its own stack frame:

    push ebp
    mov ebp, esp


    Saving stack base then changing new stack base as old top of stack.
    So we want to turn this function off and you will see why later.
     myfunc proto :DWORD, :DWORD, :DWORD, :DWORD

    .DATA

    Caption db "Success !",0
    Text db "Called successfully via trampoline",0

    .DATA?

    fxn_addr dword ?

    Declaring my own function prototype that takes 4 dwords as arguments. Defining 2 null terminated strings for later. Defining an uninitialised dword that will hold the function address that we want to trampoline.
     .CODE

    start:

    xor ebx,ebx
    mov eax,[MessageBox]
    add eax,2
    mov eax,[eax]
    mov eax,[eax]
    add eax,5
    mov fxn_addr, eax

    Some note about the MASM linker. It tells the PE loader where addresses are via its own thunk table which is usually located at the end of the executable. It is a pointer to the import address table (which updates off the corresponding dynamic link library's export address table I believe).

    So first off, I set ebx to 0 as above. This means later when I am going to use "push 0" instructions, I can "push ebx" instead which results in a smaller, faster executing program. ebx is chosen because it is a register that stdcall convention does not fiddle around with, unlike eax, ecx and edx.

    Let me just show you a screenshot of the thunk table generated by MASM's linker:

    You can see several things here.

    - The "CALL 0040102D" is the call to my function. It directly calls the address of my function.
    - There is a little table at the end with 3 entries

    The table is the JMP thunk table. If you look at what code is the call to ExitProcess:

    It does not call the virtual address of ExitProcess. This is because the address changes and so you can not just hardcode an address, unlike for my own function. What it calls instead is the entry of ExitProcess in the thunk table which is:

    JMP DWORD PTR DS:[<&kernel32.ExitProcess>]

    If you try to see what instruction that actually is, it is:

    JMP DWORD PTR DS:[402000]

    0x402000 is the entry in the import address table for the ExitProcess function. So if you look in the hex dump..

    Bearing in mind the little endianness that the 80x86 uses, this means the current address of ExitProcess on my system is 0x76793B54. Sure enough, if I go there:

    You can already recognise that procedure as ExitProcess because of the native API it calls : RtlExitUserProcess.

    So now we know how to manually find the address of a function, look at how I have done it in MASM:
     mov eax,[MessageBox]
    add eax,2
    mov eax,[eax]
    mov eax,[eax]
    add eax,5
    mov fxn_addr, eax

    The first instruction will move the virtual address of the entry in the thunk table of MessageBox into eax. Then we add 2 to that address. Maybe you are thinking "wtf is this kid smoking ?". Look at this:

    The bytes for "JMP DWORD PTR DS:[402008]" is "FF25 08204000". So the first 2 bytes "FF 25" must be for the opcode saying JMP DWORD PTR DS:[]. Then the pointer itself are the next 4 bytes (note the little endianness), 08204000 >> 402008

    So "mov eax, [MessageBox]" would lead us to the virtual address that the above instruction is on. So to get to the actual pointer to the IAT entry for this API, we need to add 2 bytes. Next we have:

    mov eax,[eax]
    mov eax,[eax]


    We move the dword that is pointed to by eax into eax. So before this instruction executes, eax is the address of the thunk entry for that address + 2 which is the pointer to the IAT entry. So the first "mov eax, [eax]" moves the address of the IAT entry into eax. Then we do it again and this time the dword held at the IAT entry is moved into eax. You already saw from before that IAT holds a pointer to the function address.
    Now we set up our address ready for trampolining:

    add eax,5
    mov fxn_addr, eax


    We add 5 to eax and then move that into our buffer named fxn_addr. All will be explained later if you have not come across this 5 byte trampoline method before !
     invoke myfunc, ebx, addr Text, addr Caption, ebx
    invoke ExitProcess, ebx

    myfunc proc w:DWORD,x:DWORD,y:DWORD,z:DWORD

    push ebp
    mov ebp,esp
    jmp fxn_addr

    myfunc endp
    end start

    So directly after this, I invoke my prototype function. The 4 dword parameters it is taking is ebx, address of text, address of caption and ebx again. These are the arguments for a normal call to MessageBox:

    So the hWnd and type is null, which is fine if you look at the exact description of those arguments. Then address of text and caption as defined earlier, fine also. Now let's look at what my function is comprised of:
     myfunc proc w:DWORD,x:DWORD,y:DWORD,z:DWORD
    push ebp
    mov ebp,esp
    jmp fxn_addr

    myfunc endp

    address of MessageBoxA + 5. So when I call my procedure, what happens is:
    - Return address is pushed onto stack (virtual address of instruction directly after the call)

    - Execution goes to the address that is called
    - My procedure sets up stack frame (which is what the first 5 bytes of MessageBoxA does)
    - We jmp to MessageBoxA + 5

    What this has achieved is that it means we can now execute any function without ever touching its first 5 bytes. This is where GameGuard places its usermode hooks, as a far jump at the first 5 bytes of the function. So we can use this method to trampoline over GG's hook.

    There are a few tricks that you will have to learn before you are able to do this to bypass a usermode hook but I'll let you figure that out yourself, it'd be no fun if I told you everything !

    Later to come if I get bored enough.. How to do IAT hooking and intercept arguments of a function call and replace it with your own

    (Now is later..)

    MOAR CODE !!!

    This code shows how to dynamically fetch the first 5 bytes (before I hardcoded bytes to set up stack frame). It also shows how to hook your own program's IAT and notice I have intercepted and modified the arguments of a call to MessageBox. If you need anything explained, please shout
     .486
    .model flat, stdcall
    option casemap:none
    option epilogue:none
    option prologue:none
    include masm32includewindows.inc
    include masm32includeuser32.inc
    include masm32includekernel32.inc
    includelib masm32libuser32.lib
    includelib masm32libkernel32.lib

    WriteMem proto
    My_Proc proto

    .DATA

    Caption db "Title",0
    Text db "Text",0
    API_Fxn dd MessageBox
    Mod_Caption db "Modified Title",0
    Mod_Text db "Modified Text",0

    .DATA?

    IAT_Entry_Addr dword ?
    Fxn_Addr dword ?
    Proc_Addr dword ?
    Ret_Addr dword ?

    Arg1 dword ?
    Arg2 dword ?
    Arg3 dword ?
    Arg4 dword ?

    StackFrameCheck dword ?

    .CODE

    start:

    xor ebx, ebx
    mov eax, [API_Fxn]
    add eax, 2
    mov eax, [eax]
    mov IAT_Entry_Addr, eax
    mov eax, [eax]
    mov Fxn_Addr, eax
    mov eax, offset My_Proc
    mov Proc_Addr, eax

    invoke WriteMem

    push ebx
    push offset Caption
    push offset Text
    push ebx
    call API_Fxn

    invoke ExitProcess, ebx

    WriteMem proc

    LOCAL OldProt:DWORD
    LOCAL OldProcProt:DWORD

    invoke VirtualProtect, IAT_Entry_Addr, 4, PAGE_EXECUTE_READWRITE, addr OldProt

    mov ecx, Proc_Addr
    mov edx, IAT_Entry_Addr
    mov [edx], ecx

    invoke VirtualProtect, IAT_Entry_Addr, 4, OldProt, addr OldProt
    invoke VirtualProtect, Proc_Addr, 5, PAGE_EXECUTE_READWRITE, addr OldProcProt

    mov eax, Fxn_Addr
    mov eax, [eax]
    mov ecx, [Proc_Addr]
    mov [ecx], eax
    mov eax, Fxn_Addr
    add eax, 4
    mov al, byte ptr ds:[eax]
    mov ecx, [Proc_Addr]
    add ecx, 4
    mov byte ptr ds:[ecx], al

    invoke VirtualProtect, Proc_Addr, 5, OldProcProt, addr OldProcProt
    ret

    WriteMem endp

    My_Proc proc
    nop
    nop
    nop
    nop
    nop
    pop StackFrameCheck
    pop Ret_Addr
    pop Arg4
    pop Arg3
    pop Arg2
    pop Arg1
    push ebx
    push offset Mod_Caption
    push offset Mod_Text
    push ebx
    push Ret_Addr
    push StackFrameCheck
    mov eax, [Fxn_Addr]
    add eax, 5
    jmp eax
    My_Proc endp

    end start

    Dynamically reads first 5 bytes of a given function and writes it to our own function prototype which then executes those 5 bytes, intercepts the arguments, modifies them and then trampolines over the real first 5 bytes (possible place where hook would go) to execute the rest of the real function
    Author: c0lo
    Please, post your questions on forum, not by PM or mail

    I spend my time, so please pay a little bit of your time to keep world in equilibrium

  2. The Following User Says Thank You to Dwar For This Useful Post:


  3. #2
    D3m0tol
    D3m0tol is offline
    New member
    Join Date
    2010 Sep
    Posts
    13
    Thanks
    6
    Thanked 3 Times in 1 Post
    Rep Power
    0

    Re: [Asm] IAT Hooking

    thnx for this tutorial i wanted to know more about IAT hooking

Visitors found this page by searching for:

iat hooking tutorial

IAT indirect jmp thunk

iat asm

asm hook

iat hook

rtlexituserprocess

hooking iat

x64 iat hook

iat hook x64

asm hooking

masm iat hookasm IAT hookiat hooking x64iat hook tutorialjmp thunk tablex64 jmp hookPortable Executable prologueiat hookingiat patching 64 bitHOOK ASMIAT slotsiat programmingasmiatiat addressIAT in programming

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •