使用微軟Detours庫進行DLL注入

lyshark發表於2024-08-20

Detours 是微軟開發的一個強大的 Windows API 鉤子庫,用於監視和攔截函式呼叫。它廣泛應用於微軟產品團隊和眾多獨立軟體開發中,旨在無需修改原始程式碼的情況下實現函式攔截和修改。本篇文章旨在幫助開發者更好地理解和應用Detours庫進行DLL注入操作,從而實現對目標程序的高效控制和管理。無論您是剛接觸Detours的新手,還是希望深入瞭解其高階功能的老手,這篇文章都將提供有價值的參考。

通常情況下Detours庫只會用於函式掛鉤,但實際上Detours庫不僅可以攔截函式,還提供了對動態連結庫的注入功能。本章將詳細講解每個注入函式的使用方法、引數和實際應用。

DetourCreateProcessWithDllA

該函式用於建立一個新程序並在建立時注入一個DLL動態連結庫檔案。其重要引數僅有兩個,引數1用於指定被注入程式路徑,引數11用於指定DLL檔案路徑。

函式原型

BOOL DetourCreateProcessWithDllA(
    LPCSTR lpApplicationName,       // 被注入程式路徑
    LPSTR lpCommandLine,            // 命令列引數
    LPSECURITY_ATTRIBUTES lpProcessAttributes,  // 程序安全屬性
    LPSECURITY_ATTRIBUTES lpThreadAttributes,   // 執行緒安全屬性
    BOOL bInheritHandles,           // 是否繼承控制代碼
    DWORD dwCreationFlags,          // 建立標誌
    LPVOID lpEnvironment,           // 環境變數
    LPCSTR lpCurrentDirectory,      // 當前目錄
    LPSTARTUPINFOA lpStartupInfo,   // 啟動資訊
    LPPROCESS_INFORMATION lpProcessInformation, // 程序資訊
    LPCSTR lpDllName,               // DLL 檔案路徑
    PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA // 自定義程序建立例程
);

使用示例

以下程式碼示例展示瞭如何使用 DetourCreateProcessWithDllA 函式,在啟動 Win32Project.exe 程序時將 hook.dll 注入到該程序中。

#include <windows.h>
#include <iostream>
#include "detours.h"

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

int main(int argc, char *argv[])
{
    STARTUPINFOA si = { sizeof(si) };
    PROCESS_INFORMATION pi;
    const char* exePath = "D://Win32Project.exe";
    const char* dllPath = "D://hook.dll";

    if (DetourCreateProcessWithDllA(
        exePath,
        NULL,
        NULL,
        NULL,
        TRUE,
        CREATE_DEFAULT_ERROR_MODE,
        NULL,
        NULL,
        &si,
        &pi,
        dllPath,
        NULL
    )) {
        printf("dwProcessId = %d \n", pi.dwProcessId);
        printf("dwThreadId = %d \n", pi.dwThreadId);
        printf("hProcess = %d \n", pi.hProcess);
        printf("hThread = %d \n", pi.hThread);

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    } else {
        printf("DLL 注入失敗,錯誤碼: %d\n", GetLastError());
    }

    system("pause");
    return 0;
}

DetourCreateProcessWithDllExA

DetourCreateProcessWithDllExA是DetourCreateProcessWithDllA的擴充套件版本,提供了更多的靈活性和控制。

函式原型

BOOL DetourCreateProcessWithDllExA(
    LPCSTR lpApplicationName,       // 被注入程式路徑
    LPSTR lpCommandLine,            // 命令列引數
    LPSECURITY_ATTRIBUTES lpProcessAttributes,  // 程序安全屬性
    LPSECURITY_ATTRIBUTES lpThreadAttributes,   // 執行緒安全屬性
    BOOL bInheritHandles,           // 是否繼承控制代碼
    DWORD dwCreationFlags,          // 建立標誌
    LPVOID lpEnvironment,           // 環境變數
    LPCSTR lpCurrentDirectory,      // 當前目錄
    LPSTARTUPINFOA lpStartupInfo,   // 啟動資訊
    LPPROCESS_INFORMATION lpProcessInformation, // 程序資訊
    LPCSTR lpDllName,               // DLL 檔案路徑
    PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA, // 自定義程序建立例程
    PVOID pContext                  // 自定義上下文
);

使用示例

以下程式碼示例展示瞭如何使用 DetourCreateProcessWithDllExA 函式,在啟動 Win32Project.exe 程序時注入 hook.dll,並透過自定義程序建立例程新增自定義邏輯。

#include <windows.h>
#include <iostream>
#include "detours.h"

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

// 自定義的程序建立例程
BOOL WINAPI MyCreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine,
	LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
	BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
	LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
{
	// 自定義邏輯
	printf("自定義程序建立例程被呼叫\n");

	// 呼叫原函式
	return CreateProcessA(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes,
		bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
}

int main(int argc, char *argv[])
{
	STARTUPINFOA si = { sizeof(si) };
	PROCESS_INFORMATION pi;
	const char* exePath = "D://Win32Project.exe";
	const char* dllPath = "D://hook.dll";

	if (DetourCreateProcessWithDllExA(
		exePath,
		NULL,
		NULL,
		NULL,
		TRUE,
		CREATE_DEFAULT_ERROR_MODE,
		NULL,
		NULL,
		&si,
		&pi,
		dllPath,
		MyCreateProcessA
		))
	{
		printf("dwProcessId = %d \n", pi.dwProcessId);
		printf("dwThreadId = %d \n", pi.dwThreadId);
		printf("hProcess = %d \n", pi.hProcess);
		printf("hThread = %d \n", pi.hThread);

		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
	}
	else {
		printf("DLL 注入失敗,錯誤碼: %d\n", GetLastError());
	}

	system("pause");
	return 0;
}

DetourCreateProcessWithDllsA

DetourCreateProcessWithDllsA函式與DetourCreateProcessWithDllA和DetourCreateProcessWithDllExA的使用方法類似,但它允許在程序建立時將多個 DLL 檔案注入到目標程序中。

函式原型

BOOL DetourCreateProcessWithDllsA(
    LPCSTR lpApplicationName,       // 被注入程式路徑
    LPSTR lpCommandLine,            // 命令列引數
    LPSECURITY_ATTRIBUTES lpProcessAttributes,  // 程序安全屬性
    LPSECURITY_ATTRIBUTES lpThreadAttributes,   // 執行緒安全屬性
    BOOL bInheritHandles,           // 是否繼承控制代碼
    DWORD dwCreationFlags,          // 建立標誌
    LPVOID lpEnvironment,           // 環境變數
    LPCSTR lpCurrentDirectory,      // 當前目錄
    LPSTARTUPINFOA lpStartupInfo,   // 啟動資訊
    LPPROCESS_INFORMATION lpProcessInformation, // 程序資訊
    DWORD nDlls,                    // DLL 的數量
    LPCSTR *rlpDlls,                // DLL 檔案路徑陣列
    PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA // 自定義程序建立例程
);

使用示例

以下程式碼示例展示瞭如何使用 DetourCreateProcessWithDllsA 函式,在啟動 Win32Project.exe 程序時注入多個 DLL 檔案。

#include <windows.h>
#include <iostream>
#include "detours.h"

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

int main(int argc, char *argv[])
{
    STARTUPINFOA si = { sizeof(si) };
    PROCESS_INFORMATION pi;
    const char* exePath = "D://Win32Project.exe";

    const char* dlls[] = {
        "D://hook1.dll",
        "D://hook2.dll"
    };

    DWORD nDlls = sizeof(dlls) / sizeof(dlls[0]);

    // 開始注入
    if (DetourCreateProcessWithDllsA(
        exePath,
        NULL,
        NULL,
        NULL,
        TRUE,
        CREATE_DEFAULT_ERROR_MODE,
        NULL,
        NULL,
        &si,
        &pi,
        nDlls,
        dlls,
        NULL
    )) {
        printf("dwProcessId = %d \n", pi.dwProcessId);
        printf("dwThreadId = %d \n", pi.dwThreadId);
        printf("hProcess = %d \n", pi.hProcess);
        printf("hThread = %d \n", pi.hThread);

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    } else {
        printf("DLL 注入失敗,錯誤碼: %d\n", GetLastError());
    }

    system("pause");
    return 0;
}

相關文章