YLLEN

要去看埃菲尔铁塔的顶

欢迎关注本人微博:t.cn/RGSLVUk

SafeSEH 机制浅析

What's ?

        SafeSEH机制是微软为了防止缓冲区溢出时覆盖SEH句柄而采用的新型内存安全机制,当SafeSEH开启时会再异常产生传递时首先校验SEH HANDLE的有效性(文件在编译时会被VS200*以上,在.data写入一张SEH HANDLE TABLE,在call 异常处理函数时对比这个表),

     按照Alex 在 08 年的 Black Hat 大会上披露了 RtlIsValidHandler() 的细节SafeSEH 机制从 RtlDispatchException() 开始:

1. 如果异常处理链不在当前程序的栈中,则终止异常处理调用。

2. 如果异常处理函数的指针指向当前程序的栈中,则终止异常处理调用。(yesterday i end this)

3. 在前两项检查都通过后,调用 RtlIsValidHandler() 进行异常处理有效性检查。



BOOL RtlIsValidHandler( handler )
{
    if (handler is in the loaded image)      // 在加载模块的内存空间内
    {
        if (image has set the IMAGE_DLLCHARACTERISTICS_NO_SEH flag)
            return FALSE;                    // 程序设置了忽略异常处理
        if (image has a SafeSEH table)       // 含有 SafeSEH 表说明程序启用了 SafeSEH
            if (handler found in the table)  // 异常处理函数地址在表中
                return TRUE;
            else
                return FALSE;
        if (image is a .NET assembly with the ILonly flag set)
            return FALSE;                    // 包含 IL 标志的 .NET 中间语言程序
    }

    if (handler is on non-executable page)   // 在不可执行页上
    {
        if (ExecuteDispatchEnable bit set in the process flags)
            return TRUE;                     // DEP 关闭
        else
            raise ACCESS_VIOLATION;          // 访问违例异常
    }

    if (handler is not in an image)          // 在可执行页上,但在加载模块之外
    {
        if (ImageDispatchEnable bit set in the process flags)
            return TRUE;                     // 允许加载模块内存空间外执行
        else
            return FALSE;
    }
    return TRUE;                             // 允许执行异常处理函数
}


基于上面的判断流程

  • 若异常句柄(处理函数)在模块外 AND  DEP 关闭 ,则 pass

  • 若异常句柄(处理函数)在模块内 AND 异常句柄 在safe SEH TABLE中,则 pass

  • 若异常句柄(处理函数)在模块内 AND  image   不是 ILonly 则 pass


绕过 SafeSEH

方法一:覆盖函数返回地址。若攻击对象启用了 SafeSEH 但是 没有启用 GS 或者存在未受 GS 保护的函数,则可用这个方法。

方法二:攻击虚函数表来绕过 SafeSEH。

方法三:将 shellcode 部署在堆中以绕过 SafeSEH。

方法三:利用未启用 SafeSEH 的模块绕过 SafeSEH。(针对上述的 RtlIsValidHandler() 函数的第二种放行可能)

方法四:DEP 关闭时,可以利用加载模块之外的指令作为跳板(见后文示例)。



      综合上面的,可以发现SafeSEH机制已经对SEH句柄进行了很严格的校验,校验函数中的

return false比较多,算是一个黑名单式的检验,但由于包含的情况不全面,所以pass的情况还是很多,接下来就是实验了。


评论

© YLLEN | Powered by LOFTER