ethical.blue Magazine

// Cybersecurity clarified.

API Hooking with Microsoft Detours (Example)

2022-04-13   Dawid Farbaniec
...

Introduction

Function hooks (API hooking) can have many different uses. One of them is, for example, the ability to monitor called functions by a specified program. This partially allows you to analyze the behavior of the application, which is "what the program does". The general art of intercepting function calls is called API hooking. There are also negative applications of this type of mechanism. It can also be found in malware. Hooks allow to intercept a function call and e.g. falsify its result. Imagine a function that displays a process list and the arguments (process list) modified by hooking. This is how VXer can hide malicious processes. However, this post will introduce the ethical use of API hooking. For easy setup there is Microsoft Detours used.

When intercepting a function call with Microsoft Detours, the flow is routed through added function called trampoline.

Simple Working Example 🧪

The presented example requires the creation of two projects:
Injector program (injector.exe) - starts the process to be monitored and injects the .dll into it.
Injected library (library.dll) - intercepts calls to defined API functions.

In short, the injector.exe program works by creating a new process for the selected application and injecting a dynamic library (.dll) into it, the task of which is to intercept calls to specific API functions.

The next listing shows the code of a dynamic library that is injected into the process. It includes, among others prototypes of intercepted functions and definitions in which we can define additional actions, e.g. saving function arguments to the report file or even their modification.

A detailed description of the individual functions of the Detours library can be found in the documentation:
https://github.com/microsoft/detours/wiki

Adding more functions to be monitored consists in placing their prototypes in the same way as:
VOID(WINAPI* pSleep)(DWORD) = Sleep;

VOID WINAPI MySleep(DWORD dwMilliseconds);

And adding the trampoline function:
VOID WINAPI MySleep(DWORD dwMilliseconds)

{
    FILE* pLogFile;

    setlocale(LC_CTYPE, "");

    _wfopen_s(&pLogFile, L"log.txt", L"a+");

    fwprintf(pLogFile, L"Monitorowany program zasnÄ…Å‚ (funkcja Sleep) na %i milisekund.", dwMilliseconds);

    fclose(pLogFile);

    return pSleep(dwMilliseconds);
}

And finally, adding calls to DetourAttach() and DetourDetach() for new functions to be intercepted.

DLL injection program (injector.exe)
#include <Windows.h>

#include "..\detours\detours.h"

#pragma comment(lib, "..\x64\Debug\detours.lib")

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
    _In_ PSTR szCmdLine, _In_ int iCmdShow)
{
    STARTUPINFOA si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_SHOW;
    ZeroMemory(&pi, sizeof(pi));

    BOOL injected = FALSE;

    injected = DetourCreateProcessWithDllExA(
        "prog1.exe", NULL, NULL, NULL, TRUE,
        CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED,
        NULL, NULL, &si, &pi, "library.dll", NULL);

    if (injected == TRUE)
    {
        MessageBox(0, L"Biblioteka DLL zostaÅ‚a wstrzykniÄ™ta w proces.",
            L"Informacja", MB_OK + MB_ICONINFORMATION);
    }
    else
    {
        MessageBox(0, L"Nie udaÅ‚o siÄ™ wstrzyknąć biblioteki DLL.",
            L"BÅ‚Ä…d", MB_OK + MB_ICONERROR);
    }

    ResumeThread(pi.hThread);

    WaitForSingleObject(pi.hProcess, INFINITE);

    CloseHandle(&si);
    CloseHandle(&pi);

    return EXIT_SUCCESS;
}

Injected library (library.dll)
#include <Windows.h>

#include <cstdio>
#include <clocale>
#include "..\detours\detours.h"

#pragma comment(lib, "..\x64\Debug\detours.lib")

VOID(WINAPI* pSleep)(DWORD) = Sleep;
VOID WINAPI MySleep(DWORD dwMilliseconds);

VOID WINAPI MySleep(DWORD dwMilliseconds)
{
    FILE* pLogFile;

    setlocale(LC_CTYPE, "");

    _wfopen_s(&pLogFile, L"log.txt", L"a+");

    if (pLogFile != NULL)
    {
        fwprintf(pLogFile, L"Monitorowany program zasnÄ…Å‚ (funkcja Sleep) na %i milisekund.", dwMilliseconds);

        fclose(pLogFile);
    }

    return pSleep(dwMilliseconds);
}

extern "C" __declspec(dllexport) void nothing(void) {
    return;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if (DetourIsHelperProcess())
        return TRUE;

    if (fdwReason == DLL_PROCESS_ATTACH)
    {
        DetourRestoreAfterWith();

        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());

        DetourAttach(&(PVOID&)pSleep, MySleep);
        DetourTransactionCommit();
    }
    else if (fdwReason == DLL_PROCESS_DETACH)
    {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());

        DetourDetach(&(PVOID&)pSleep, MySleep);
        DetourTransactionCommit();
    }

    return TRUE;
}

Final Words

Thank you for the time given to reading this text.

Bibliography

https://github.com/ethicalblue/Microsoft-Detours-Example [access: 2022-04-13]
https://github.com/microsoft/Detours [access: 2022-04-13]

ethical.blue Appz

Categories

Archives


Donate to ethical.blue Magazine website maintenance with cryptocurrency or PayPal.

aspnet
Connections: 19

bitcoin diesel