You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DLL注入后拦截目标进程LoadLibrary调用及Detour失效排查

问题描述

通过CreateRemoteThread将DLL注入目标进程后,希望该DLL拦截目标进程发起的LoadLibraryA/W调用,仅获取待加载DLL的完整路径及名称,不修改原调用行为。尝试用Detour库拦截LoadLibraryW后弹窗始终未触发,观察Procmon记录到的操作是CreateFile而非LoadLibrary,拦截CreateFileA也无效,求原因。

附上相关代码:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <stdio.h>
#include <windows.h>
#include "detours.h"

// Target pointer for the uninstrumented LoadLibraryW API.
//
static HMODULE(WINAPI* TrueLoadLibrary)(LPCWSTR lpLibFileName) = LoadLibraryW;

// Detour function that replaces the LoadLibrary API.
//
HMODULE WINAPI DetouredLoadLibrary(LPCWSTR lpLibFileName)
{
    HMODULE res = TrueLoadLibrary(lpLibFileName);
    MessageBoxW(NULL, lpLibFileName, L"Detoured!", MB_OK | MB_ICONEXCLAMATION);
    return res;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
        if (DetourIsHelperProcess()) {
            return TRUE;
        }

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

            DetourTransactionBegin();
            DetourUpdateThread(GetCurrentThread());
            DetourAttach(&(PVOID&)TrueLoadLibrary, DetouredLoadLibrary);
            DetourTransactionCommit();
        }
        else if (ul_reason_for_call == DLL_PROCESS_DETACH) {
            DetourTransactionBegin();
            DetourUpdateThread(GetCurrentThread());
            DetourDetach(&(PVOID&)TrueLoadLibrary, DetouredLoadLibrary);
            DetourTransactionCommit();
        }

        return TRUE;
    }
问题原因与解决方案

核心原因分析

  • 拦截API范围不全:你只拦截了LoadLibraryW,但目标进程可能实际调用的是LoadLibraryA、LoadLibraryExA/W,甚至底层的LdrLoadDll(ntdll.dll中负责DLL加载的核心函数)。Procmon记录的CreateFile是LoadLibrary内部的文件操作步骤,直接拦截CreateFile会因调用层级过多、参数无法对应而失效。
  • DllMain中执行Detour的局限性:DLL_PROCESS_ATTACH时仅对当前线程执行DetourUpdateThread,无法覆盖进程中所有线程;且DllMain属于加载临界区,执行Hook操作容易引发死锁或加载顺序问题。
  • 弹窗的兼容性问题:若目标进程是无窗口服务、控制台进程,或当前线程处于非UI环境,MessageBoxW可能无法正常显示,导致你误以为拦截未生效。

修正方案与代码示例

  1. 扩展拦截API集合:覆盖所有常见的DLL加载API,包括LoadLibraryA/W、LoadLibraryExA/W;必要时可追加拦截LdrLoadDll。
  2. 在独立线程中初始化Detour:避免在DllMain中执行Hook操作,创建单独线程完成初始化,降低死锁风险。
  3. 替换弹窗为文件日志:用日志文件记录加载路径,规避UI环境限制导致的误判。

修正后的代码:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <stdio.h>
#include <windows.h>
#include "detours.h"

// 原始函数指针
static HMODULE(WINAPI* TrueLoadLibraryA)(LPCSTR lpLibFileName) = LoadLibraryA;
static HMODULE(WINAPI* TrueLoadLibraryW)(LPCWSTR lpLibFileName) = LoadLibraryW;
static HMODULE(WINAPI* TrueLoadLibraryExA)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) = LoadLibraryExA;
static HMODULE(WINAPI* TrueLoadLibraryExW)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) = LoadLibraryExW;

// 日志写入函数
void LogDllLoad(const wchar_t* dllPath) {
    FILE* fp = _wfopen(L"dll_load_log.txt", L"a");
    if (fp) {
        fwprintf(fp, L"Loaded DLL: %s\n", dllPath);
        fclose(fp);
    }
}

void LogDllLoadA(const char* dllPath) {
    wchar_t wPath[MAX_PATH] = {0};
    MultiByteToWideChar(CP_ACP, 0, dllPath, -1, wPath, MAX_PATH);
    LogDllLoad(wPath);
}

// Hook函数实现
HMODULE WINAPI DetouredLoadLibraryA(LPCSTR lpLibFileName) {
    LogDllLoadA(lpLibFileName);
    return TrueLoadLibraryA(lpLibFileName);
}

HMODULE WINAPI DetouredLoadLibraryW(LPCWSTR lpLibFileName) {
    LogDllLoad(lpLibFileName);
    return TrueLoadLibraryW(lpLibFileName);
}

HMODULE WINAPI DetouredLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) {
    LogDllLoadA(lpLibFileName);
    return TrueLoadLibraryExA(lpLibFileName, hFile, dwFlags);
}

HMODULE WINAPI DetouredLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) {
    LogDllLoad(lpLibFileName);
    return TrueLoadLibraryExW(lpLibFileName, hFile, dwFlags);
}

// 初始化Hook的线程函数
DWORD WINAPI InitDetours(LPVOID param) {
    DetourRestoreAfterWith();

    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    // 附加所有需要拦截的函数
    DetourAttach(&(PVOID&)TrueLoadLibraryA, DetouredLoadLibraryA);
    DetourAttach(&(PVOID&)TrueLoadLibraryW, DetouredLoadLibraryW);
    DetourAttach(&(PVOID&)TrueLoadLibraryExA, DetouredLoadLibraryExA);
    DetourAttach(&(PVOID&)TrueLoadLibraryExW, DetouredLoadLibraryExW);
    LONG error = DetourTransactionCommit();

    if (error != NO_ERROR) {
        FILE* fp = _wfopen(L"detour_error.txt", L"w");
        if (fp) {
            fwprintf(fp, L"Detour commit failed: %ld\n", error);
            fclose(fp);
        }
    }

    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    if (DetourIsHelperProcess()) {
        return TRUE;
    }

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        // 创建独立线程执行Hook初始化
        CreateThread(NULL, 0, InitDetours, NULL, 0, NULL);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        // 卸载Hook
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(&(PVOID&)TrueLoadLibraryA, DetouredLoadLibraryA);
        DetourDetach(&(PVOID&)TrueLoadLibraryW, DetouredLoadLibraryW);
        DetourDetach(&(PVOID&)TrueLoadLibraryExA, DetouredLoadLibraryExA);
        DetourDetach(&(PVOID&)TrueLoadLibraryExW, DetouredLoadLibraryExW);
        DetourTransactionCommit();
        break;
    }
    return TRUE;
}

内容的提问来源于stack exchange,提问作者Dlionis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:15:39