繁体   English   中英

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

[英]Setting hardware breakpoint using winapi for current process

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

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 int status = WaitForDebugEvent(&dbgEvent, INFINITE); 它不会完美地等待,只是立即返回0,我将MessageBoxA放置到测试中,基本上我没有收到任何通知,并等待对lpBuffer执行的读取。 我认为我做错了什么,也许与dr7标志有关? 0x30002是‭00110000000000000010‬,因此应为硬件读/写bp。

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

关于WaitForDebugEvent不会造成任何等待。 WaitForDebugEvent内部调用ZwWaitForDebugEvent ,从何处HANDLE hDebugObject 从线程TEB (此处存在用于保存它的特殊字段)。 当您使用标志DEBUG_PROCESS调用CreateProcessDebugActiveProcess系统在内部调用DbgUiConnectToDbg -此api检查-线程是否已附带调试对象(在TEB中 ),如果还没有,请使用ZwCreateDebugObject创建新对象并将其存储在TEB中 (可以通过DbgUiGetThreadDebugObject访问并通过DbgUiSetThreadDebugObject更改)。 只有在此之后,您才能调用WaitForDebugEvent 因为您没有通过ZwCreateDebugObject直接创建调试对象,并且没有用标志DEBUG_PROCESSDebugActiveProcess调用CreateProcess没有调试对象与您的线程DEBUG_PROCESS ,所以调用WaitForDebugEvent当然会失败

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

LONG NTAPI OnVex(PEXCEPTION_POINTERS ExceptionInfo)
{
    WCHAR buf[1024], *sz = buf, wz[64];
    PEXCEPTION_RECORD ExceptionRecord = ExceptionInfo->ExceptionRecord;

    swprintf(wz, L"%x> %x at %p", GetCurrentThreadId(), ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress);

    *buf = 0;

    if (ULONG NumberParameters = ExceptionRecord->NumberParameters)
    {
        sz += swprintf(sz, L"[ ");

        PULONG_PTR ExceptionInformation = ExceptionRecord->ExceptionInformation;
        do 
        {
            sz += swprintf(sz, L"%p, ", *ExceptionInformation++);
        } while (--NumberParameters);

        sz += swprintf(sz - 2, L" ]");
    }

    MessageBoxW(0, buf, wz, 0);

    return ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_CONTINUE_SEARCH;
}

DWORD HardwareTest(PVOID pv)
{
    WCHAR sz[64];
    swprintf(sz, L"hThread = %p\n", *(void**)pv);
    return MessageBoxW(0, 0, sz, MB_ICONINFORMATION);
}

void ep()
{
    if (PVOID handler = AddVectoredExceptionHandler(TRUE, OnVex))
    {
        if (HANDLE hThread = CreateThread(0, 0, HardwareTest, &hThread, CREATE_SUSPENDED, 0))
        {
            CONTEXT ctx = {};
            ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
            ctx.Dr3 = (ULONG_PTR)&hThread;
            ctx.Dr7 = 0xF0000040;

            SetThreadContext(hThread, &ctx);

            ResumeThread(hThread);

            WaitForSingleObject(hThread, INFINITE);

            CloseHandle(hThread);
        }

        RemoveVectoredExceptionHandler(handler);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM