简体   繁体   English

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

[英]Setting hardware breakpoint using winapi for current process

I want to set a breakpoint on my variable, when i do the read access, i have this code: 我想在变量上设置一个断点,当我进行读取访问时,我有以下代码:

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);

    //..
}

I always get 0 from int status = WaitForDebugEvent(&dbgEvent, INFINITE); 我总是从int status = WaitForDebugEvent(&dbgEvent, INFINITE);得到0 int status = WaitForDebugEvent(&dbgEvent, INFINITE); it doesnt perfrorm any waiting just returns 0 immediatly, i placed MessageBoxA to test, basically i don't get any notifications and waiting that the read has performed on lpBuffer . 它不会完美地等待,只是立即返回0,我将MessageBoxA放置到测试中,基本上我没有收到任何通知,并等待对lpBuffer执行的读取。 I think i have done something wrong, maybe it has to do with dr7 flags? 我认为我做错了什么,也许与dr7标志有关? 0x30002 is ‭00110000000000000010‬, so it should be hardware read/write bp. 0x30002是‭00110000000000000010‬,因此应为硬件读/写bp。

about debugging. 关于调试。 for debug need create special DebugObject and associate process (which you want to debug) with this debug object. 对于调试,需要创建特殊的DebugObject并将该进程(您要调试的)与此调试对象相关联。 after this, when some events occur in process associated with debug object, system suspend all threads in process , insert debug event to debug object and set it to signal state. 此后,当与调试对象相关联的进程中发生某些事件时,系统挂起进程中的所有线程 ,将调试事件插入调试对象并将其设置为信号状态。 in debugger, thread which wait on debug object, say via WaitForDebugEvent (but possible direct pass handle of debug object to say MsgWaitForMultipleObjectsEx ) awakened and handle this debug event. 在调试器中,等待对象的线程,例如,通过WaitForDebugEvent (但可以通过调试对象的直接传递句柄说MsgWaitForMultipleObjectsEx )唤醒,并处理此调试事件。 but if thread will be from debugged process - it will be suspended, as all threads in process and never handle this event. 但是如果线程将来自已调试的进程,则它将被挂起,因为所有进程中的线程都不会处理此事件。 process hang in this case. 在这种情况下进程挂起。 so - process can not debug itself because system suspend all threads in process when debug event (exception for example) occur. 因此-进程无法调试自身,因为发生调试事件(例如,异常)时,系统会挂起进程中的所有线程

about WaitForDebugEvent doesnt perfrorm any waiting. 关于WaitForDebugEvent不会造成任何等待。 WaitForDebugEvent internally call ZwWaitForDebugEvent and from where is HANDLE hDebugObject is geted ? WaitForDebugEvent内部调用ZwWaitForDebugEvent ,从何处HANDLE hDebugObject from thread TEB (here exist special field for save it). 从线程TEB (此处存在用于保存它的特殊字段)。 when you call CreateProcess with flag DEBUG_PROCESS or DebugActiveProcess system internally call DbgUiConnectToDbg - this api check - are thread already have accosiated debug object (in TEB ) and if yet no - create new with ZwCreateDebugObject and store it in TEB (it can be accessed via DbgUiGetThreadDebugObject and changed via DbgUiSetThreadDebugObject ). 当您使用标志DEBUG_PROCESS调用CreateProcessDebugActiveProcess系统在内部调用DbgUiConnectToDbg -此api检查-线程是否已附带调试对象(在TEB中 ),如果还没有,请使用ZwCreateDebugObject创建新对象并将其存储在TEB中 (可以通过DbgUiGetThreadDebugObject访问并通过DbgUiSetThreadDebugObject更改)。 only after this you can call WaitForDebugEvent . 只有在此之后,您才能调用WaitForDebugEvent because you not direct create debug object via ZwCreateDebugObject , and not call CreateProcess with flag DEBUG_PROCESS or DebugActiveProcess - no debug objects assosiated with your thread, and call WaitForDebugEvent of course fail 因为您没有通过ZwCreateDebugObject直接创建调试对象,并且没有用标志DEBUG_PROCESSDebugActiveProcess调用CreateProcess没有调试对象与您的线程DEBUG_PROCESS ,所以调用WaitForDebugEvent当然会失败

only one option catch hardware breakpoint in own process - use VEX . 只有一个选项可以在自己的过程中捕获硬件断点-使用VEX for example: 例如:

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