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

Windows逆向工程提升之IMAGE_RUNTIME_FUNCTION_ENTRY

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

目录

异常处理信息在 PE 文件中的存放

核心数据结构

RUNTIME_FUNCTION

UNWIND_INFO

UNWIND_CODE

SCOPE_TABLE

图解

与 x86 平台 SEH 的对比

x86 SEH

x64 SEH

执行图解

IMAGE_DATA_DIRECTORY

IMAGE_RUNTIME_FUNCTION

UNWIND_INFO

UNWIND_CODE

SCOPE_TABLE


异常处理信息在 PE 文件中的存放

  • PE异常目录: 在 PE 文件的 Data Directory 中,IMAGE_DIRECTORY_ENTRY_EXCEPTION 指向异常表,通常位于 .pdata 段。该段中包含整个模块中所有函数的异常信息条目。
  • 功能: Windows x64 不在每个函数的栈中设置 SEH 帧,而是在静态数据(即异常表中)记录每个函数的异常和栈展开信息,在异常发生时,通过查询该表快速定位出当前函数对应的 RUNTIME_FUNCTION 数据,从而执行栈展开。

核心数据结构

RUNTIME_FUNCTION

typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY {  DWORD BeginAddress;   // 函数起始 RVA,相对于模块基址  DWORD EndAddress;     // 函数结束 RVA  union {  DWORD UnwindInfoAddress;  // 指向 UNWIND_INFO 结构的 RVA(通常)   DWORD UnwindData;  } DUMMYUNIONNAME;  
} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;  
  •  每个 RUNTIME_FUNCTION 条目描述一个函数的异常与栈展开信息。
  • 在异常处理过程中,系统会根据错误地址在该表中查找匹配的函数范围。如果找到匹配的 BeginAddress 与 EndAddress,则根据 UnwindInfoAddress 获取对应的展开信息。

UNWIND_INFO

typedef struct _UNWIND_INFO {  UCHAR Version : 3;           // 版本号(通常为1)  UCHAR Flags : 5;             // 标志(如是否包含异常处理程序)UCHAR SizeOfProlog;          // 函数序言(Prolog)的字节数  UCHAR CountOfCodes;          // 展开代码条目数量(数组中 UNWIND_CODE 个数)  UCHAR FrameRegister : 4;     // 帧指针寄存器(如 RBP、RDI 等)  UCHAR FrameOffset   : 4;     // 帧指针偏移,用 16 字节单位(FP = RSP + FrameOffset * 16)  UNWIND_CODE UnwindCode[1];   // 不定长度数组,描述具体的栈展开操作  // 后续紧跟可选字段:  // 1. 如果设置了 UNW_FLAG_EHANDLER 或 UNW_FLAG_UHANDLER,则紧跟有 ExceptionHandler 和 ExceptionData。  // 2. 如果设置了 UNW_FLAG_CHAININFO,则后续为一个 RUNTIME_FUNCTION 结构。  
} UNWIND_INFO, *PUNWIND_INFO;  

UNWIND_CODE

typedef union _UNWIND_CODE {  struct {  UBYTE CodeOffset;     // 在函数中相对于 Prolog 起始处的偏移量,指定该操作的开始位置  UBYTE UnwindOp : 4;   // 展开操作类型,属于 UNWIND_OP_CODES 之一  UBYTE OpInfo   : 4;   // 补充信息,根据不同的 UnwindOp 含义不同  };  USHORT FrameOffset;       // 某些操作直接用来描述栈帧内偏移的值  
} UNWIND_CODE, *PUNWIND_CODE;  typedef enum _UNWIND_OP_CODES {UWOP_PUSH_NONVOL = 0, /* info == register number */UWOP_ALLOC_LARGE,     /* no info, alloc size in next 2 slots */UWOP_ALLOC_SMALL,     /* info == size of allocation / 8 - 1 */UWOP_SET_FPREG,       /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */UWOP_SAVE_NONVOL,     /* info == register number, offset in next slot */UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */UWOP_SAVE_XMM128 = 8, /* info == XMM reg number, offset in next slot */UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */UWOP_PUSH_MACHFRAME   /* info == 0: no error-code, 1: error-code */
} UNWIND_CODE_OPS;

SCOPE_TABLE

typedef struct _SCOPE_TABLE {  DWORD Count;  struct {  DWORD BeginAddress;  DWORD EndAddress;  DWORD HandlerAddress;  DWORD JumpTarget;  } ScopeRecord[1];  
} SCOPE_TABLE, *PSCOPE_TABLE;  

图解

┌──────────────────────┐        ┌──────────────────────┐
│ RUNTIME_FUNCTION     │        │ UNWIND_INFO          │
├──────────────────────┤        ├──────────────────────┤
│ BeginAddress         │        │ Version/Flags        │
│ EndAddress           │        │ SizeOfProlog         │
│ UnwindInfoAddress    |─────── | CountOfCodes         │
└──────────────────────┘        │ FrameRegister/Offset ││ UnwindCode[]         ││ ExceptionHandler      ─┐└──────────────────────┘ ││▼┌──────────────────────┐│ SCOPE_TABLE          │├──────────────────────┤│ Count                ││ ScopeRecord[0..N]    │└──────────────────────┘

与 x86 平台 SEH 的对比

x86 SEH

  • 基于链表机制,在每个函数的栈上构造 SEH 帧(链表节点)来捕获异常信息。
  • 异常处理信息嵌入在函数栈区,处理过程依赖于栈上注册的异常处理例程。

x64 SEH

  • 将所有异常相关信息集中存放于静态数据区(PE 文件中的异常目录),运行时通过查询定位当前函数展开信息。
  • 栈展开完全依赖预编译生成的 UNWIND_INFO 和 UNWIND_CODE,由操作系统提供支持。

执行图解

IMAGE_DATA_DIRECTORY

IMAGE_RUNTIME_FUNCTION

UNWIND_INFO

UNWIND_CODE

SCOPE_TABLE

http://www.xdnf.cn/news/661519.html

相关文章:

  • 按键状态机
  • FFmpeg 4.3 H265 二十二.3,avformat_open_input 支持打开的协议
  • 07-多线程案例-任务调度
  • NoteGen 如何使用 AI 进行记录
  • set和map简单模拟实现
  • TCP 三次握手过程详解
  • 【Java学习笔记】抽象类
  • 时间的基本概念及相关技术
  • 通用寄存器 专用寄存器
  • 大模型训练中的GPU作用解析
  • 项目三 - 任务8:实现词频统计功能
  • 基于Geotools的Worldpop世界人口tif解析-以中国2020年数据为例
  • 北京大学肖臻老师《区块链技术与应用》公开课:02-BTC-密码学原理
  • Excel快捷键大全
  • 深入理解Java装饰器模式:动态扩展对象功能的优雅之道
  • USB设备状态
  • pyhton基础【5】循环
  • uniapp 小说成品源码
  • Python爬虫实战:研究Selenium框架相关技术
  • NAT、代理服务、内网穿透
  • Python训练营打卡Day37
  • 经典文献阅读之--RT-Grasp(通过MLLM进行推理调优的机器人抓取)
  • 如何设计ES的冷热数据分离架构?Elasticsearch 集群如何实现高可用?如何避免脑裂问题?如果出现脑裂如何恢复?
  • 6.1 Q1|广州医科大学GBD发文 | 良性前列腺增生与合并症之间的相关性
  • mysql ACID 原理
  • OpenCV CUDA模块图像过滤------创建一个 Sobel 滤波器函数createSobelFilter()
  • 高并发下使用防重表做防重案例
  • Linux 常用操作步骤
  • ubantu给github配置ssh
  • Unity—lua基础语法