【问题标题】:Debugger don't receive breakpoint event调试器不接收断点事件
【发布时间】:2023-03-07 05:12:02
【问题描述】:

我正在学习在 VS2015 和 windows10 上使用 Visual c++ 制作内存补丁。所以我用 DEBUG_PROCESS 'CreateProcess' | DEBUG_ONLY_THIS_PROCESS。 然后我很快得到 CREATE_PROCESS_DEBUG_EVENT ,我将 0xcc 写到我想中断的地方。在那之后,调试目标就挂在那里,“WaitForDebugEvent”不能给我任何调试事件。 我转储了目标,并且 INT3 确实存在,运行转储文件并按应有的方式执行。 代码如下:

    STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
HANDLE PatchProcess;
BYTE ReadBuffer[MAX_PATH] = { 0 };
BYTE int3Code[1] = { 0xcc };
BYTE dwOldStyle[4] = { 0x65,0x65,0x65,0x65 };
if (!CreateProcess(FILE_NAME, NULL, NULL, NULL, FALSE, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
    std::cout << "CreateProcess failed" << std::endl;
    return false;
}
GetLastError();
PatchProcess = pi.hProcess;
DEBUG_EVENT dbEvent;
CONTEXT Regs;
DWORD dwState, Oldpp;

Regs.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
BOOL WhileDoFlag = true;
while (WhileDoFlag) {
    WaitForDebugEvent(&dbEvent, INFINITE);
    std::cout << "Waiting" << std::endl;
    std::cout << "Debug event code:" << dbEvent.dwDebugEventCode << std::endl;
    dwState = DBG_EXCEPTION_HANDLED;
    switch (dbEvent.dwDebugEventCode)
    {
    case CREATE_PROCESS_DEBUG_EVENT:
        ReadProcessMemory(pi.hProcess, (LPVOID)(BP), &ReadBuffer, 2, NULL);
        GetLastError();
        std::cout << "Code at" << BP << ":" << ReadBuffer[0] << std::endl;
        system("pause");
        VirtualProtectEx(pi.hProcess, (LPVOID)BP, 4, PAGE_EXECUTE_READWRITE, &Oldpp);
        GetLastError();
        WriteProcessMemory(pi.hProcess, (LPVOID)(BP), &int3Code, 2, NULL);
        GetLastError();
        dwState = DBG_CONTINUE;
        break;

    case EXIT_PROCESS_DEBUG_EVENT:
        WhileDoFlag = false;
        break;

    case EXCEPTION_DEBUG_EVENT:
        switch (dbEvent.u.Exception.ExceptionRecord.ExceptionCode)
        {
            case EXCEPTION_BREAKPOINT: 
            {
                GetThreadContext(pi.hThread, &Regs);
                if (Regs.Eip == BP + 1) {
                    Regs.Eip--;
                    WriteProcessMemory(pi.hProcess, (LPVOID)BP, &dwOldStyle, 4, 0);
                    GetLastError();
                    ReadProcessMemory(pi.hProcess, (LPVOID)(Regs.Ebp), &ReadBuffer, 1, 0);
                    GetLastError();
                    MessageBox(0, (char*)ReadBuffer, "patch test", MB_OK);
                    SetThreadContext(pi.hThread, &Regs);
                }
                dwState = DBG_CONTINUE;
                break;
            }
        }
        break;
    }
    ContinueDebugEvent(pi.dwProcessId, pi.dwThreadId, dwState);
}

它是 Windows 上的某种安全保护吗(在 XP 之后)?

PS:IDA 可以使用默认的本地 win32 调试器从转储文件中获取正确位置的断点。 PS2:使用ollydbg调试dump文件,执行时目标crash

mov dword ptr ss:[esp+0x4],eax

eax 是一个 ModuleEntryPoint esp+0x4 也是一个 ModuleEntryPoint 是不是我添加的错误断点导致了问题?

【问题讨论】:

  • CREATE_PROCESS_DEBUG_EVENT 触发时将断点放在那里是不是太晚了?在任何现代 CPU 上,您都需要使用 FlushInstructionCache 来确保 CPU 确实可以执行您的断点(此时它可能已经在指令缓存中拥有代码)。另外,你为什么不使用lpStartAddress
  • 感谢您的想法,我在 WriteProcessMemory 之后添加了“FlushInstructionCache”,但没有任何改变。似乎 WriteProcessMemory 会自行刷新[来自谷歌] 也许我没有正确使用它。然后我发现目标代码根本没有运行。
  • 我认为你需要恢复原始指令并取消引用地址才能继续执行
  • 另外你写的是两个字节,但是你的操作码是一个字节。

标签: c++ windows debugging


【解决方案1】:

0xCC 是一个字节,您正在写入 2 个字节导致目标进程崩溃,您正在写入的字节之一只是随机垃圾。只将调用中的一个字节写入WriteProcessMemory()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 2013-01-01
    相关资源
    最近更新 更多