# Import Address Table (IAT) Hooking

## Import Adress Table (IAT) Hooking

### Overview

* Windows portable executable contains a structure called `Import Address Table (IAT)`
* IAT contains pointers to information that is critical for an executable to do its job:
  * a list of DLLs it depends on for providing the expected functionality
  * a list of function names and their addresses from those DLLs that may be called by the binary at some point
* It is possible to hook function pointers specified in the IAT by overwriting the target function's address with a rogue function address and optionally to execute the originally intended function

Below is a simplified diagram that attempts to visualize the flow of events before and after a function\
(`MessageBoxA` in this example, but could be any) is hooked:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LujUxqEwvQ8GVJuyKNY%2F-LulPrP3NUbUY6FD2CpU%2Fimage.png?alt=media\&token=75271be1-0a7d-4dd5-ba59-8261615d6ed2)

**Before hooking**

1. the target program calls a WinAPI `MessageBoxA` function
2. the program looks up the `MessageBoxA` address in the IAT
3. code execution jumps to the `kernel32!MessageBoxA` address resolved in step 2 where legitimate code for displaying the `MessageBoxA` (green box) lives

**After hooking**

1. the target program calls `MessageBoxA` like before hooking
2. the program looks up the `MessageBoxA` address in the IAT
3. this time, because the IAT has been tampered with, the `MessageBoxA` address in the IAT is pointing to a rogue `hookedMessageBox` function (red box)
4. the program jumps to the `hookedMessageBox` retrieved in step 3
5. `hookedMessageBox` intercepts the `MessageBoxA` parameters and executes some malicous code
6. `hookedMessageBox` calls the legitimate `kernel32!MessageBoxA` routine

### Walkthrough

In this lab I'm going to write a simple executable that will hook `MessageBoxA` in its process memory space by leveraging the IAT hooking technique and redirect it to a function called `hookedMessageBox` as per above visualisation and then transfer the code execution back to the intended `MessageBoxA` routine.

{% hint style="warning" %}
IAT hooking is usually performed by a DLL injected into a target process, but for the sake of simplicity and illustration, in this lab, the IAT hooking is implemented in the local process.
{% endhint %}

To hook the `MessageBoxA` we need to:

1. Save memory address of the original `MessageBoxA`
2. Define a `MessageBoxA` function prototype
3. Create a `hookedMessageBox` (rogue `MessageBoxA`) function with the above prototype. This is the function that intercepts the original `MessageBoxA` call, executes some malicious code (in my case, it invokes a `MessageBoxW`) and transfers code execution to the original `MessageBoxA` routine for which the address is retrieved in step 1
4. Parse IAT table until address of `MessageBoxA` is found
   1. More about PE parsing in [Parsing PE File Headers with C++](https://hamcodes.gitbook.io/hackersnotes/reversing-forensics-and-misc/internals/parsing-pe-file-headers-with-c++)
   2. More about Import Address Table parsing in [Reflective DLL Injection](https://hamcodes.gitbook.io/hackersnotes/offensive-security/code-and-process-injection/reflective-dll-injection)
5. Replace `MessageBoxA` address with address of the `hookedMessageBox`

As a reminder, we can check the IAT of any binary using CFF Explorer or any other PE parser. Below highlighted is one of the IAT entries - the target function `MessageBoxA` that will be patched during runtime and swapped with `hookedMessageBox`:

![IAT table, CFF Explorer](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LunGQFurZBU6FeU6yIp%2F-LutnrDLKI1_jOwA73F7%2Fimage.png?alt=media\&token=5acb0b90-950c-4449-87b8-116faba0f3a5)

### Code

Below is the code and key comments showing how IAT hooking could be implemented:

```cpp
#include <iostream>
#include <Windows.h>
#include <winternl.h>

// define MessageBoxA prototype
using PrototypeMessageBox = int (WINAPI *)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);

// remember memory address of the original MessageBoxA routine
PrototypeMessageBox originalMsgBox = MessageBoxA;

// hooked function with malicious code that eventually calls the original MessageBoxA
int hookedMessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
	MessageBoxW(NULL, L"Ola Hooked from a Rogue Senor .o.", L"Ola Senor o/", 0);
	// execute the original NessageBoxA
	return originalMsgBox(hWnd, lpText, lpCaption, uType);
}

int main()
{
	// message box before IAT unhooking
	MessageBoxA(NULL, "Hello Before Hooking", "Hello Before Hooking", 0);
	
	LPVOID imageBase = GetModuleHandleA(NULL);
	PIMAGE_DOS_HEADER dosHeaders = (PIMAGE_DOS_HEADER)imageBase;
	PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)imageBase + dosHeaders->e_lfanew);

	PIMAGE_IMPORT_DESCRIPTOR importDescriptor = NULL;
	IMAGE_DATA_DIRECTORY importsDirectory = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
	importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(importsDirectory.VirtualAddress + (DWORD_PTR)imageBase);
	LPCSTR libraryName = NULL;
	HMODULE library = NULL;
	PIMAGE_IMPORT_BY_NAME functionName = NULL; 

	while (importDescriptor->Name != NULL)
	{
		libraryName = (LPCSTR)importDescriptor->Name + (DWORD_PTR)imageBase;
		library = LoadLibraryA(libraryName);

		if (library)
		{
			PIMAGE_THUNK_DATA originalFirstThunk = NULL, firstThunk = NULL;
			originalFirstThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)imageBase + importDescriptor->OriginalFirstThunk);
			firstThunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)imageBase + importDescriptor->FirstThunk);

			while (originalFirstThunk->u1.AddressOfData != NULL)
			{
				functionName = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)imageBase + originalFirstThunk->u1.AddressOfData);
					
				// find MessageBoxA address
				if (std::string(functionName->Name).compare("MessageBoxA") == 0)
				{
					SIZE_T bytesWritten = 0;
					DWORD oldProtect = 0;
					VirtualProtect((LPVOID)(&firstThunk->u1.Function), 8, PAGE_READWRITE, &oldProtect);
						
					// swap MessageBoxA address with address of hookedMessageBox
					firstThunk->u1.Function = (DWORD_PTR)hookedMessageBox;
				}
				++originalFirstThunk;
				++firstThunk;
			}
		}

		importDescriptor++;
	}

	// message box after IAT hooking
	MessageBoxA(NULL, "Hello after Hooking", "Hello after Hooking", 0);
	
	return 0;
}
```

### Demo

Our binary's base address (ImageBase) in memory is at `0x00007FF69C010000`:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LunGQFurZBU6FeU6yIp%2F-LutsC4uwoiEkLe-F14u%2Fimage.png?alt=media\&token=dae7862d-a83b-456a-9a8b-b234a047c0fd)

Before IAT manipulation, `MessageBoxA` points to `0x00007ffe78071d30`:

![Line 58 in provided code - MessageBoxA is located at 0x00007ffe78071d30 before hooking](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LunGQFurZBU6FeU6yIp%2F-Lutw-TY0mzqj4KQj5Zy%2Fimage.png?alt=media\&token=91942ede-ca95-4107-aa99-92f744d4a380)

If interested, we can manually work out that `MessageBoxA` is located at `0x00007ffe78071d30` by:

1. adding the ImageBase `0x00007FF69C010000` and Relative Virtual Address (RVA) of the First Thunk of `MessageBoxA` `0x000271d0` which equals to `0x00007FF69C0371D0`
2. dereferrencing `0x00007FF69C0371D0`

![RVA of the function MessageBoxA](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LunGQFurZBU6FeU6yIp%2F-Luttc22F934_KKUhWAD%2Fimage.png?alt=media\&token=ef0f30d1-7fde-4317-9a01-8b1f3f794c73)

Dereferrencing `0x00007FF69C0371D0 (0x00007FF69C010000 + 0x000271d0)` reveals the `MessageBoxA` location in memory `0x00007ffe78071d30`:

![0x00007FF69C0371D0 points to MessageBoxA at 0x00007ffe78071d30](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LunGQFurZBU6FeU6yIp%2F-LutuRPwoQhB1u29blRw%2Fimage.png?alt=media\&token=56d87ae9-5e0f-415e-a4bc-f0b6a2cbe116)

Now, our `hookedMessageBox` is located at `0x00007ff396d5440`:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LujCBxZV2fH0--5dpyG%2F-LujP-UnPtx04_QMfL3N%2Fimage.png?alt=media\&token=cb2888c0-451a-4a9e-829b-72010867466e)

After the IAT manipulation code executes, `MessageBoxA` points to `hookedMessageBox` at `0x00007ff396d5440`

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LujCBxZV2fH0--5dpyG%2F-LujPHpMG9OIQZQKoIfl%2Fimage.png?alt=media\&token=3d389793-ac04-47f9-a787-344b1905d2cf)

Once the function pointers are swapped, we can see that calling the `MessageBoxA` with an argument `Hello after Hooking` does not print `Hello after Hooking`, rather, the message text is that seen in the `hookedMessageBox` routine, confirming that the IAT hook was successful and the rouge function was called first:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LujCBxZV2fH0--5dpyG%2F-LujPdWTo11DAv1LIkVx%2Fimage.png?alt=media\&token=8cdce074-9b65-4b81-84b4-3485d4a261b1)

Below shows the entire flow of key events that happen in this program:

1. Before hooking, `MessageBoxA` is called with an argument `Hello Before Hooking` and the program displays the message as expected
2. After IAT hooking, `MessageBoxA` is called with an argument `Hello after Hooking`, but the program gets redirected to a `hookedMessageBox` function and displays `Ola Hooked from a Rogue Senor .o.`
3. Finally, `hookedMessageBox` calls the original `MessageBoxA` which prints out the intended `Hello after Hooking`

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-LujCBxZV2fH0--5dpyG%2F-LujQUW8-NQydFhBqrCE%2Fiat-hook-demo.gif?alt=media\&token=a3544841-c3b0-4f9e-a357-090e78f63372)

### References

{% content-ref url="windows-api-hooking" %}
[windows-api-hooking](https://hamcodes.gitbook.io/hackersnotes/offensive-security/code-and-process-injection/windows-api-hooking)
{% endcontent-ref %}

{% content-ref url="reflective-dll-injection" %}
[reflective-dll-injection](https://hamcodes.gitbook.io/hackersnotes/offensive-security/code-and-process-injection/reflective-dll-injection)
{% endcontent-ref %}

{% content-ref url="../../reversing-forensics-and-misc/internals/parsing-pe-file-headers-with-c++" %}
[parsing-pe-file-headers-with-c++](https://hamcodes.gitbook.io/hackersnotes/reversing-forensics-and-misc/internals/parsing-pe-file-headers-with-c++)
{% endcontent-ref %}
