Import Address Table hooking is a method to redirect execution of a function.
I’ve previously covered inline hooking, so be sure to read that as well.
PE format
Portable Executable is the file format used on Windows for executables, libraries, and certainly more things I can’t remember right now.
It’s an SVG, so open it in a new page and zoom in if needed.
This format contains all the information Windows needs to successfully load an image (an executable) into memory.
Import Address Table
On Windows, our software can make use of functions that are part of a shared library (dynamic link library).
The advantage of dynamic libraries is that they can be loaded into memory only once, saving memory.
However, when mapping these libraries onto a process, the same address can not always be used. This is where the Import Address Table comes in.
You can see the IAT on the image above close to the bottom left.
The IAT is a lookup table, and when loading an image into memory, the loader will fill in the IAT with the correct addresses.
Therefore, instead of the program using addresses to call a function directly, it will call function printf on the IAT
and it will perform an indirect call.
Describing the the process of import resolution in great detail is not my intention here, but please read the following article to learn more http://sandsprite.com/CodeStuff/Understanding_imports.html.
If we overwrite the function pointers on the IAT with a pointer to our own function, we can redirect execution whenever the original function is called.
Viewing imports
Here is some example code.
|
|
Yes, I am aware of how creative I am.
Visualizing the imports on PE-bear, I can see MessageBoxW
is imported from USER32.dll
.
You can also notice that libraries from dynamic libraries and functions that parte part of the program are called differently.
_main PROC
push ebp
mov ebp, esp
push 0
push OFFSET $SG89621
push OFFSET $SG89622
push 0
call DWORD PTR [email protected]
call void a(void) ; a
xor eax, eax
pop ebp
ret 0
_main ENDP
Hooking
We will hook a process IAT by injecting a DLL onto it. After injecting, we will parse the PE header to find our target function in the IAT, and then overwrite the address with our own function.
We need a way to retrieve the original function, so let’s save it before we do any hooking and then have our new function call the old one with modified parameters.
|
|
Parsing the PE is not the easiest thing in the world since it’s a complex format, but it can be done with a little bit of patience.
The best way to learn is to look at the above picture while either reading the code or looking through it manually on an hex editor.
We will need the base address of the module before anything, which can be obtained using GetModuleHandle
.
At the base address we have the DOS header, and we can find the PE header by following e_lfanew
.
|
|
Next we need the optional header and the Import directory:
|
|
We get the address of the import descriptor by adding the RVA to the base address:
|
|
Next we will iterate over the import descriptor until we find our DLL.
Then, we will iterate over each entry in originalFirstThunk
, check whether the function is imported by name, and if it matches the function we want.
We look at its address on firstThunk
at the same position, change the memory protection so we can write to it, write the address of our new function, and then restore the old protection.
From then on, each call to MessageBoxW
will call our hooked function.
|
|
Calling the function now:
|
|
Results in our hooked function being called: