SetUnhandledExceptionFilter拦不住的崩溃

前段程序测试中使用了SetUnhandledExceptionFilter,发现很多崩溃并没有拦截到,还是弹出关闭窗口,网上找了找,发现问题在于MS在c++缓存溢出检查中重置了这个函数,原因很简单,避免黑客利用这个常见错误黑电脑,不过也带来很多不便,这篇文章告诉我们如何避开这个问题

SetUnhandledExceptionFilter and VC

原文:http://blog.kalmbachnet.de/?postid=75

 

Many programs are setting an own Unhandled-Exception-Filter , for catching unhandled exceptions and do some reporting or logging (for examplecreating a mini-dump ).

Now, starting with VC8 (VS2005), MS changed the behaviour of theCRT is some security related and special situations.
The CRT forces the call of the default-debugger (normally Dr.Watson) without informing the registered unhandled exception filter. The situations in which this happens are the following:

  • Calling abort if the abort-behaviour was set to _CALL_REPORTFAULT. This is the default setting for release builds!
  • Failures detected by security checks (see alsoCompiler Security Checks In Depth ) This is also enabled by default!
  • If no invalid parameter handler was defined (which is the default setting) and an invalid parameter was detected (this is done in manyCRT functions by calling _invalid_parameter).

So the conclusion is: The are many situations in which your user-defined Unhandled-Exception-Filter will never be called. This is a major change to the previous versions of theCRT and IMHO not very well documented.

The solution

If you don’t want this behavior and you will be sure that your handler will be called, you need to intercept the call toSetUnhandledExceptionFilter which is used by the CRT to disable all previously installed filters. You can achieve this for x86 with the following code:

 

 

  #include 
  #include 
  #include 

  #ifndef _M_IX86
  #error "The following code only works for x86!"
  #endif
  LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter(
    LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
  {
    return NULL;
  }

  BOOL PreventSetUnhandledExceptionFilter()
  {
    HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
    if (hKernel32  NULL) return FALSE;
    void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter");
    if(pOrgEntry  NULL) return FALSE;
    unsigned char newJump[ 100 ];
    DWORD dwOrgEntryAddr = (DWORD) pOrgEntry;
    dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far
    void *pNewFunc = &MyDummySetUnhandledExceptionFilter;
    DWORD dwNewEntryAddr = (DWORD) pNewFunc;
    DWORD dwRelativeAddr = dwNewEntryAddr – dwOrgEntryAddr;

    newJump[ 0 ] = 0xE9;  // JMP absolute
    memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc));
    SIZE_T bytesWritten;
    BOOL bRet = WriteProcessMemory(GetCurrentProcess(),
      pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten);
    return bRet;
  }

  LONG WINAPI MyUnhandledExceptionFilter(
    struct _EXCEPTION_POINTERS *lpTopLevelExceptionFilter)
  {
    // TODO: MiniDumpWriteDump
    FatalAppExit(0, _T(“Unhandled Exception occured!”));
    return EXCEPTION_CONTINUE_SEARCH;
  }

  int _tmain()
  {
    SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
    BOOL bRet = PreventSetUnhandledExceptionFilter();
    _tprintf(_T(“Prevented: %d”), bRet);

    abort();  // force Dr.Watson in release!
  }


Before calling PreventSetUnhandledExceptionFilter you must be sure that no other thread is running (or at least no other thread is trying to callSetUnhandledExceptionFilter).


你可能感兴趣的:(游戏编程)