使用SetUnhandledExceptionFilter函数获取dump文件,非常便于生产环境中的调试。但突然发现release版本竟然无法dump了。
经查,新版本的CRT 实现在异常处理中强制删除所有应用程序先前设置的捕获函数,如下所示:
/* Make sure any filter already in place is deleted. */
SetUnhandledExceptionFilter(NULL);
UnhandledExceptionFilter(&ExceptionPointers);
解决方法是拦截CRT 调用SetUnhandledExceptionFilter 函数,使之无效。在X86 平台下,可以使用以下代码。
#ifndef _M_IX86
#error “The following code only works for x86!”
#endif
void DisableSetUnhandledExceptionFilter()
{
void *addr = (void*)GetProcAddress(LoadLibrary(_T(“kernel32.dll”)),
“SetUnhandledExceptionFilter”);
if (addr)
{
unsigned char code[16];
int size = 0;
code[size++] = 0×33;
code[size++] = 0xC0;
code[size++] = 0xC2;
code[size++] = 0×04;
code[size++] = 0×00;
DWORD dwOldFlag, dwTempFlag;
VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
}
}
在设置自己的异常处理函数后,调用DisableSetUnhandledExceptionFilter 禁止CRT 设置即可。
static BOOL PreventSetUnhandledExceptionFilter(){ HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); if (hKernel32 == NULL) return FALSE; void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter"); if (pOrgEntry == NULL) return FALSE;#ifdef _M_IX86 // Code for x86: // 33 C0 xor eax,eax // C2 04 00 ret 4 unsigned char szExecute[] = { 0x33, 0xC0, 0xC2, 0x04, 0x00 };#elif _M_X64 // 33 C0 xor eax,eax // C3 ret unsigned char szExecute[] = { 0x33, 0xC0, 0xC3 };#else#error "The following code only works for x86 and x64!"#endif SIZE_T bytesWritten = 0; BOOL bRet = WriteProcessMemory(GetCurrentProcess(), pOrgEntry, szExecute, sizeof(szExecute), &bytesWritten); return bRet;}
//首先要清掉SEH
asm
@Loop:
mov eax,fs:[0]
cmp dword ptr [eax],$FFFFFFFF
je @SEHCleared
mov eax,[eax]
mov fs:[0],eax
jmp @Loop
@SEHCleared:
http://www.debuginfo.com/articles/debugfilters.htmlhttp://blog.kalmbach-software.de/2013/05/23/improvedpreventsetunhandledexceptionfilter/
No comments:
Post a Comment