繁体   English   中英

我在使用WaitForDebugEvent EXCEPTION_DEBUG_EVENT时遇到问题

[英]I'm having problems with WaitForDebugEvent EXCEPTION_DEBUG_EVENT

我正在使用CreateProcess(标志NORMAL_PRIORITY_CLASS + DEBUG_PROCESS + DEBUG_ONLY_THIS_PROCESS)启动Explorer.exe实例,然后执行以下操作:

procedure FakeDebugProcess; 
var 
  wDebugEvent : DEBUG_EVENT; 
begin 
  fillchar( wDebugEvent, sizeof( wDebugEvent ), 0 ); 
  repeat 
    if WaitForDebugEvent( wDebugEvent, INFINITE ) 
      then 
        begin 
          if wDebugEvent.dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT 
            then break; 
          ContinueDebugEvent( wDebugEvent.dwProcessId, wDebugEvent.dwThreadId, DBG_CONTINUE ); 
        end;
  until false; 
end;

一切正常,除了我从看起来像是“ C:\\ Windows \\ System32 \\ rpcrt4.dll”的文件中获得了许多EXCEPTION_DEBUG_EVENTs之外

(其他详细信息:EXCEPTION_ACCESS_VIOLATION)

77ea3c00 sub_77ea3c00:                    ; function entry point
77ea3c00 >>mov     [ecx+4], eax
77ea3c03   movsx   eax, bx
77ea3c06   cdq
77ea3c07   sub     eax, edx
77ea3c09   sar     eax, 1
77ea3c0b   mov     [ecx], ax
77ea3c0e   xor     eax, eax
77ea3c10   pop     edi
77ea3c11   pop     esi
77ea3c12   pop     ebx
77ea3c13   pop     ebp
77ea3c14   ret     8

我究竟做错了什么? 我如何解决它?

我正在使用Delphi 7,顺便说一句。

您的代码很好,可以使用ollydbg,rpcrt4.dll等其他调试器进行测试,仍然会报告附加到某些应用程序上的异常。 解决此问题的唯一方法是根据异常代码,然后根据模块,定义过滤器(ollydbg允许用户执行操作)。 因此,如果收到0xC0000005(EXCEPTION_ACCESS_VIOLATION),则检查: EIP >= (UINT_PTR)GetModuleHandle("rpcrt.dll") && EIP <= (UINT_PTR)GetModuleHandle("rpcrt.dll") + getModuleSize("rpcrt.dll") (当然,getModuleSize是一个自定义函数,用于从PE获取模块虚拟化的大小,而UINT_PTR是一种足以将指针保留在目标系统上的类型),您可以忽略它,否则处理该事件,尽管可能需要钩子进入KiDispatchUserException(这应该是正确的,否则检查NTInternals)

我知道这个线程很旧,但是我遇到了同样的问题并解决了它,所以我想分享一下。

如果启动进程并希望使用Windows API调用对其进行调试,则应该知道Windows在首次加载时将发送一个EXCEPTION_BREAKPOINT(INT3)。 您必须DEBUG_CONTINUE这个第一个断点异常...如果您使用DBG_EXCEPTION_NOT_HANDLED,则会出现弹出消息框:应用程序无法正确初始化(0x80000003)。

现在,对于所有其他异常,您想返回DBG_EXCEPTION_NOT_HANDLED,以便将它们传递回并进行处理。 在Windows生成第一个断点异常之后,您可以随意设置其他断点。

调试循环的真正简化代码如下所示:

// debug loop...  while(debugging) or whatever you want to do.

DEBUG_EVENT DebugEvent;
DWORD ContinueStatus = DBG_CONTINUE;

WaitForDebugEvent(&DebugEvent, INFINITE);

switch (DebugEvent.dwDebugEventCode) {

    case EXCEPTION_DEBUG_EVENT:

        switch(DebugEvent.u.Exception.ExceptionRecord.ExceptionCode) { 

            case EXCEPTION_BREAKPOINT:
                // stay with DBG_CONTINUE at least for the first breakpoint. 
                // continue, don't pass this back to process being debugged.   
                break;
            default:
                // handles all other stuff like EXCEPTION_ACCESS_VIOLATION
                // pass these back to the process being debugged... 
                ContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
                break;
        }
        break;

    default: 
        break;
}

ContinueDebugEvent(DebugEvent.dwProcessId, DebugEvent.dwThreadId, ContinueStatus);

基本:

  • Windows会在启动时生成一个断点,您需要捕获该断点而不要将其传递回来。
  • 大型Windows程序还会处理许多其他异常,因此请将其传回。
  • 在启动时传回断点原因:“应用程序无法正确初始化(0x80000003)”
  • 捕获内存/ SEH异常并没有将其传递回去会导致调试器循环中无休止的循环,因为这些异常永远不会被代码清除。

您为什么认为您的代码有什么问题? 调试器会针对任何SEH异常获得优先通知。 您正在调试大量的代码。 不只是Explorer.exe,您还可以获得所有的Shell扩展处理程序。 周围有很多问题,即使这些扩展程序有错误,Explorer也会尽力保持生存。

如果您确实想解决这个问题,那么可以使用SysInternals的Autoruns实用程序,并禁用Microsoft并非您真正不需要的任何Shell扩展处理程序。 如果要测试调试器,请尝试使用其他更简单的工具,例如Notepad.exe。 尽管File + Open带来了这些Shell扩展。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM