Salta ai contenuti

Detours

Detours is a software package developed by Microsoft for intercepting Win32 API function calls. It enables developers and security researchers to monitor, modify, and redirect function behavior at runtime through inline code patching and trampolining.

Overview

Detours allows you to:

  • Hook existing Win32 API functions
  • Redirect function calls to custom handlers
  • Intercept and modify function behavior
  • Monitor API usage patterns
  • Perform DLL injection at runtime
  • Create detour chains for multiple hooks

Installation

From Microsoft

# Download Detours from Microsoft Research
# https://www.microsoft.com/en-us/download/details.aspx?id=52172

# Extract the archive
Expand-Archive -Path detours.zip -DestinationPath C:\detours

# Build library
cd C:\detours
msbuild src\detours.sln /p:Configuration=Release /p:Platform=x64

# Add to project include/lib paths
$DetourPath = "C:\detours"
# Include: $DetourPath\include
# Lib: $DetourPath\lib.X64

Building from Source

# Clone or download the source
cd detours/src

# Build with Visual Studio
msbuild detours.sln /p:Configuration=Release

# Or use nmake
nmake

Basic Function Hooking

Simple API Hook Example

#include <detours.h>
#include <windows.h>
#include <stdio.h>

#pragma comment(lib, "detours.lib")

// Original function pointer
static LPVOID (WINAPI *Real_HeapAlloc)(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes) = HeapAlloc;

// Detour function
LPVOID WINAPI Mine_HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes)
{
    printf("[HOOK] HeapAlloc called with size: %zu\n", dwBytes);
    return Real_HeapAlloc(hHeap, dwFlags, dwBytes);
}

// Attach hook
void AttachHook()
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)Real_HeapAlloc, Mine_HeapAlloc);
    DetourTransactionCommit();
}

// Detach hook
void DetachHook()
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourDetach(&(PVOID&)Real_HeapAlloc, Mine_HeapAlloc);
    DetourTransactionCommit();
}

Hooking Registry Functions

#include <detours.h>
#include <winreg.h>
#include <stdio.h>

#pragma comment(lib, "detours.lib")

// Hook RegOpenKeyEx
static LONG (WINAPI *Real_RegOpenKeyEx)(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions,
                                        REGSAM samDesired, PHKEY phkResult) = RegOpenKeyExA;

LONG WINAPI Mine_RegOpenKeyEx(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions,
                              REGSAM samDesired, PHKEY phkResult)
{
    printf("[HOOK] RegOpenKeyEx: %s\n", lpSubKey ? lpSubKey : "(null)");
    return Real_RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, phkResult);
}

void SetupRegistryHook()
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)Real_RegOpenKeyEx, Mine_RegOpenKeyEx);
    DetourTransactionCommit();
}

Hooking File API Functions

#include <detours.h>
#include <windows.h>
#include <stdio.h>

#pragma comment(lib, "detours.lib")

// Hook CreateFileA
static HANDLE (WINAPI *Real_CreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess,
    DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) = CreateFileA;

HANDLE WINAPI Mine_CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
    LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
    printf("[HOOK] CreateFileA: %s\n", lpFileName);

    // Log sensitive file access
    if (strstr(lpFileName, "password") || strstr(lpFileName, "config"))
    {
        printf("[ALERT] Sensitive file access detected!\n");
    }

    return Real_CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
        dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}

DLL Injection

DLL Injection Module

// injected.dll - Code that runs in target process
#include <windows.h>
#include <stdio.h>

BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        // Create log file in target process
        FILE* log = fopen("C:\\temp\\injection.log", "a");
        fprintf(log, "[*] DLL Injected into process\n");
        fclose(log);

        // Set up hooks here
        SetupAllHooks();
    }
    else if (fdwReason == DLL_PROCESS_DETACH)
    {
        FILE* log = fopen("C:\\temp\\injection.log", "a");
        fprintf(log, "[*] DLL Detached from process\n");
        fclose(log);
    }

    return TRUE;
}

Injector Program

#include <detours.h>
#include <windows.h>
#include <stdio.h>

#pragma comment(lib, "detours.lib")

// Function to inject DLL into target process
BOOL InjectDLL(DWORD dwProcessId, const char* dllPath)
{
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if (!hProcess)
    {
        printf("[-] Failed to open process: %d\n", GetLastError());
        return FALSE;
    }

    // Allocate memory in target process
    SIZE_T dllPathLen = strlen(dllPath) + 1;
    LPVOID lpBuffer = VirtualAllocEx(hProcess, NULL, dllPathLen,
                                     MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (!lpBuffer)
    {
        printf("[-] Failed to allocate memory\n");
        CloseHandle(hProcess);
        return FALSE;
    }

    // Write DLL path to target process
    if (!WriteProcessMemory(hProcess, lpBuffer, (void*)dllPath, dllPathLen, NULL))
    {
        printf("[-] Failed to write process memory\n");
        VirtualFreeEx(hProcess, lpBuffer, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return FALSE;
    }

    // Create remote thread to load DLL
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,
        (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"),
        lpBuffer, 0, NULL);

    if (!hThread)
    {
        printf("[-] Failed to create remote thread\n");
        VirtualFreeEx(hProcess, lpBuffer, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        return FALSE;
    }

    // Wait for thread completion
    WaitForSingleObject(hThread, INFINITE);

    // Cleanup
    VirtualFreeEx(hProcess, lpBuffer, 0, MEM_RELEASE);
    CloseHandle(hThread);
    CloseHandle(hProcess);

    printf("[+] DLL injected successfully\n");
    return TRUE;
}

API Monitoring

Network API Monitoring

#include <detours.h>
#include <winsock2.h>
#include <stdio.h>

#pragma comment(lib, "detours.lib")
#pragma comment(lib, "ws2_32.lib")

// Hook socket operations
static int (WINAPI *Real_send)(SOCKET s, const char* buf, int len, int flags) = send;

int WINAPI Mine_send(SOCKET s, const char* buf, int len, int flags)
{
    printf("[HOOK] send() called with %d bytes\n", len);

    // Log first 100 bytes
    if (len > 0)
    {
        printf("[DATA] ");
        for (int i = 0; i < (len < 100 ? len : 100); i++)
        {
            printf("%02x ", (unsigned char)buf[i]);
        }
        printf("\n");
    }

    return Real_send(s, buf, len, flags);
}

Process Spawning Monitor

#include <detours.h>
#include <windows.h>
#include <stdio.h>

#pragma comment(lib, "detours.lib")

static BOOL (WINAPI *Real_CreateProcessA)(LPCSTR lpApplicationName, LPSTR lpCommandLine,
    LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
    LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) = CreateProcessA;

BOOL WINAPI Mine_CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine,
    LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
    LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
{
    FILE* log = fopen("C:\\temp\\process_monitor.log", "a");
    fprintf(log, "[*] CreateProcess called:\n");
    fprintf(log, "    Application: %s\n", lpApplicationName ? lpApplicationName : "(null)");
    fprintf(log, "    Command Line: %s\n", lpCommandLine ? lpCommandLine : "(null)");
    fclose(log);

    return Real_CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes,
        lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
        lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
}

Advanced Techniques

Detour Chains

// Multiple detours on same function
static int (WINAPI *Real_send)(SOCKET s, const char* buf, int len, int flags) = send;
static int (WINAPI *ChainedSend)(SOCKET s, const char* buf, int len, int flags) = send;

int WINAPI Mine_send_v1(SOCKET s, const char* buf, int len, int flags)
{
    printf("[DETOUR 1] Logging\n");
    return ChainedSend(s, buf, len, flags);
}

int WINAPI Mine_send_v2(SOCKET s, const char* buf, int len, int flags)
{
    printf("[DETOUR 2] Analyzing\n");
    return Real_send(s, buf, len, flags);
}

void AttachChain()
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());

    // First detour
    ChainedSend = Real_send;
    DetourAttach(&(PVOID&)Real_send, Mine_send_v1);
    DetourAttach(&(PVOID&)ChainedSend, Mine_send_v2);

    DetourTransactionCommit();
}

Function Parameter Modification

// Modify function behavior
static HANDLE (WINAPI *Real_CreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess,
    DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) = CreateFileA;

HANDLE WINAPI Mine_CreateFileA_Protective(LPCSTR lpFileName, DWORD dwDesiredAccess,
    DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
    // Block access to protected files
    if (strstr(lpFileName, "protected"))
    {
        SetLastError(ERROR_ACCESS_DENIED);
        return INVALID_HANDLE_VALUE;
    }

    return Real_CreateFileA(lpFileName, dwDesiredAccess, dwShareMode,
        lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}

Compilation and Deployment

Building a Detour Hook DLL

# Compile with Detours library
cl.exe /D_WINDOWS /D_USRDLL /D_WINDLL /I"C:\detours\include" ^
  myhooks.cpp ^
  /link /DLL /LIBPATH:"C:\detours\lib.X64" detours.lib

# Result: myhooks.dll

Testing Detours

// Test program that hooks itself
#include <detours.h>
#include <stdio.h>

static int (WINAPI *Real_printf)(const char*, ...) = printf;

int WINAPI Mine_printf(const char* fmt, ...)
{
    // Intercept printf calls
    return Real_printf("[HOOKED] %s", fmt);
}

int main()
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)Real_printf, Mine_printf);
    DetourTransactionCommit();

    printf("This will be hooked\n");
    return 0;
}

Detection and Defense

Detecting Detours Usage

  • Monitor for API hook patterns in memory
  • Check for inline code patches
  • Monitor CreateRemoteThread + LoadLibrary patterns
  • Analyze DLL imports for detours.lib usage

Preventing Detours Injection

# Disable DLL injection at system level
Set-MpPreference -DisableRealtimeMonitoring $true
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\MiSvc" -Name "Start" -Value 4

# Monitor suspicious thread creation
Get-WinEvent -LogName Security | Where-Object {$_.Id -eq 8