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

多线程64位应用中通过代码设置断点的问题排查

调试多线程64位应用时的冻结与多线程断点设置问题

我参考了其他来源的代码,但在当前场景下无法解决问题。要附加到一个随时有100多个线程的64位应用程序,遇到两个核心问题:

  • 执行DebugActiveProcess(pid)时,被附加的应用程序直接冻结。
  • 当前代码仅能在单个线程(通过GetProcessThreadID获取的第一个线程)设置断点,但我需要在多个(最好是所有)线程上设置硬件断点。

已确认执行SetThreadContext(hThread, &ctx)时,dr0和dr7寄存器按预期更改,这部分逻辑正常。目前的痛点是应用冻结和多线程断点设置:我考虑过遍历所有线程一次性设置断点,但进入调试事件循环后显然会引发问题,且资源消耗极大。另外,用CheatEngine调试器附加该应用时,断点能正常工作,无冻结或断点失效问题。

以下是我使用的代码:

DWORD GetProcessThreadID(DWORD dwProcessID)
{
    THREADENTRY32 te = { sizeof(THREADENTRY32) };
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

    if (Thread32First(hSnapshot, &te))
        while (Thread32Next(hSnapshot, &te))
            if (te.th32OwnerProcessID == dwProcessID)
                return te.th32ThreadID;

    return NULL;
}

BOOL SetDebugPrivilege(BOOL State)
{
    HANDLE hToken;
    TOKEN_PRIVILEGES token_privileges;
    DWORD dwSize;

    ZeroMemory(&token_privileges, sizeof(token_privileges));
    token_privileges.PrivilegeCount = 1;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
        return FALSE;

    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &token_privileges.Privileges[0].Luid))
    {
        CloseHandle(hToken);
        return FALSE;
    }

    if (State)
        token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;

    if (!AdjustTokenPrivileges(hToken, FALSE, &token_privileges, 0, NULL, &dwSize))
    {
        CloseHandle(hToken);
        return FALSE;
    }

    return CloseHandle(hToken);
}

void CreateBreakpoint(DWORD pid, DWORD64 addr) {

    DebugActiveProcess(pid);
    DebugSetProcessKillOnExit(false);

    DWORD_PTR dwThreadID = GetProcessThreadID(pid);
    std::cout << std::hex << dwThreadID << std::endl;

    HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);

    SetDebugPrivilege(true);

    CONTEXT ctx = { 0 };
    ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS | CONTEXT_INTEGER;
    ctx.Dr0 = addr;
    ctx.Dr7 = 0x00000001;

    SetThreadContext(hThread, &ctx);

    DEBUG_EVENT dbgEvent;
    while (true) {
        if (WaitForDebugEvent(&dbgEvent, INFINITE) == 0)
            break;

        if (dbgEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
            dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) // EXCEPTION_BREAKPOINT
        {
            if (dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)addr)
            {
                GetThreadContext(hThread, &ctx);
                std::cout << ctx.Rax << "\n";
                ctx.Dr7 = 0;
                SetThreadContext(hThread, &ctx);
            }
        }
        ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
    }
}

注:这是Python脚本的C扩展,但问题与扩展无关,单独运行代码也会出现相同问题。我并非C专家,若有理解偏差请见谅。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 04:01:07