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:

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 <windows.h>
  #include <tchar.h>
  #include <stdio.h>

  #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).


  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值