使用winapi为当前进程设置硬件断点

时间:2017-08-23 01:15:43

标签: c debugging winapi

我想在我的变量上设置一个断点,当我进行读取访问时,我有这个代码:

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。

1 个答案:

答案 0 :(得分:0)

关于调试。对于调试需要创建特殊的 DebugObject ,并将该进程(您要调试)与此调试对象关联。在此之后,当某个事件发生在与调试对象关联的进程中时,系统挂起进程中的所有线程,将调试事件插入调试对象并将其设置为信号状态。在调试器中,等待调试对象的线程,通过WaitForDebugEvent说(但可能是调试对象的直接传递句柄说MsgWaitForMultipleObjectsEx)唤醒并处理此调试事件。但是如果线程将来自调试进程 - 它将被暂停,因为正在处理的所有线程并且从不处理此事件。在这种情况下,进程挂起。所以 - 当调试事件(例如,例外)发生时,系统挂起进程中的所有线程,进程无法调试自身。

WaitForDebugEvent没有任何等待。 WaitForDebugEvent在内部致电ZwWaitForDebugEventHANDLE hDebugObject在哪里?来自线程 TEB (此处存在保存它的特殊字段)。当您使用标志CreateProcessDEBUG_PROCESS系统内部调用DebugActiveProcess来调用DbgUiConnectToDbg时 - 此api检查 - 线程已经具有相关的调试对象(在 TEB )如果还没有 - 用ZwCreateDebugObject创建新的并将其存储在 TEB 中(可以通过DbgUiGetThreadDebugObject访问并通过DbgUiSetThreadDebugObject更改)。只有在此之后你才能打电话给WaitForDebugEvent。因为您不是通过ZwCreateDebugObject直接创建调试对象,而是不使用标志CreateProcessDEBUG_PROCESS调用DebugActiveProcess - 没有与您的线程相关的调试对象,并调用{{1}当然失败

在自己的进程中只有一个选项捕获硬件断点 - 使用 VEX 。例如:

WaitForDebugEvent