Buffer Overflow
Practice stack based buffer overflows! (link to the walkthrough below)
Last updated
Practice stack based buffer overflows! (link to the walkthrough below)
Last updated
We will use the Immunity Debugger with the Mona.py
script
We need to open Immunity Debugger, open a binary (oscp.exe) and set a working directory with Mona.py script inside:
Don't forget to re-run the binary everytime before you run theexploit.py
script
Create the Fuzzing script:
Run the fuzzer.py
script using python: python3 fuzzer.py
. The fuzzer will send increasingly long strings comprised of As. If the fuzzer crashes the server with one of the strings, the fuzzer should exit with an error message
Make a note of the largest number of bytes that were sent
Create another script to perform a Crash Replication & Controlling EIP:
Generate the payload
value with /opt/tools/metasploit-framework/tools/exploit/pattern_create.rb -l <largest nb bytes + 400 bytes>
Run the exploit.py
Run !mona findmsp -distance <largest nb bytes + 400 bytes>
inside the input box of Immunity Debugger
Get the offset
value from the log data of Mona inside this line EIP contains normal pattern : ... (offset XXXX)
and update the offset
variable of the exploit.py
script.
Set the retn
variable to BBBB
Restart oscp.exe
in Immunity and run the modified exploit.py
script again. The EIP register should now be overwritten with the 4 B's (e.g. 42424242).
!mona
: This tells Immunity Debugger to execute a Mona.py command. The plugin is invoked using !mona
.
findmsp
: This is a Mona.py feature that searches for MSP (Module Stack Pointer) or Metasploit Pattern. It looks for specific patterns that are used during the process of detecting buffer overflow conditions.
In a buffer overflow exploit, attackers need to find out where the "Saved Return Pointer" (EIP) is overwritten. findmsp
helps locate the offset at which the saved return pointer is corrupted in the crash.
-distance 600
: This specifies the maximum distance (600 bytes in this case) to search from the start of the buffer to the point where the buffer overflow might occur. Essentially, it tells Mona.py to look for the pattern within 600 bytes of the buffer's input to locate the exact offset of the crash.
The Finding Bad Characters step in a buffer overflow exploit is critical for ensuring that the payload or shellcode you inject does not get corrupted during transmission or execution.
Certain characters, known as bad characters, can cause problems like truncation, improper parsing, or unintended behavior during the buffer overflow.
Let the retn
variable with "BBBB" during this step
Generate a bytearray using !mona bytearray -b "\x00"
. The location should be C:\mona\oscp\bytearray.bin
(depends on your working directory). It will be useful to compare what is in the memory to the generated list
Generate a string of bad characters from \x01
to \xff
with this script:
Set the payload
variable to the string of bad chars the script generates
Restart oscp.exe
in Immunity and run the modified exploit.py
script again
Make a note of the address to which the ESP register points and use it in the following mona command: !mona compare -f C:\mona\oscp\bytearray.bin -a <address>
A window ("mona Memory comparison results") shows the results of the comparison, indicating any characters that are different in memory to what they are in the generated bytearray.bin
file
Make a note of the badchars
Generate a new bytearray in mona, specifying these new badchars along with \x00
Repeat all the steps until the results status returns "Unmodified"
The Finding a Jump Point step in a buffer overflow exploit is crucial after identifying bad characters. Once you have confirmed that your payload can be safely injected into the buffer (without interference from bad characters), the next step is to redirect the program’s execution flow to your payload. This is done by finding a jump point, typically using ROP (Return Oriented Programming) techniques or by overwriting the EIP (Extended Instruction Pointer) with a memory address that points to code that can transfer execution to your shellcode.
Run this command !mona jmp -r esp -cpb "\x00"
to find automate the search of JMP ESP
instructions with the -cpb
option with all the badchars you identified.
Choose an address from the "Log data" window and update your exploit.py
script, setting the retn
variable to the address, written backwards
Run the following msfvenom command:
Copy the generated C code strings and integrate them into your exploit.py
script payload
variable using the following notation:
Prepending NOPs to your shellcode is a simple yet powerful technique to:
Increase the likelihood of successful execution by creating a "landing zone."
Handle minor inaccuracies in the jump address or offsets.
Avoid stack alignment issues or conflicts with bad characters.
Provide space for shellcode decoders and other exploit elements.
Set the padding
variable to a string of 16 or more "No Operation" (\x90
) bytes:
With the correct prefix
, offset
, return address
, padding
, and payload
set, you can now exploit the buffer overflow to get a reverse shell.
Start a netcat listener
Restart oscp.exe
in Immunity and run the modified exploit.py
script again. Your netcat listener should catch a reverse shell!
What is the EIP offset for OVERFLOW1?
2400 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW1?
What is the EIP offset for OVERFLOW2?
1100 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW2?
What is the EIP offset for OVERFLOW3?
1700 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW3?
What is the EIP offset for OVERFLOW4?
2500 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW4?
What is the EIP offset for OVERFLOW5?
800 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW5?
What is the EIP offset for OVERFLOW6?
1500 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW6?
What is the EIP offset for OVERFLOW7?
1800 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW7?
What is the EIP offset for OVERFLOW8?
2200 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW8?
What is the EIP offset for OVERFLOW9?
2000 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW9?
What is the EIP offset for OVERFLOW10?
1000 bytes (fuzzer)
In byte order (e.g. \x00\x01\x02) and including the null byte \x00, what were the badchars for OVERFLOW10?
Update the payload
variable in your exploit.py
script and remove the new badchars as well
In our case, the goal si to find a JMP ESP
address instruction and overwrite it to the EIP