C++ Windows程序需通过SEH、VEH、全局异常处理器、调试中断及WER五种机制协同捕获硬件异常。具体包括:一、__try/__except建立顶层过滤器;二、SetUnhandledExceptionFilter注册全局处理器;三、AddVectoredExceptionHandler注入VEH;四、DbgBreakPoint触发调试中断并读取内核状态;五、RegisterApplicationRecoveryCallback接管WER崩溃上报。

当C++程序在Windows平台运行时触发了硬件异常(如访问违规、除零错误等),系统可能通过结构化异常处理(SEH)机制向用户态传递内核级异常信号。若未正确设置SEH过滤器或未适配系统异常向量,将导致进程直接终止而无法捕获关键崩溃上下文。以下是实现稳定SEH异常捕获与内核崩溃信息提取的具体操作步骤:
一、使用__try/__except语法建立顶层异常过滤器
该方法通过编译器内置的SEH关键字,在函数作用域内设置异常分发入口点,可拦截当前线程中所有同步异常(如STATUS_ACCESS_VIOLATION、STATUS_INTEGER_DIVIDE_BY_ZERO),并阻止异常向上层调用栈传播。
1、在主函数或线程入口函数最外层包裹__try块,确保覆盖全部执行路径。
2、在__except表达式中调用GetExceptionCode()获取异常标识符,并与预定义的NT状态码进行比对。
立即学习“C++免费学习笔记(深入)”;
3、使用GetExceptionInformation()获取EXCEPTION_POINTERS结构指针,从中提取CONTEXT记录与异常地址。
4、在__except块内调用MiniDumpWriteDump生成用户模式内存转储文件,传入ExceptionParam->ExceptionRecord->ExceptionAddress作为崩溃位置标记。
二、注册全局向量异常处理器SetUnhandledExceptionFilter
该方式绕过编译器SEH语法限制,直接向系统注册一个顶层异常回调函数,适用于捕获未被任何__try块处理的异常,包括DLL加载期异常和堆损坏引发的异步异常。
1、定义符合LPTOP_LEVEL_EXCEPTION_FILTER签名的回调函数,返回值类型为LONG。
2、在程序初始化阶段(如WinMain开头)调用SetUnhandledExceptionFilter并传入该函数地址。
3、在回调函数内部检查ExceptionInfo->ExceptionRecord->ExceptionCode是否等于STATUS_BREAKPOINT或STATUS_STACK_OVERFLOW等高危码。
4、使用SymInitialize初始化符号引擎,再调用StackWalk64遍历崩溃线程调用栈,保存每一帧的AddrPC.Offset用于后续逆向定位。
三、结合Vectored Exception Handler动态注入捕获点
VEH机制优先级高于SEH且独立于函数栈帧,可在任意时刻通过AddVectoredExceptionHandler注册回调,特别适合监控第三方DLL中的不可信代码段引发的异常。
1、调用AddVectoredExceptionHandler(TRUE, VEHHandler)注册前置处理器,TRUE表示插入链表头部。
2、在VEHHandler函数中判断ExceptionInfo->ExceptionRecord->ExceptionFlags是否包含EXCEPTION_NONCONTINUABLE标志位。
3、若为非连续异常,立即调用TerminateThread强制结束当前线程,避免异常扩散至其他模块。
4、对可继续异常(如STATUS_SINGLE_STEP),修改ExceptionInfo->ContextRecord->Eip字段跳转至自定义恢复桩代码地址。
四、利用DbgBreakPoint触发调试中断并读取内核寄存器快照
当目标进程以调试模式启动时,可通过硬编码插入INT 3指令触发断点异常,在SEH上下文中捕获后调用NtQueryInformationThread获取线程内核对象状态,从而获得更底层的执行现场。
1、在可疑代码段前插入__asm { int 3 } 或调用DebugBreak()函数。
2、在__except块中调用NtQueryInformationThread,传入ThreadBasicInformation类获取THREAD_BASIC_INFORMATION结构。
3、解析该结构中的ClientId.UniqueThread字段,作为内核线程ID用于后续Windbg符号匹配。
4、调用NtReadVirtualMemory读取崩溃点附近0x100字节机器码,写入日志供反汇编分析。
五、配置WER(Windows Error Reporting)回调接管系统默认崩溃弹窗
通过RegisterApplicationRecoveryCallback与RegisterApplicationRestart配合WER服务,可在SEH捕获异常后延迟退出,执行数据保存逻辑,并由系统完成崩溃上报,避免用户感知到原始异常对话框。
1、在程序启动时调用SetErrorMode(SEM_NOGPFAULTERRORBOX)屏蔽系统默认错误框。
2、调用RegisterApplicationRecoveryCallback注册恢复函数,该函数将在进程终止前被WER调用。
3、在恢复函数中调用GetApplicationRecoveryProgress确认当前处于ApplicationRecoveryInProgress状态。
4、调用ApplicationRecoveryFinished(FALSE)通知WER放弃自动重启,改由程序自行调用ExitProcess并携带EXCEPTION_EXECUTE_HANDLER退出码。


















