gpt4 book ai didi

c++ - 调试器在异常 C++ 时不挂起被调试者

转载 作者:搜寻专家 更新时间:2023-10-31 02:11:24 25 4
gpt4 key购买 nike

我用 C++ 做了一个非常简单的调试器,它似乎工作正常,除非我调用 WaitForDebugEvent dwMilliseconds 的任意值除了INFINITE它不会立即挂起被调试者。

我有一个 if检查异常地址是否与我设置的断点地址匹配的语句 if(ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == lpBreakpoint) .

递减 eip ( wow64cntxt.Eip --; ), 用原始指令 ( int3 ) 替换断点 ( WriteProcessMemory ) 字节, 刷新指令缓存 ( FlushInstructionCache ), 然后设置 eip指向我用原始指令(Wow64SetThreadContext)替换的断点。

然后它返回到主调试循环(break)并继续调试(ContinueDebugEvent)。

case EXCEPTION_BREAKPOINT:
{
WOW64_CONTEXT wow64cntxt = {0};

wow64cntxt.ContextFlags = WOW64_CONTEXT_ALL;

if(!Wow64GetThreadContext(hThread, &wow64cntxt))
{
printf("Error getting thread context: %lu\n", GetLastError());
}

//lpFunction is the address of a mov instruction I set a breakpoint on
if(excDbgInfo.ExceptionRecord.ExceptionAddress == lpBreakpoint)
{
printf("EIP-Before: 0x%X\n", wow64cntxt.Eip);

//Decrement eip value to point back to the opcode I wrote over with int3
wow64cntxt.Eip --;

printf("EIP-After: 0x%X\n", wow64cntxt.Eip);

//original opcode I replaced with int3(0xCC)
instr = 0x89;

//replace the breakpoint with the original instruction
if(!WriteProcessMemory(hProcess, lpBreakpoint, &instr, sizeof(CHAR), NULL))
{
printf("Error reversing breakpoint: %lu\n", GetLastError());
}

//Flush the instruction cache
FlushInstructionCache(hProcess, lpBreakpoint, 1);

//Set eip to previous instruction
if(!Wow64SetThreadContext(hThread, &wow64cntxt))
{
printf("Error setting thread context: %lu\n", GetLastError());
}

}
system("pause");
//Return to main debug loop, ContinueDebugEvent...
break;
}

如果我使用 INFINITE 以外的任何东西与 WaitForDebugEvent然后eip设置为在我设置的断点后一段时间执行的地址。

问题是如果我不使用 WaitForDebugEventINFINITE然后eip当调试器捕捉到异常时已经过了断点。即使我有 WaitForDebugEvent等待0毫秒,立即返回,被调试者依然跑过断点。

然后这会导致访问冲突,我猜是因为我用断点替换的指令的另一半变成了一个新的操作码,它修改了它不允许的内存。

这是我的主要调试循环:

while(1)
{
WaitForDebugEvent(&dbgEvent, INFINITE);

ProcessDebugEvent(&dbgEvent);

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

如有任何信息、见解、提示、解释等,我们将不胜感激。谢谢。

最佳答案

dwMilliseconds 参数告诉 WaitForDebugEvent() 等待调试事件到达的时间:

dwMilliseconds [in]
The number of milliseconds to wait for a debugging event. If this parameter is zero, the function tests for a debugging event and returns immediately. If the parameter is INFINITE, the function does not return until a debugging event has occurred

您需要检查 WaitForDebugEvent() 的返回值,以确保您确实有需要处理的真实调试事件:

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

例如:

while (1)
{
if (WaitForDebugEvent(&dbgEvent, AnyValueHere)) // <--
{
ProcessDebugEvent(&dbgEvent);
ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE);
}
...
}

也就是说,dwMilliseconds 参数对命中断点时调试对象等待的时间没有影响。当遇到断点时,被调试者立即停止,并通知你的调试器。这在文档中有明确说明:

Debugging Events

When the system notifies the debugger of a debugging event, it also suspends all threads in the affected process. The threads do not resume execution until the debugger continues the debugging event by using ContinueDebugEvent.

很有可能,ProcessDebugEvent() 根本没有正确处理断点,只有当您在完成处理后调用 ContinueDebugEvent() 时,调试对象才会被唤醒。

关于c++ - 调试器在异常 C++ 时不挂起被调试者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43637131/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com