另一个进程中的断点处理

时间:2013-05-14 02:59:31

标签: c++ debugging winapi assembly

根据Read eax register中给出的建议,我使用winapi编写了一个简单的调试器。 我的目标是每次在另一个线程中执行汇编指令后读取eax寄存器。 它正在工作,我设法在另一个进程中放置一个硬件断点。

当断点到达调试对象线程内部时出现问题,我可以按预期读取eax寄存器,但我仍然无法找到恢复线程执行的任何方法。

我的代码:

 int _tmain(int argc, _TCHAR* argv[])
 {
 // Finding Window
HWND window = FindWindow(0, _T("Test"));
if( window == 0 )
{
    printf("Process not found!\n");
    return 0;
}

DWORD_PTR pID = 0;
GetWindowThreadProcessId(window, &pID);


// Get Handle
//HANDLE _handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);

DWORD_PTR eax = 0;
DWORD_PTR address = 0xC31E1B; // address of the instruction after the call for hardware breakpoint

DebugActiveProcess(pID); // PID of target process

// Avoid killing app on exit
DebugSetProcessKillOnExit(false);

// get thread ID of the main thread in process
DWORD_PTR dwThreadID = GetProcessThreadID(pID);

// gain access to the thread
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);

SetDebugPrivilege(true);

//ctx.Dr6=0;           //clear debug status register (only bits 0-3 of dr6 are cleared by processor)

CONTEXT ctx = {0};
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS | CONTEXT_INTEGER;
ctx.Dr0 = address;
ctx.Dr7 = 0x00000001;


// hThread with enough permissions
SetThreadContext(hThread, &ctx); 

DEBUG_EVENT dbgEvent;
while (true)
{
    if (WaitForDebugEvent(&dbgEvent, INFINITE) == 0)
        break;

    if (dbgEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
        dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) // EXCEPTION_BREAKPOINT
    {
        if (dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)address)
        {
            GetThreadContext(hThread, &ctx);
            eax = ctx.Eax; // eax get
            std::cout<<eax<<"\n";
            // Resume execution
            ctx.Eip = address + 0x3;
            SetThreadContext(hThread, &ctx);
        }

    }

    ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
}
return 0;
}

感谢您的帮助!!

3 个答案:

答案 0 :(得分:1)

ContinueDebugEvent(dwProcessId,dwThreadId,dwContinueStatus)


这应该可以胜任!你不需要改变eip。如果您想了解更多信息,请阅读Writing the Debugger's Main Loop

答案 1 :(得分:1)

取自:Hardware breakpoints EXCEPTION_SINGLE_STEP all the time

整个逻辑应该遵循:

  1. 添加断点。
  2. 触发后,删除断点并在EFLAGS(0x100)中设置单步标记
  3. 下次调用循环时,重新启用硬件断点。
  4. 所以你的while循环应该是这样的:

    while (true)
    {
        if (WaitForDebugEvent(&dbgEvent, INFINITE) == 0)
            break;
    
        if (dbgEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
            dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) // EXCEPTION_BREAKPOINT
        {
            CONTEXT newCtx = {0};
            newCtx.ContextFlags = CONTEXT_ALL;
            GetThreadContext(hThread, &newCtx);
            if (dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)address)
            {
                newCtx.Dr0 = newCtx.Dr6 = newCtx.Dr7 = 0;
                newCtx.EFlags |= (1 << 8);
            }else{
                newCtx.Dr0 = address;
                newCtx.Dr7 = 0x00000001;
                newCtx.EFlags &= ~(1 << 8);
            }
            SetThreadContext(hThread, &newCtx);
        }
        ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
    }
    

答案 2 :(得分:1)

if (dbgEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT &&
    dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) // EXCEPTION_BREAKPOINT
{
    if (dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress == (LPVOID)address)
    {
        GetThreadContext(hThread, &ctx);
        std::cout << ctx.Eax << "\n";
        ctx.Dr7 = 0;
        SetThreadContext(hThread, &ctx);
    }
}

在 ctx 中禁用 Dr7 中的 Dr0 应该可以完成这项工作。其他评论不能解决问题)