什么是 SafeSEH ?
测试代码:
(借用网上的代码,通过这段代码编译分析)
1 | |
在了解 SafeSEH 之前,我们要首先了解什么是 SEH, 然后才知道为什么会出现 SafeSEH 这个东西。
1. 结构化异常处理(SEH)
结构化异常处理 (SEH) 是 C 和 C++ 的 Microsoft 扩展,用于处理某些特殊代码情况,例如硬件故障,正常。 尽管 Windows 和 Microsoft C++ 支持 SEH,但我们建议在 C++ 代码中使用 ISO 标准 C++ 异常处理。 它提高了代码的可移植性和灵活性。 但是,为了维护现有代码,或者对于特定类型的程序,你仍可能必须使用 SEH。
更加详细的内容,请参考微软的官方文档:https://learn.microsoft.com/zh-cn/cpp/cpp/structured-exception-handling-c-cpp?view=msvc-170
我们下面说的是具体结构问题。
保存结构化异常,在系统内部需要一套结构来保存处理的函数数据, 所有的结构化异常数据都保存在 TEB 中, 也就是线程环境块,是系统为每一个线程分配的一个线程管理的数据块,其中又包括了线程信息块 TIB, TIB 块是 TEB 结构的第一部分,在windows系统中, TIB 的结构为 _NT_TIB, 所以,我们可以通过 TEB的地址,来获取 _NT_TIB 的数据内容。如下:

通过上面的地址,我们分析 _NT_TIB 结构,如下:

我们通过上面的结构,就能看到异常处理的链,保存的是一个 _EXCEPTION_REGISTRATION_RECORD 的结构, 那么我们查看这个结构,数据如下:

我们得到相关的 _EXCEPTION_REGISTRATION_RECORD 的结构如下图:

_EXCEPTION_REGISTRATION_RECORD指向下一个异常结构_EXCEPTION_DISPOSITION异常处理的代码地址
我们继续分析程序,因为上述的结构化异常处理是一个链表,我们打印几个点查看相关的数据,如下图:

我们上图能看处理,异常处理的 Handler 正好是我们程序的异常处理的地方:
1 | |
我们通过上图知道,我们自己的异常处理结构的位置为:0x0136fc0c, 然后我们查看一下 esp的值,也就是当前函数栈帧的所在地址范围, 如下图:

通过上图,我们可以看出来, 异常处理的结构基本就是在栈帧的所在范围。记住这一点,后续的对于通过利用 SEH 实现漏洞利用很重要。
2. 什么是 SafeSEH ?
SafeSEH(安全结构化异常处理程序)是一种针对 32 位可执行文件的 Windows 二进制保护机制,已经存在了一段时间。启用该选项后,链接器会在构建二进制文件时在 SEHandlerTable 中创建一个有效异常处理程序地址列表。这种保护可防止执行损坏的异常处理程序,这是一种常见的利用技术。当抛出异常并且处理程序的地址由攻击者控制时,他们可以使用的地址选择有限。由于所有现代操作系统上都有 DEP(数据执行保护),攻击者选择的地址必须是可执行的,通常这些地址仅限于可执行模块的 .text 部分内的地址。在启用 SafeSEH 的模块中选择地址时,会将其与 SEHandlerTable 中的有效地址列表进行比较,除非找到,否则不会执行。
注意: SafeSEH 只针对 32位的程序,对于64位程序,有其他的处理办法来实现类似思路。
1. VisualStudio开发中设置 /SafeSEH 选项

我们本身的测试程序是加入了 /SafeSEH 选项的,那么我们查看PE结构如下:

在 SE Handler Table 地方存在,这个地方就是保留的 SafeSEH 的一个对照表,用于防止 SEH 被修改
我们在看看,把 /SafeSEH 选项去掉的情况,如下图:

发现 SE Handler Table 已经是空的了,说明不存在这个表了。
3. 关于x64下的SEH
SEH 在 x86下是通过Stack保存的,但在x64位下,是通过PE的节保存的: .pdata, 参考的文章可以看:
x64 exception handling: https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170&viewFallbackFrom=vs-2019Exceptional behavior: the Windows 8.1 X64 SEH Implementation: https://blog.talosintelligence.com/exceptional-behavior-windows-81-x64-seh/Programming against the x64 exception handling support: http://www.nynaeve.net/?p=113&ref=cisco-talos-blogWindows Exceptions (SEH stack x86 + section based x64): https://github.com/qilingframework/qiling/issues/76
参考
结构化异常SEH处理机制详细介绍(一): https://www.cnblogs.com/yilang/p/11233935.htmlAnalyzing Safe Exception Handlers: https://warroom.rsmus.com/analyzing-safe-exception-handlers/