【问题标题】:Why do the hooking libraries work only occasionally for API Calls in Windows 10?为什么挂钩库仅偶尔适用于 Windows 10 中的 API 调用?
【发布时间】:2017-09-28 04:10:42
【问题描述】:

我使用了多个 Hooking 库,例如Microsoft Detours Express、Mhook 等钩住 NtWriteVirtualMemory API 调用。我编写了以下代码来挂钩 API:

    #include <string>
    #include <fstream>
    #include <process.h>
    #include <Windows.h>
    #include <detours.h>

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

    using namespace std;

    #define MAX_SIZE 10000
    char tempPath[MAX_SIZE];

    typedef LONG(NTAPI * oNtWriteVirtualMemory)(
            IN HANDLE               ProcessHandle,
            IN PVOID                BaseAddress,
            IN PVOID                Buffer,
            IN ULONG                NumberOfBytesToWrite,
            OUT PULONG              NumberOfBytesWritten OPTIONAL);

    oNtWriteVirtualMemory pNtWriteVirtualMemory = (oNtWriteVirtualMemory)GetProcAddress(GetModuleHandle(L"Ntdll.dll"), "NtWriteVirtualMemory");

    BOOL WINAPI MyNtWriteVirtualMemory(
            IN HANDLE               ProcessHandle,
            IN PVOID                BaseAddress,
            IN PVOID                Buffer,
            IN ULONG                NumberOfBytesToWrite,
            OUT PULONG              NumberOfBytesWritten OPTIONAL
        )
        {
           DWORD pidSource = GetCurrentProcessId();
           DWORD pidDestination = GetProcessId(ProcessHandle);
             if (pidSource != pidDestination)
             {
                 FILE * f1 = fopen(tempPath, "a+");
                    fprintf(f1, "inter-process write from %d to %d!\n", pidSource, pidDestination);
                    fclose(f1);
             }

          return pNtWriteVirtualMemory(ProcessHandle, BaseAddress, Buffer,umberOfBytesToWrite, NumberOfBytesWritten OPTIONAL);
        }

  BOOL APIENTRY DllMain(HMODULE hModule,
        DWORD  ul_reason_for_call,
        LPVOID lpReserved
        )
    {
        strcpy(tempPath, "C:\\Windows\\Temp\\log.txt");
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:

            try
            {
                DisableThreadLibraryCalls(hModule);

                DetourTransactionBegin();
                DetourUpdateThread(GetCurrentThread());
                DetourAttach(&(PVOID&)pNtWriteVirtualMemory, MyNtWriteVirtualMemory);
                DetourTransactionCommit();
            }
            catch (int e)
            { }
            break;
        case DLL_THREAD_ATTACH:
            try
            {
                DisableThreadLibraryCalls(hModule);

                DetourTransactionBegin();
                DetourUpdateThread(GetCurrentThread());
                DetourAttach(&(PVOID&)pNtWriteVirtualMemory, MyNtWriteVirtualMemory);
                DetourTransactionCommit();
            }
            catch (int e)
            {
            }
            break;
        case DLL_PROCESS_DETACH:

            try
            {
                DetourTransactionBegin();
                DetourUpdateThread(GetCurrentThread());
                DetourDetach(&(PVOID&)pNtWriteVirtualMemory, MyNtWriteVirtualMemory);
                DetourTransactionCommit();
            }
            catch (int e)
            {
            }
            break;
        case DLL_THREAD_DETACH:
            try
            {
                DetourTransactionBegin();
                DetourUpdateThread(GetCurrentThread());
                DetourDetach(&(PVOID&)pNtWriteVirtualMemory, MyNtWriteVirtualMemory);
                DetourTransactionCommit();
            }
            catch (int e)
            {
            }
            break;
        }
        return TRUE;
    }

但是,它仅适用于某些特定情况。例如,当 API Monitor 程序将其监控 DLL 写入目标进程以监控进程的行为时,我的钩子代码运行良好,并像往常一样钩住 API Monitor 程序的 NtWriteVritualMemory 调用。此外,代码很好地挂钩了 Visual Studio 中的 API。当 Visual Studio 开始构建项目时,它会调用 NtWriteVirtualMemory 进行一些进程间写入,我可以在我的临时日志文件中看到这些调用的日志!

但是,当我编写自己的代码或构建另一个代码(例如Reflective DLL Injection)来调用 NtWriteVirtualMemory API 时,钩子根本没有检测到它。我使用 Visual Studio 2015 构建这些代码来调用 API 或挂钩它。此外,我使用AppInit_DLLs Infrastructure 使我的挂钩 DLL 成为全局用户级挂钩。

任何线索将不胜感激。

【问题讨论】:

  • 你的意思是它不是一个可靠的方法来挂钩一个 API?你为用户级挂钩提供什么?
  • (a) 我不明白这个问题。 (b) 你试过调试吗? (c) 您能否提供一个完整的工作示例? (这个东西叫“MCVE”。)
  • A) 更具体地说,在某些进程中,挂钩库不起作用,尽管它已经加载到进程中。 B)不,我没有。它是否提供了一个全球系统范围的用户级挂钩?你能解释更多吗? C) 我已将代码示例更新为完整的。
  • 单步执行挂钩代码。查看您正在挂钩的任何内容(导入表、函数开头等)的内存。变了吗?

标签: c++ winapi windows-10 hook internals


【解决方案1】:

简单:您的 DLL 仅加载到加载 user32.dll 的进程中。有些过程会。其他的不要。你说的那个没有:

并不是说钩子不起作用。你的 DLL 甚至没有加载。

此外,在线程附加中挂钩可能不是您想要的,在线程分离中取消挂钩几乎肯定不是您想要的。

【讨论】:

  • 谢谢。我以为它会被加载,因为当我在 API-Monitor 中打开它时,我在 inject.exe 的加载模块列表中看到 USER32.DLL。但是,在您回复之后,我将 LoadLibrary("user32.dll") 添加到代码中,它奏效了!!!!有什么区别?有没有其他选择,也可以在没有此限制的情况下挂钩 API?
  • 我设置了一个Sleep 代码在注入之前检查加载的模块,然后我可以看到user32.dll 在注入之前就已经加载了!而且,听说自从Windows 7 推出以来,GUI 和非GUI 进程都加载user32.dll 并支持这种机制。我自己,大约一年前在 Windows 7 上检查了这个机制,它甚至在非 GUI 进程上也能正常工作!问题可能出在其他地方!
  • 我使用了调试器而不是休眠,直到注入时才看到它加载。事实上,添加LoadLibrary 调用确实解决了您的问题,所以...
猜你喜欢
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 2022-01-17
  • 2018-09-17
  • 2014-11-18
  • 1970-01-01
  • 2013-11-01
  • 2016-08-08
相关资源
最近更新 更多