✍️
Red Teaming Experiments
  • What is this iRed.team?
  • Pinned
    • Pentesting Cheatsheets
      • SQL Injection & XSS Playground
    • Active Directory & Kerberos Abuse
      • From Domain Admin to Enterprise Admin
      • Kerberoasting
      • Kerberos: Golden Tickets
      • Kerberos: Silver Tickets
      • AS-REP Roasting
      • Kerberoasting: Requesting RC4 Encrypted TGS when AES is Enabled
      • Kerberos Unconstrained Delegation
      • Kerberos Constrained Delegation
      • Kerberos Resource-based Constrained Delegation: Computer Object Take Over
      • Domain Compromise via DC Print Server and Kerberos Delegation
      • DCShadow - Becoming a Rogue Domain Controller
      • DCSync: Dump Password Hashes from Domain Controller
      • PowerView: Active Directory Enumeration
      • Abusing Active Directory ACLs/ACEs
      • Privileged Accounts and Token Privileges
      • From DnsAdmins to SYSTEM to Domain Compromise
      • Pass the Hash with Machine$ Accounts
      • BloodHound with Kali Linux: 101
      • Backdooring AdminSDHolder for Persistence
      • Active Directory Enumeration with AD Module without RSAT or Admin Privileges
      • Enumerating AD Object Permissions with dsacls
      • Active Directory Password Spraying
  • offensive security
    • Red Team Infrastructure
      • HTTP Forwarders / Relays
      • SMTP Forwarders / Relays
      • Phishing with Modlishka Reverse HTTP Proxy
      • Automating Red Team Infrastructure with Terraform
      • Cobalt Strike 101
      • Powershell Empire 101
      • Spiderfoot 101 with Kali using Docker
    • Initial Access
      • Password Spraying Outlook Web Access: Remote Shell
      • Phishing with MS Office
        • Phishing: XLM / Macro 4.0
        • T1173: Phishing - DDE
        • T1137: Phishing - Office Macros
        • Phishing: OLE + LNK
        • Phishing: Embedded Internet Explorer
        • Phishing: .SLK Excel
        • Phishing: Replacing Embedded Video with Bogus Payload
        • Inject Macros from a Remote Dotm Template
        • Bypassing Parent Child / Ancestry Detections
        • Phishing: Embedded HTML Forms
      • Phishing with GoPhish and DigitalOcean
      • Forced Authentication
      • NetNTLMv2 hash stealing using Outlook
    • Code Execution
      • T1117: regsvr32
      • T1170: MSHTA
      • T1196: Control Panel Item
      • Executing Code as a Control Panel Item through an Exported Cplapplet Function
      • Code Execution through Control Panel Add-ins
      • T1191: CMSTP
      • T1118: InstallUtil
      • Using MSBuild to Execute Shellcode in C#
      • T1202: Forfiles Indirect Command Execution
      • Application Whitelisting Bypass with WMIC and XSL
      • Powershell Without Powershell.exe
      • Powershell Constrained Language Mode ByPass
      • Forcing Iexplore.exe to Load a Malicious DLL via COM Abuse
      • T1216: pubprn.vbs Signed Script Code Execution
    • Code & Process Injection
      • CreateRemoteThread Shellcode Injection
      • DLL Injection
      • Reflective DLL Injection
      • Shellcode Reflective DLL Injection
      • Process Doppelganging
      • Loading and Executing Shellcode From PE Resources
      • Process Hollowing and Portable Executable Relocations
      • APC Queue Code Injection
      • Early Bird APC Queue Code Injection
      • Shellcode Execution in a Local Process with QueueUserAPC and NtTestAlert
      • Shellcode Execution through Fibers
      • Shellcode Execution via CreateThreadpoolWait
      • Local Shellcode Execution without Windows APIs
      • Injecting to Remote Process via Thread Hijacking
      • SetWindowHookEx Code Injection
      • Finding Kernel32 Base and Function Addresses in Shellcode
      • Executing Shellcode with Inline Assembly in C/C++
      • Writing Custom Shellcode Encoders and Decoders
      • Backdooring PE Files with Shellcode
      • NtCreateSection + NtMapViewOfSection Code Injection
      • AddressOfEntryPoint Code Injection without VirtualAllocEx RWX
      • Module Stomping for Shellcode Injection
      • PE Injection: Executing PEs inside Remote Processes
      • API Monitoring and Hooking for Offensive Tooling
      • Windows API Hooking
      • Import Adress Table (IAT) Hooking
      • DLL Injection via a Custom .NET Garbage Collector
      • Writing and Compiling Shellcode in C
      • Injecting .NET Assembly to an Unmanaged Process
    • Defense Evasion
      • AV Bypass with Metasploit Templates and Custom Binaries
      • Evading Windows Defender with 1 Byte Change
      • Bypassing Windows Defender: One TCP Socket Away From Meterpreter and Beacon Sessions
      • Bypassing Cylance and other AVs/EDRs by Unhooking Windows APIs
      • Windows API Hashing in Malware
      • Detecting Hooked Syscalls
      • Calling Syscalls Directly from Visual Studio to Bypass AVs/EDRs
      • Retrieving ntdll Syscall Stubs from Disk at Run-time
      • Full DLL Unhooking with C++
      • Enumerating RWX Protected Memory Regions for Code Injection
      • Disabling Windows Event Logs by Suspending EventLog Service Threads
      • T1027: Obfuscated Powershell Invocations
      • Masquerading Processes in Userland via _PEB
      • Commandline Obfusaction
      • File Smuggling with HTML and JavaScript
      • T1099: Timestomping
      • T1096: Alternate Data Streams
      • T1158: Hidden Files
      • T1140: Encode/Decode Data with Certutil
      • Downloading Files with Certutil
      • T1045: Packed Binaries
      • Unloading Sysmon Driver
      • Bypassing IDS Signatures with Simple Reverse Shells
      • Preventing 3rd Party DLLs from Injecting into your Malware
      • ProcessDynamicCodePolicy: Arbitrary Code Guard (ACG)
      • Parent Process ID (PPID) Spoofing
      • Executing C# Assemblies from Jscript and wscript with DotNetToJscript
    • Enumeration and Discovery
      • Windows Event IDs and Others for Situational Awareness
      • Enumerating COM Objects and their Methods
      • Enumerating Users without net, Services without sc and Scheduled Tasks without schtasks
      • Enumerating Windows Domains with rpcclient through SocksProxy == Bypassing Command Line Logging
      • Dump GAL from OWA
      • T1010: Application Window Discovery
      • T1087: Account Discovery & Enumeration
      • Using COM to Enumerate Hostname, Username, Domain, Network Drives
      • Detecting Sysmon on the Victim Host
    • Privilege Escalation
      • T1134: Primary Access Token Manipulation
      • Windows NamedPipes 101 + Privilege Escalation
      • T1038: DLL Hijacking
      • T1108: WebShells
      • T1183: Image File Execution Options Injection
      • Unquoted Service Paths
      • Pass The Hash: Privilege Escalation with Invoke-WMIExec
      • Environment Variable $Path Interception
      • Weak Service Permissions
    • Credential Access & Dumping
      • Dumping Credentials from Lsass Process Memory with Mimikatz
      • Dumping Lsass Without Mimikatz
      • Dumping Lsass without Mimikatz with MiniDumpWriteDump
      • Dumping Hashes from SAM via Registry
      • Dumping SAM via esentutl.exe
      • Dumping LSA Secrets
      • Dumping and Cracking mscash - Cached Domain Credentials
      • Dumping Domain Controller Hashes Locally and Remotely
      • Dumping Domain Controller Hashes via wmic and Vssadmin Shadow Copy
      • Network vs Interactive Logons
      • Reading DPAPI Encrypted Secrets with Mimikatz and C++
      • T1214: Credentials in Registry
      • T1174: Password Filter
      • Forcing WDigest to Store Credentials in Plaintext
      • Dumping Delegated Default Kerberos and NTLM Credentials w/o Touching Lsass
      • Intercepting Logon Credentials via Custom Security Support Provider and Authentication Packages
      • Pulling Web Application Passwords by Hooking HTML Input Fields
      • Intercepting Logon Credentials by Hooking msv1_0!SpAcceptCredentials
      • Credentials Collection via CredUIPromptForCredentials
    • Lateral Movement
      • T1028: WinRM for Lateral Movement
      • WinRS for Lateral Movement
      • T1047: WMI for Lateral Movement
      • T1076: RDP Hijacking for Lateral Movement with tscon
      • T1051: Shared Webroot
      • T1175: Lateral Movement via DCOM
      • WMI + MSI Lateral Movement
      • Lateral Movement via Service Configuration Manager
      • Lateral Movement via SMB Relaying
      • WMI + NewScheduledTaskAction Lateral Movement
      • WMI + PowerShell Desired State Configuration Lateral Movement
      • Simple TCP Relaying with NetCat
      • Empire Shells with NetNLTMv2 Relaying
      • Lateral Movement with Psexec
      • From Beacon to Interactive RDP Session
      • SSH Tunnelling / Port Forwarding
      • Lateral Movement via WMI Event Subscription
      • Lateral Movement via DLL Hijacking
      • Lateral Movement over headless RDP with SharpRDP
      • ShadowMove: Lateral Movement by Duplicating Existing Sockets
    • Persistence
      • DLL Proxying for Persistence
      • T1053: Schtask
      • T1035: Service Execution
      • T1015: Sticky Keys
      • T1136: Create Account
      • T1013: AddMonitor()
      • T1128: NetSh Helper DLL
      • T1084: Abusing Windows Managent Instrumentation
        • WMI as a Data Storage
      • Windows Logon Helper
      • Hijacking Default File Extension
      • Persisting in svchost.exe with a Service DLL
      • Modifying .lnk Shortcuts
      • T1180: Screensaver Hijack
      • T1138: Application Shimming
      • T1197: BITS Jobs
      • T1122: COM Hijacking
      • T1198: SIP & Trust Provider Hijacking
      • T1209: Hijacking Time Providers
      • T1130: Installing Root Certificate
      • Powershell Profile Persistence
      • RID Hijacking
      • Word Library Add-Ins
      • Office Templates
    • Exfiltration
      • Powershell Payload Delivery via DNS using Invoke-PowerCloud
  • reversing, forensics & misc
    • Windows Internals
      • Configuring Kernel Debugging Environment with kdnet and WinDBG Preview
      • Compiling a Simple Kernel Driver, DbgPrint, DbgView
      • Loading Windows Kernel Driver for Debugging
      • Subscribing to Process Creation, Thread Creation and Image Load Notifications from a Kernel Driver
      • Listing Open Handles and Finding Kernel Object Addresses
      • Sending Commands From Your Userland Program to Your Kernel Driver using IOCTL
      • Windows Kernel Drivers 101
      • x64 Calling Convention: Stack Frame
      • System Service Descriptor Table - SSDT
      • Interrupt Descriptor Table - IDT
      • Token Abuse for Privilege Escalation in Kernel
      • Manipulating ActiveProcessLinks to Hide Processes in Userland
      • ETW: Event Tracing for Windows 101
      • Exploring Injected Threads
      • Parsing PE File Headers with C++
      • Instrumenting Windows APIs with Frida
      • Exploring Process Environment Block
    • Cloud
      • AWS Accounts, Users, Groups, Roles, Policies
    • Neo4j
    • Dump Virtual Box Memory
    • AES Encryption Using Crypto++ .lib in Visual Studio C++
    • Reversing Password Checking Routine
Powered by GitBook
On this page
  • Overview
  • Walkthrough
  • Code
  • Demo
  • References

Was this helpful?

  1. offensive security
  2. Code & Process Injection

Import Adress Table (IAT) Hooking

PreviousWindows API HookingNextDLL Injection via a Custom .NET Garbage Collector

Last updated 4 years ago

Was this helpful?

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:

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.

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.

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

  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:

Code

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

#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:

Before IAT manipulation, MessageBoxA points to 0x00007ffe78071d30:

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

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

Now, our hookedMessageBox is located at 0x00007ff396d5440:

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

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:

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

References

More about PE parsing in

More about Import Address Table parsing in

Parsing PE File Headers with C++
Parsing PE File Headers with C++
Reflective DLL Injection
Windows API Hooking
Reflective DLL Injection
IAT table, CFF Explorer
Line 58 in provided code - MessageBoxA is located at 0x00007ffe78071d30 before hooking
RVA of the function MessageBoxA
0x00007FF69C0371D0 points to MessageBoxA at 0x00007ffe78071d30