首页
社区
课程
招聘
[翻译]绕过SEHOP安全机制
2010-1-7 14:42 35921

[翻译]绕过SEHOP安全机制

2010-1-7 14:42
35921
作者:Stéfan Le Berre (s.leberre@sysdream.com)
          Damien Cauquil (d.cauquil@sysdream.com)
译者:riusksk (泉哥:http://riusksk.blogbus.com)
时间:2010年1月7日

目录
0.        前言
1.        SEHOP简介
2.        溢出攻击中的SEHOP对抗策略
   2.1经典的溢出方法
   2.2 微妙之处
3. Proof Of Concept
        3.1 目标程序与限制条件
        3.2 程序崩溃与利用
4. 结论
5. 鸣谢
6. 参考资料

0.        前言
最近微软在一些windows版本中加入了一种新的安全机制——《Structured Exception Handling Overwrite Protection 》[1 & 2],这些系统有:

• Microsoft Windows 2008 SP0
• Microsoft Windows Vista SP1
• Microsoft Windows 7

目前我们尚未发现任何针对这一安全机制而采取的攻击,但已有少量文章已描述了它的特性及健壮性。的确,SEHOP似乎相当可靠,以致Microsoft发布了一款补丁,以使所有程序在缺省状态下启用这一安全机制。这是否会成为堆栈溢出攻击的未日呢?还没有,详细情况将在后面叙述。

1.        SEHOP简介
SEHOP作为Structured Exception Handling的扩展,用于针对程序中使用的SHE结构进行一些安全检测。SEHOP的核心特性是用于检测程序栈中的所有SHE结构链表,特别是最后一个SHE结构,它拥有一个特殊的异常处理函数指针,指向一个位于ntdll中的函数。下面就是一个经典的SHE链表:

每一SHE结构均拥有指向下一个SHE结构的指针,后面再连接一个指向ntdll!_except_handler4的异常处理函数指针。在通过覆盖SHE结构的栈溢出中,next SHE指针被一些字节码覆盖,而SHE handler被一个指向pop pop ret指令串的地址覆盖掉,该指令串位于一个non-SafeSEH模块中。
这种使用SEHOP的验证算法首次被A. Sotirov在Black Hat 2008大会上批露[3]。下面我们来看一下:

BOOL RtlIsValidHandler(handler)
{
        if (handler is in an image) {
                if (image has the IMAGE_DLLCHARACTERISTICS_NO_SEH flag set)
                        return FALSE;
                if (image has a SafeSEH table)
                if (handler found in the table)
                        return TRUE;
                else
                        return FALSE;
                if (image is a .NET assembly with the ILonly flag set)
                        return FALSE;
                // fall through
        }
        if (handler is on a non-executable page) {
                if (ExecuteDispatchEnable bit set in the process flags)
                        return TRUE;
                else
                // enforce DEP even if we have no hardware NX
                raise ACCESS_VIOLATION;
        }
        if (handler is not in an image) {
                if (ImageDispatchEnable bit set in the process flags)
                        return TRUE;
                else
                        return FALSE; // don't allow handlers outside of images
        }
// everything else is allowed
return TRUE;
}
[...]
// Skip the chain validation if the
DisableExceptionChainValidation bit is set
if (process_flags & 0x40 == 0) {
        // Skip the validation if there are no SEH records on the
        // linked list
        if (record != 0xFFFFFFFF) {
                // Walk the SEH linked list
                do {
                        // The record must be on the stack
                        if (record < stack_bottom || record > stack_top)
                                goto corruption;
                        // The end of the record must be on the stack
                        if ((char*)record + sizeof(EXCEPTION_REGISTRATION) > stack_top)
                                goto corruption;
                        // The record must be 4 byte aligned
                        if ((record & 3) != 0)
                                goto corruption;
                        handler = record->handler;
                        // The handler must not be on the stack
                        if (handler >= stack_bottom && handler < stack_top)
                                goto corruption;
                        record = record->next;
                } while (record != 0xFFFFFFFF);
                // End of chain reached
                // Is bit 9 set in the TEB->SameTebFlags field?
                // This bit is set in ntdll!RtlInitializeExceptionChain,
                // which registers FinalExceptionHandler as an SEH handler
                // when a new thread starts.
                if ((TEB->word_at_offset_0xFCA & 0x200) != 0) {
                        // The final handler must be ntdll!FinalExceptionHandler
                        if (handler != &FinalExceptionHandler)
                                goto corruption;
                }
        }
}

下面我们来考虑一些限制:
• SHE handler必须指向non-SafeSEH module
• 内存页必须可执行
• SHE链表不应被篡改,并且位于链表末端的SHE结构必须为特定值(next SHE指针值为0xFFFFFFFF,SHE handler也必须为一特定值)
• 所有的SHE结构必须为4-byte对齐
• 最后一个SHE结构的handler必须正确指向ntdll中的ntdll!FinalExceptionHandler例程
• 所有SHE指针必须指向栈中

2.        溢出攻击中的SEHOP对抗策略
2.1 经典的溢出方法
下面是覆盖SHE结构的经典溢出方法的结构图:

SHE handler指向POP POP RET指令串,next SHE中的栈地址被jmp 06 nop nop(机器码:EB 06 90 90)替换掉。当处理一个程序异常时,Windows将控制权传给SHE链表中的异常处理程序。当第一个异常处理函数被覆盖掉后,程序的执行流程重定向到POP POP RET指令串中(代替真实的异常处理函数)。该指令串将执行到当前SHE结构中next SHE的前两个字节(jmp 06),以此直接跳转到我们的shellcode。这样,SHE链表就被拆分了:

SHE结构中的next SEH的前两字节(90 90)从不被执行,它主要是用于填充字符,以构造出一个DWORD大小的有效栈地址。当然,我们也可以改变另外的两字节来使其指向一个有效栈地址,而将这两字节改为跳转指令(EB 06)。这一DWORD值当被调用时,它相当于一个有效的栈地址与一个有效指令的结合以实现跳转。如果我们伪造SHE结构中的这一DWORD值指向的栈地址,那么我们就可伪造整个SHE链表,并控制下一个SHE结构以使此链表有效。

2.2 微妙之处
还有一个问题:哪一被编码的跳转指令可以代替4字节对齐地址?只有一指令与其相配:JE(机器码为0x74),该指令是一条件跳转:只有当Z标志被设置时才实现跳转。在Windows在处理异常时,Z标志是默认关闭的,我们必须通过执行一指令来计算出零值,以设置该标志位。Xor指令似乎是不错的选择,看来我们的解决方法已经很明了了:跳至XOR,POP,POP,RET指令串,以便将JE指令解释为JMP。这就是SEHOP绕过技术的微妙之处。
XOR,POP,POP,RET指令串并不难找到,我们可以通过查找返回NULL值的函数的末端来找到这些指令串:
XOR EAX, EAX
POP ESI
POP EBP
RET
为了确保该方案可行,我们就以XOR,POP,POP,RET指令串来编写一份PoC测试一下。
已知第一个SEH结构位于0x0022FD48,我们就可以在0x0022FD74处构造第二个SHE结构,它的next SHE指针值为0xFFFFFFFF,handler指向ntdll!FinalExceptHandler。如果我们将第一个SHE结构中的handler指向XOR,POP,POP,RET指令串,那么我们就可以将执行流程重定向到任何地方,真正地破坏掉SHE链表。具体地,我们可以重新伪造一个有效的SHE链表,以使其重定向到特定的shellcode。
        另一个主要限制是Microsoft Windows 7和vista中的ASLR安全机制。我们知道程序的利用需要依赖于ntdll!FinalExceptHandler的地址,但这一地址在每次电脑重启后都会发生改变。Ntdll ImageBase在重启时都被随机化,这样就增加攻击的难度。我们针对ASLR(未经逆向分析)进行一些测试,结果表明ImageBase似乎在16位中只有9位发生随机化,也就是说,在超过512次机会中你只有一次机会可以成功地绕过SEHOP实现溢出攻击。

3. Proof Of Concept
  3.1 目标程序与限制条件
我们编写一段小程序,以在Windows 7下演示这一技术。这一程序只是复制一个文件(OwnMe.txt)的内容到内存中,并在操作中实现栈溢出,以引发可被异常处理程序捕获的异常。
我们需要完成以下任务:
• 伪造一个有效的SEH链表
• 将最后一个SEH结构中的handler指向ntdll!FinalExceptHandler
• 在栈中放置shellcode(与Windows 7相兼容)
• 定位内存中的XOR,POP,POP,RET指令串地址
首先,XOR,POP,POP,RET指令串是已知的,因为我们已经将其放置在程序代码中了,我们可以发现该指令串位于内存地址0x004018E1中。
  3.2 程序崩溃与利用
当程序崩溃时,可发现:
   0012F700 41414141 Pointer to next SEH record
   0012F704 41414141 SE handler
接着我们需要利用存储在0x0012F774中的第二个SEH结构来伪造SEH链表,这一SEH结构中next SEH指针值为0xFFFFFFFF,SHE handler指向ntdll!FinalExceptHandler。然后位于0x0012F700的SEH结构被篡改,使其指向仿造的SHE结构,并将handler设置为0x004018E1,同时在每一SHE结构之前写入一跳转指令(JMP+8),以避免数据段被执行。整个利用的工作流程如下图所示:

Shellcode将执行calc.exe:

注意:目标程序及exploit均已打包成zip文件,可在Sysdream网站上[4]下载到。

4. 结论
SEHOP并不是对抗栈溢出的终极防护。自从SafeSEH扩展被公布之后,很多人认为它是不可突破的。这里我们只是演示了在一些情况下Structured Exception Handling Overwrite Protection是可能绕过的。但SEHOP结合ASLR和DEP使用,是一种优秀的本地安全机制,这点是不可否认的。

5. 鸣谢
http://sysdream.com/
http://ghostsinthestack.org/
http://virtualabs.fr/

6. 参考资料
[1] Preventing the Exploitation of Structured Exception Handler (SEH) Overwrites with SEHOP:
http://blogs.technet.com/srd/archive/2009/02/02/preventing-the-exploitation-of-seh-overwriteswith-
sehop.aspx
[2] SEHOP per-process opt-in support in Windows 7:
http://blogs.technet.com/srd/archive/2009/11/20/sehop-per-process-opt-in-support-in-windows-
7.aspx
[3] Bypassing Browser Memory Protections: http://taossa.com/archive/bh08sotirovdowd.pdf
[4] ZIP containing our target program & exploit http://www.sysdream.com/SEHOP.zip

[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

上传的附件:
收藏
点赞7
打赏
分享
最新回复 (12)
雪    币: 26415
活跃值: (18468)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2010-1-7 14:46
2
0
riusksk辛苦了,2010好的开端
雪    币: 408
活跃值: (1875)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
riusksk 41 2010-1-7 15:41
3
0
多谢kanxue大哥,今天可以说是我大学生活的最后一天了,翻译一篇文章记念一下,明天将启程去实习了!原本是要将exploit编写系列教程给翻译完的,但第五篇由cntrump翻译了一半,我一直没有继续去翻译这文章,之前答应moonife要搞定的,但到现在一直没动手去翻译,这一专题原本早就该完成的,没想到一直拖到现在,于是就找了这篇比较短的文章翻译了一下,算做补偿吧
雪    币: 733
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
非安全 17 2010-1-14 04:16
4
0
学习。。。。。
雪    币: 266
活跃值: (24)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
youstar 2 2010-1-14 17:03
5
0
学习研究!多谢!
雪    币: 112
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sagittar 2010-1-18 09:43
6
0
好东西 留名标记 学习 ^_^
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
天行客 2010-1-27 17:44
7
0
泉哥,很活跃。
文章很好。
雪    币: 436
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mlzz 2010-2-23 12:05
8
0
和好很强大,对我等e文水平惨的筒子帮助很大啊。感谢!
雪    币: 246
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
gtboy 2 2010-2-24 16:30
9
0
还是中文看的舒服
英文总是看的云山雾罩的
雪    币: 386
活跃值: (150)
能力值: (RANK:110 )
在线值:
发帖
回帖
粉丝
wingdbg 2 2011-1-1 15:46
10
0
汇编与二进制的摆设艺术
雪    币: 480
活跃值: (281)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
tishion 9 2013-10-31 16:37
11
0
爽翻了,现在碰了一个问题,程序Crash之后进入了SEH处理,但是却又在RtlIsValidHandler这个函数里触发了二次异常,最终栈就被

a4d 001004ec 7c94a89d 3094b0e4 0014b0e4 00100580 ntdll!RtlIsValidHandler+0x56 (FPO: [Non-Fpo])
a4e 00100568 7c92e48a 00000000 0010059c 00100580 ntdll!RtlDispatchException+0x7e (FPO: [Non-Fpo])
a4f 00100568 7c9701b6 00000000 0010059c 00100580 ntdll!KiUserExceptionDispatcher+0xe (FPO: [2,0,0])
这三个函数给爆栈了
满头大汗啊……
雪    币: 10042
活跃值: (15979)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhczf 2013-10-31 16:54
12
0
来学习一下技术知识,了解一下详情
雪    币: 43
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hbcld 2014-1-18 11:31
13
0
谢谢,赞大牛
游客
登录 | 注册 方可回帖
返回