image_load_config_directory中sehandlercount非零才表示启用dep;需先检查datadirectory[10].size>0,再按结构size判断版本并读取对应偏移的sehandlercount字段。

怎么看 IMAGE_LOAD_CONFIG_DIRECTORY 里有没有 SEHandlerCount
DEP(Data Execution Prevention)是否启用,关键不在于 PE 头本身,而在于加载配置目录(Load Configuration Directory)中是否包含有效的结构体,且其 SEHandlerCount 字段非零 —— 这表示启用了 Safe Exception Handlers,是 Windows 启用硬件级 DEP 的必要条件之一。
实际解析时容易直接跳去读 IMAGE_NT_HEADERS 或 IMAGE_OPTIONAL_HEADER,但这两者根本不存 DEP 相关标志;必须定位到可选头里的 DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG],再按 RVA 解析出 IMAGE_LOAD_CONFIG_DIRECTORY 结构。
- 先检查
OptionalHeader.DataDirectory[10].Size是否 > 0(10是IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG的索引) - 若 size > 0,用该
VirtualAddress转为文件偏移,读取至少sizeof(IMAGE_LOAD_CONFIG_DIRECTORY)字节(注意:不同 Windows SDK 版本结构大小不同,Win10+ 常见为 144 字节) - 确认结构体中
SEHandlerCount字段(偏移 0x4C,32 位下)或SEHandlerCount(64 位下偏移 0x58)是否 > 0 - 若
SEHandlerCount == 0,即使其他字段存在,也说明未启用 SafeSEH,大概率未开启 DEP(除非程序用/NXCOMPAT:NO显式禁用)
为什么 IMAGE_OPTIONAL_HEADER.DllCharacteristics 的 IMAGE_DLLCHARACTERISTICS_NX_COMPAT 不够可靠
这个标志只是告诉系统“我兼容 NX(即 DEP)”,不代表实际启用;它只影响加载器是否允许在 DEP 开启的系统上运行该模块,不决定 DEP 是否对当前模块生效。
常见误判场景:程序编译时加了 /NXCOMPAT,DllCharacteristics 里确实设置了 IMAGE_DLLCHARACTERISTICS_NX_COMPAT,但链接时没配 /SAFESEH 或没生成有效加载配置目录,结果运行时仍被当作“不支持 DEP”处理。
-
IMAGE_DLLCHARACTERISTICS_NX_COMPAT是软声明,纯属“自我申报” - Windows 内核真正执行 DEP 策略时,会查
IMAGE_LOAD_CONFIG_DIRECTORY.SEHandlerCount和SEHandlerTable的有效性 - 32 位程序若缺失
IMAGE_LOAD_CONFIG_DIRECTORY,即使有NX_COMPAT,也会被降级为无 DEP 保护(尤其在旧版 Windows 上) - 64 位程序强制要求
SEHandlerCount有效,否则加载失败(报错STATUS_INVALID_IMAGE_FORMAT),所以反而更可信
解析时怎么避开结构体版本混乱和字段偏移陷阱
Windows SDK 中 IMAGE_LOAD_CONFIG_DIRECTORY 在不同年代定义差异极大:VC2008、VC2015、WDK 10 都扩展了字段,导致固定偏移读取极易越界或错位。比如 SEHandlerCount 在 VS2008 定义中根本不存在,是后来才加的。
不能硬写 *(DWORD*)((BYTE*)config + 0x4C) 就完事 —— 你得先知道这个 config 指向的是哪个版本的结构。
- 优先读
Size字段(结构体开头 4 字节),它标识了当前结构体的实际字节数(如 64、72、144) - 根据
Size判断版本:Size == 64→ VS2003/2005;Size >= 144→ Win10+ WDK;中间值需查对应 SDK 文档 -
SEHandlerCount在Size >= 72的结构中才存在,且 32/64 位偏移不同(32 位:0x4C;64 位:0x58) - 务必做边界检查:若
Size ,直接认为无 <code>SEHandlerCount,不尝试读取
用 dumpbin /headers 快速验证,但别全信输出
开发机上最省事的方式是用微软工具交叉验证:dumpbin /headers xxx.exe | findstr "NX",看到 application can run only on OS with SEH validation 就基本确定开了 DEP。
但它底层也是解析同一套数据,所以遇到混淆或手工构造的 PE(比如加壳后清空了 LoadConfig 目录),dumpbin 可能显示 “no load config” 却实际运行时受 DEP 保护(因为系统 fallback 到页表级策略)。
-
dumpbin不显示SEHandlerCount数值,只给结论性描述,无法用于自动化判断 - 某些加壳器会伪造
DataDirectory[10]条目指向无效地址,dumpbin可能静默忽略,但你的解析代码若没做指针校验就会崩 - 真正上线的检测逻辑,必须自己做 RVA→FOA 转换、结构体 size 校验、字段存在性判断,不能依赖工具输出
最易被忽略的一点:PE 文件可能根本没有 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 条目(Size == 0),此时无论编译选项如何,Windows 都不会对该模块启用基于异常处理程序校验的 DEP —— 但页级 DEP(如堆、栈不可执行)仍可能由系统策略全局开启,这已超出 PE 头能表达的范围。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!









