Hi all. Yes, we are looking at hooks still. So many ways to skin this cat. Here’s another method, however this one revolves around imported functions.
What
The Import Address Table (IAT) is the list of functions that a portable executable (PE) imports from DLLs for it to use. This table is stuck into the PE header which can be parsed and read by another process. If you’ve looked at a few Road To Malware Analysis posts, you’ve seen how viewing these imported functions can be used as clues as to how they function.
There are actually 3 import tables. There’s the Import (Directory) Table (IDT), Import Lookup Table (ILT), and Import Address Table (IAT).
The IDT contains the DLLs that are imported and a pointer to the library’s first function in the IAT.
The ILT contains pointers to the names of the functions that are listed in the IAT. They are also in the same order. This is also why imported function names show up in the strings list.
The IAT contains the function pointers of the imported functions.
Why
A fun thing you can do here is that you can replace these tabulated function pointers with your own. Essentially, you can make an executable call your functions with relative ease. The only catch is that you can only do it with imported functions.
How
It’s very simple. All you need to do is load up the IAT, scan it and find the function you want to replace, and replace it with your own function.
Methodology
Write a DLL that replaces an imported function used in a target process via an IAT hook;
Alter the functionality of the imported function;
Requirements
(Preferably) a PE header exploring program such as PeStudio or PEExplorer;
A DLL injecting program;
C++ Knowledge;
Ability to parse a PE header;
You won’t need a disassembler for this post, finally! :D
Another program on my Tor site. It’s a zip file called “iat” under the programs folder.
Running hello.exe yields a prompt to enter your name, then after entering it, a message box pops up saying “Hello, name!”.
If you’re unaware of what function is used to open a message box, it’s just called MessageBox
(MessageBoxA
in this case). The goal is to perform an IAT hook on the MessageBoxA
function and alter what it says.
You can look at the exe in PeStudio to ensure that the function MessageBoxA
is used. Let’s hook it.
Your function should should have a prototype that mimics that of MessageBoxA
. If the function declaration differs from the one used in the target executable, then a crash may occur.
#include <Windows.h>
#pragma comment(lib, "user32.lib")
using tMessageBoxA = int (WINAPI *)(HWND, LPCSTR, LPCSTR, UINT);
tMessageBoxA oMessageBoxA{};
oMessageBoxA
is going to hold a pointer to the original MessageBoxA
function. This is in case your module is to unload and you want to undo your hook and return functionality to normal. It’s good practice. Also note the function prototype.
Next will be the hook function.
int WINAPI hMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
return MessageBoxA(hWnd, "I'm in your wallsI'm in your wallsI'm in your wallsI'm in your wallsI'm in your wallsI'm in your wallsI'm in your wallsI'm in your wallsI'm in your walls", lpCaption, uType);
}
The hook is ready. All that is left is to replace the function in the IAT. This involves loading the PE header, finding the location of the IAT from optional header’s data directory, and iterating it until you hit MessageBoxA
.
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hinstDLL);
CreateThread(0, 0, [](LPVOID param) -> DWORD
{
// Get the IAT of the attached process
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)GetModuleHandle(0);
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((DWORD)dos + dos->e_lfanew);
PIMAGE_IMPORT_DESCRIPTOR iat = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)dos + nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
// Get the address of MessageBoxA
while (iat->Name)
{
PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)((DWORD)dos + iat->FirstThunk);
while (thunk->u1.Function)
{
if (thunk->u1.Function == (DWORD)MessageBoxA)
{
// Get the address of the IAT entry
DWORD *iatentry = (DWORD *)((DWORD)dos + iat->FirstThunk + (DWORD)(&thunk->u1.Function) - (DWORD)thunk);
// Save the original function
oMessageBoxA = (tMessageBoxA)*iatentry;
// Change the IAT entry to point to our function
DWORD oldprotect;
VirtualProtect(iatentry, 4, PAGE_EXECUTE_READWRITE, &oldprotect);
*iatentry = (DWORD)&hMessageBoxA;
VirtualProtect(iatentry, 4, oldprotect, &oldprotect);
return 0;
}
thunk++;
}
iat++;
}
return 0;
},
0, 0, 0);
}
return TRUE;
}
That’s it. All that’s left is to inject hello.exe with this DLL and the MessageBox
function should be altered creepily.
That’s how it’s done; very simple and straightforward. If you’re fancy enough, you can do hooks that involve network connections and detour the network traffic that a program produces.
Thanks for reading, and have a great weekend.
Go!
-BowTiedCrawfish