我想在我的变量上设置一个断点,当我进行读取访问时,我有这个代码:
char * lpBuffer = NULL;
void proc(PVOID)
{
for (int i = 0; i < 10; i++) {
Sleep(100);
MessageBoxA(0, 0, 0, 0);
char * h = lpBuffer;
h[0x4] = 0x88;
}
}
int main()
{
lpBuffer = malloc(20);
SetDebugPrivilege(TRUE);
HANDLE hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)proc, 0, CREATE_SUSPENDED, 0);
CONTEXT ctx = {};
BOOL st = GetThreadContext(hThread, &ctx);
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
ctx.Dr0 = (DWORD)&lpBuffer;
ctx.Dr7 = 0x30002;
st = SetThreadContext(hThread, &ctx);
ResumeThread(hThread);
DEBUG_EVENT dbgEvent;
int status = WaitForDebugEvent(&dbgEvent, INFINITE);
//..
}
我总是从int status = WaitForDebugEvent(&dbgEvent, INFINITE);
获得0它没有任何等待只是立即返回0,我放置MessageBoxA
进行测试,基本上我没有收到任何通知并等待读取已执行在lpBuffer
。我想我做错了,也许它与dr7标志有关? 0x30002是00110000000000000010,所以它应该是硬件读/写bp。
答案 0 :(得分:0)
关于调试。对于调试需要创建特殊的 DebugObject ,并将该进程(您要调试)与此调试对象关联。在此之后,当某个事件发生在与调试对象关联的进程中时,系统挂起进程中的所有线程,将调试事件插入调试对象并将其设置为信号状态。在调试器中,等待调试对象的线程,通过WaitForDebugEvent
说(但可能是调试对象的直接传递句柄说MsgWaitForMultipleObjectsEx
)唤醒并处理此调试事件。但是如果线程将来自调试进程 - 它将被暂停,因为正在处理的所有线程并且从不处理此事件。在这种情况下,进程挂起。所以 - 当调试事件(例如,例外)发生时,系统挂起进程中的所有线程,进程无法调试自身。
约WaitForDebugEvent
没有任何等待。 WaitForDebugEvent
在内部致电ZwWaitForDebugEvent
,HANDLE hDebugObject
在哪里?来自线程 TEB (此处存在保存它的特殊字段)。当您使用标志CreateProcess
或DEBUG_PROCESS
系统内部调用DebugActiveProcess
来调用DbgUiConnectToDbg
时 - 此api检查 - 线程已经具有相关的调试对象(在 TEB )如果还没有 - 用ZwCreateDebugObject
创建新的并将其存储在 TEB 中(可以通过DbgUiGetThreadDebugObject
访问并通过DbgUiSetThreadDebugObject
更改)。只有在此之后你才能打电话给WaitForDebugEvent
。因为您不是通过ZwCreateDebugObject
直接创建调试对象,而是不使用标志CreateProcess
或DEBUG_PROCESS
调用DebugActiveProcess
- 没有与您的线程相关的调试对象,并调用{{1}当然失败
在自己的进程中只有一个选项捕获硬件断点 - 使用 VEX 。例如:
WaitForDebugEvent