簡體   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