首页
社区
课程
招聘
[ZT]"SetUnhandledExceptionFilter" and VC8
2006-6-16 10:40 4293

[ZT]"SetUnhandledExceptionFilter" and VC8

2006-6-16 10:40
4293
Many programs are setting an own Unhandled-Exception-Filter , for catching unhandled exceptions and do some reporting or logging (for example creating a mini-dump ).

Now, starting with VC8 (VS2005), MS changed the behaviour of the CRT 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 also Compiler 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 many CRT 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 the CRT 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 to SetUnhandledExceptionFilter 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 call SetUnhandledExceptionFilter).

Win32 • 6 Comments/Trackbacks

[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞0
打赏
分享
最新回复 (1)
雪    币: 214
活跃值: (70)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
fengercn 2006-6-16 23:52
2
0
用了后The CRT失效了
游客
登录 | 注册 方可回帖
返回