多线程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
相关产品推荐
相关产品推荐

