当前位置: 首页 > news >正文

Windows逆向工程提升之x86结构化异常SEH处理机制

  • 公开视频 -> 链接点击跳转公开课程
  • 博客首页 -> ​​​链接点击跳转博客主页

目录

SEH的派发流程

异常发生

遍历 SEH 链表

异常处理程序

栈展开

SEH的底层机制

异常存储

异常记录

上下文记录

SEH的存储方式

ScopeTable

tryLevel

示例代码


SEH的派发流程

异常发生

  • 操作系统检测到异常,例如非法内存访问、除零等。
  • 调用内核的专有机制(如 KiUserExceptionDispatcher),将异常信息传递给用户模式。

遍历 SEH 链表

  • 系统通过 FS:[0] 找到当前 SEH 链表头节点。
  • 遍历链表,每遇到一个节点时调用它的 Handler 函数,并将异常上下文作为参数传递给过滤器 __except。

异常处理程序

  • 如果异常处理程序 (Handler) 返回 EXCEPTION_EXECUTE_HANDLER,则表示该处理器愿意处理异常,跳转到 __except 块。
  • 如果没有找到处理器,则退出当前进程。

栈展开

  • 如果处理器未完全解决异常,栈数据会逐层展开。
  • 如果处理完成,则控制权返回到调用者。

SEH的底层机制

异常存储

  • 链式结构:通过EXCEPTION_REGISTRATION_RECORD结构体链表实现,每个线程的FS:[0]指向当前处理链头部。
  • 每个线程维护一个异常链表,用于记录当前线程中所有已注册的 SEH 处理器。
  • 异常链表结构存储在栈中,当异常发生时,操作系统会遍历该链表以找到合适的异常处理程序。
struct _EXCEPTION_REGISTRATION_RECORD {_EXCEPTION_REGISTRATION_RECORD* Next; //下一个节点(链表)PEXCEPTION_ROUTINE Handler;           //异常处理函数
};

异常记录

  • 当异常发生时,操作系统生成一个 EXCEPTION_RECORD 结构体,用于描述异常的详细信息,如异常代码、异常标志、异常地址、参数等。
typedef struct _EXCEPTION_RECORD {  DWORD ExceptionCode;                      // 异常代码  DWORD ExceptionFlags;                     // 异常标志  struct _EXCEPTION_RECORD *ExceptionRecord;// 链接到上一个异常记录  PVOID ExceptionAddress;                   // 异常发生的指令地址  DWORD NumberParameters;                   // 附加参数个数  ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];  
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;typedef enum _EXCEPTION_DISPOSITION
{ExceptionContinueExecution,ExceptionContinueSearch,ExceptionNestedException,ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
  • ExceptionCode:标识异常类型。

  • ExceptionFlags:标识异常处理标志,是否可恢复等。

  • ExceptionAddress:异常发生的指令地址。

  • NumberParameters:异常附加参数个数。

上下文记录

  • 保存并传递发生异常时的CPU状态(寄存器、堆栈等)。
  • 例如代码执行前后的寄存器状态。

SEH的存储方式

  • Windows SEH采用处理器分离模式,而不是直接存储用户的except块地址,主要出于以下考虑:
		[ebp - 18]0x0073FCA4  58 fc 73 00  	esp[ebp - 14]0x0073FCA8  42 f2 d3 60   exceptioninformation[ebp - 10]0x0073FCAC  28 fd 73 00	next node[ebp - 0c]0x0073FCB0  e2 15 be 00	handler(oep)[ebp - 08]0x0073FCB4  08 66 be 00	scopetable[ebp - 04]0x0073FCB8  ff ff ff ff	trylevel[ebp + 00]0x0073FCBC  dc fc 73 00	old ebp[ebp + 04]0x0073FCC0  13 1d be 00	ret addr
  1. 统一处理机制__except_handler3作为通用入口点,为所有异常提供一致的处理框架

  2. 支持复杂逻辑:允许实现过滤器表达式评估、嵌套异常和异常转发

  3. 优化代码大小:避免为每个try/except块生成独立的处理函数

  4. 安全性考虑:通用处理器可以执行额外验证和安全检查

ScopeTable
  • 定义​​:ScopeTable是编译器生成的静态数据表,每个条目描述一个__try块的作用域和处理逻辑。__except_handler3通过此表匹配当前执行的代码位置与异常处理块。
typedef struct _SCOPETABLE_ENTRY {DWORD EnclosingLevel;    // 外层tryLevel(类似作用域链)DWORD FilterFunc;        // 过滤器函数地址(__except括号内的表达式)DWORD HandlerFunc;       // 异常处理代码地址(__except块内的代码)
} SCOPETABLE_ENTRY;
tryLevel
  • 定义​​:tryLevel是一个栈帧局部变量(通常位于[ebp-4]),用于标识当前活动的__try块层级。
  • 值范围​​:
    • -1(0xFFFFFFFF):表示无活动的__try块。
    • 0, 1, ...:索引值,对应ScopeTable中的条目,表示当前处于哪一层__try块。
示例代码
#include <stdio.h>
#include <Windows.h>int main()
{/*EXCEPTION_REGISTRATION_RECORDNext;Handler;scopeTabletryLevel[ebp - 18]0x0073FCA4  58 fc 73 00  	esp[ebp - 14]0x0073FCA8  42 f2 d3 60   exceptioninformation[ebp - 10]0x0073FCAC  28 fd 73 00	next node[ebp - 0c]0x0073FCB0  e2 15 be 00	handler(oep)[ebp - 08]0x0073FCB4  08 66 be 00	scopetable[ebp - 04]0x0073FCB8  ff ff ff ff	trylevel[ebp + 00]0x0073FCBC  dc fc 73 00	old ebp[ebp + 04]0x0073FCC0  13 1d be 00	ret addr00E11C30 55                   push        ebp  00E11C31 8B EC                mov         ebp,esp  00E11C33 6A FF                push        0FFFFFFFFh  00E11C35 68 08 66 E1 00       push        0E16608h  00E11C3A 68 E2 15 E1 00       push        offset __except_handler3 (0E115E2h)  00E11C3F 64 A1 00 00 00 00    mov         eax,dword ptr fs:[00000000h]  00E11C45 50                   push        eax  00E11C46 64 89 25 00 00 00 00 mov         dword ptr fs:[0],esp [esp + 0]	seh.node[esp + 4]	__except_handler300E11C4D 83 C4 B8             add         esp,0FFFFFFB8h  00E11C50 53                   push        ebx  00E11C51 56                   push        esi  00E11C52 57                   push        edi  00E11C53 89 65 E8             mov         dword ptr [ebp-18h],esp  00E11C56 C7 45 FC 00 00 00 00 mov         dword ptr [ebp-4],0  00E11C5D C7 45 FC FF FF FF FF mov         dword ptr [ebp-4],0FFFFFFFFh  	*/int a = 1;__try{// [ebp - 04] trylevel = 0/*	0x01016608  ff ff ff ff  ....0x0101660C  60 19 01 01  `...0x01016610  66 19 01 01  f...		*/a = 2;__try{// [ebp - 04] trylevel = 1/*		0x01016614  00 00 00 00  ....0x01016618  40 19 01 01  @...0x0101661C  46 19 01 01  F...		*/a = 3;__try{// [ebp - 04] trylevel = 2/*0x01016620  01 00 00 00  ....0x01016624  20 19 01 01   ...0x01016628  26 19 01 01  &...*/a = 4;}__except (EXCEPTION_EXECUTE_HANDLER){a = 5;}}__except (EXCEPTION_EXECUTE_HANDLER){a = 6;}}__except (EXCEPTION_EXECUTE_HANDLER){a = 7;}return 0;
}

相关文章:

  • 非接触式互连:当串扰是您的朋友时
  • npm修改镜像的教程,将npm镜像修改为国内地址增加下载速度
  • SpringBoot-11-基于注解和XML方式的SpringBoot应用场景对比
  • Kubernetes(k8s)全面解析:从入门到实践
  • 以前端的角度理解 Kubernetes(K8s)
  • xy坐标上如何判定两个矩形是否重合
  • 什么是ESLint?它有什么作用?
  • 指针、空间地址
  • 当NLP能模仿人类写作:原创性重构而非终结
  • 华为OD机试真题—— 货币单位换算(2025B卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
  • 佳源科技退卷IPO:曾于2023年7月过会,原计划募资约9亿元
  • CAPL自动化-诊断Demo工程
  • 达梦数据库-学习-23-获取执行计划的N种方法
  • Leetcode 587. 安装栅栏
  • 针对面试- RabbitMQ消息队列篇
  • 基础编程题目集 7-1 厘米换算英尺英寸
  • java基础(面向对象高级部分)
  • 快速扩容VHD文件的DiskPart命令指南
  • 临床研究统计分析核心概念解析
  • 【AI智能体】Spring AI Tool 从使用到实战详解
  • 做网站需要前置审批/如何做推广引流赚钱
  • 用什么软件制作动画视频/来宾网站seo
  • 定制一个网站多少钱/关键词热度分析工具
  • 动物自己做的网站/网站底部友情链接代码
  • 金属材料网站建设/2022最新时事新闻及点评
  • angular 做网站/软文营销范文