【问题标题】:Debugging .DLL Injection Issue - Breakpoint On Supposedly Executing Code Not Being Hit调试 .DLL 注入问题 - 假设执行代码未命中的断点
【发布时间】:2017-12-08 12:56:12
【问题描述】:

我已经编写了一个程序(.DLL),将被注入到 process.exe 中。

DLL 注入器代码:

Bool InjectDll(DWORD pID, const char* dllPath) {
    Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
    if (!Proc)
    {
        return false;
    }
    void* LoadLibAddr = (void*)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
    void* RemoteString = (void*)VirtualAllocEx(Proc, NULL, strlen(dllPath), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(Proc, (LPVOID)RemoteString, dllPath, strlen(dllPath), NULL);
    HANDLE ret = CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddr, (LPVOID)RemoteString, CREATE_SUSPENDED, NULL);
    if (ret) {
        return true;
    }
}

要注入的.DLL的DllMain()函数:

#include <Windows.h>

extern void vMain();

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
    )
{
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&vMain, 0, 0, 0);
        return true;
    }
    return false;
}

vMain:

void vMain() {
    CreateConsole();        
    std::cout << "vMain() has executed!\n";
}

当我在 Visual Studio 中编译要注入的 .DLL 时,它工作正常,但是当我在 QT Creator 中编译时,vMain() 永远不会被执行。注入器、.DLL 和目标进程都是 32 位的。因此,我尝试通过使用CREATE_SUSPENDED 标志使.DLL 注入器调用CreateRemoteThread() 来调试目标进程,这样我就可以在LoadLibraryA() 上设置断点,恢复线程,从断点逐步执行,然后查看返回值。但是,我在 LoadLibraryA() 上的断点没有被命中。

所以我调试了 .DLL 注入器应用程序以确保正在创建远程线程。我确认是通过在CreateRemoteThread()的返回值上调用GetThreadID(),将其输出,并在目标进程的线程列表中查看该线程:

请记住,线程仍处于挂起状态。进一步检查,EIP 指向_RtlUserThreadStart() 中的第一条指令。我在这条指令上设置了一个断点。然后我通过从我的 .DLL 注入程序中调用 ResumeThread() 来恢复挂起的线程。没有命中断点。

值得注意的是,目标应用程序没有任何反断点机制,除了这个实例之外,断点对我来说都很好。

那么我怎样才能找出问题所在呢?我的断点没有被击中是有原因的吗?有没有更好的方法来调试问题?

【问题讨论】:

  • dllPath 是完整路径吗?如果不是,那么您确定从 Qt Creator 运行时可以访问它吗?

标签: c++ qt debugging dll dll-injection


【解决方案1】:

从 DLL 中进行控制台输出时,您可能需要将 stdout 重定向到控制台:

// AllocConsole() instead of CreateConsole()
AllocConsole();
freopen("CONOUT$", "w", stdout); // <====
std::cout << "vMain() has executed!\n";

此外,在DllMain() 中创建线程并不是一个好主意,原因如下:

相关问题:

我记得我过去曾遇到过一些麻烦,因此我不再按照建议在 DllMain() 中创建线程/窗口等操作。

不过,在某些情况下它确实有效,但我不相信它。

话虽如此,如果上述方法不起作用,请尝试在没有线程的情况下直接调用您的vMain(),看看会发生什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    • 2010-11-05
    相关资源
    最近更新 更多