Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
369 views
in Technique[技术] by (71.8m points)

c++ - Breakpoint handling in another process

Following advices given in Read eax register , I wrote a simple debugger using winapi. My objective is to read the eax register each time after an assembly instruction is executed in another thread. It is working and I managed to put an hardware breakpoint in another process.

The problem arise when the breakpoint is reach inside the debuggee thread, I can read the eax register as intended, but I still couldn't find any way to resume the thread's execution.

My code :

 int _tmain(int argc, _TCHAR* argv[])
 {
 // Finding Window
HWND window = FindWindow(0, _T("Test"));
if( window == 0 )
{
    printf("Process not found!
");
    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<<"
";
            // Resume execution
            ctx.Eip = address + 0x3;
            SetThreadContext(hThread, &ctx);
        }

    }

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

Thanks for help !!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Taken from this: Hardware breakpoints EXCEPTION_SINGLE_STEP all the time

The entire logic should be following:

  1. Add breakpoint.
  2. Upon triggering it, you remove the breakpoint and set a Single Step flag in EFLAGS (0x100)
  3. The next time the loop is called, you re-enable the hardware breakpoint.

So your while-loop should be like this:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...