我从其他来源(主要是here)改编了一些代码,但在我的环境中没有任何用处。我正在连接一个64位的应用程序,在任何给定的时间都有100个线程。我有两个问题,有点不相关:
1.只要代码命中DebugActiveProcess(pid)
,附加的应用程序就会冻结。
1.我的代码只在主线程上设置了一个断点,但我需要在多个线程上设置断点--最好是在所有线程上。
我已经确认,当代码命中SetThreadContext(hThread, &ctx)
时,dr0
和dr7
寄存器会按预期进行更改,因此没有问题。我现在看到的唯一问题是进程冻结和设置多个断点(我想对每个线程进行迭代,但当它进入while循环时,显然会出现问题,并且非常消耗资源)。我还应该注意到,我可以将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扩展,但这应该不是真正相关的,即使我单独运行代码,也会遇到同样的问题。另外,我不是CMaven,所以如果有任何误解,我道歉。
1条答案
按热度按时间uurity8g1#
我同意Taekahn的观点,除非你给予更多关于你要做什么的信息,为什么不使用一个普通的调试器呢?如果你只是想读取寄存器,任何调试器都可以做到。你甚至可以在反汇编或随机地址中设置断点,或者设置数据断点。
关于gdb的IDK,但是即使在visual studio中,你也可以在断点上设置条件和动作。它没有c++代码那么强大,但是再次,没有更多的信息...
如果你想修改应用程序的行为,我们不是这样做的,使用调试器实际上会导致问题。