-
Notifications
You must be signed in to change notification settings - Fork 52
Buffer Overflows
Begin by sending a payload that overflows the buffer (For the sake of tradition, make sure it's all 'A's). If the program is vulnerable, we will see an error in Immunity saying 'Access violation when executing [41414141]' demonstrating that we overwrote the SRP with 'AAAA'
.
This will usually result in a Denial of Service, but will give an indication that the program is vulnerable to a Buffer Overflow. This is where we also begin the development of our exploit, either from scratch or based on a known exploit.
To move forward, we need to know the offset between the beginning of our overflowing variable and the Saved Return Pointer. Update the exploit with a payload using Metasploit's pattern_create.rb
then find the offset using pattern_offset.rb
.
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l LENGTH
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q PATTERN
Alternatively, you can send the pattern and then use the following mona.py
command to find the pattern offsets in memory.
!mona findmsp
Update the exploit and test and record the offset.
To test our offset, generate a new payload consisting of the offset's length in 'A's, 'BBBB' (overwriting the SRP), 'CCCC' (overwriting the ESP), followed by 'D's for the remainder of the buffer. Confirm with Immunity that the access violation now occurs on 42424242
(the four 'B's) and that the stack following the SRP contains 'CCCC' followed by a whole heap of 'D's.
Now that we can control the EIP, we can begin to look to adding shellcode to our exploit. Before doing this, we should check which characters we should exclude from our payload to prevent the program from misinterpreting our payload and the exploit from failing.
modify the exploit to contain each non-bad-character and write it to the ESP (in place of our 'CCCC' from before). If the Exploit ails the same and the bytes contained in the stack from the ESP onwards match the payload, then we've found all bad characters. If not, we compare and begin the process of elimination.
We can compare the contents of the stack using the following mona.py
command:
!mona compare -a esp -f c:\badchar_test.bin
Common bad characters include:
\x00 - The NULL byte.
\x0A - The new-line character '\n'.
Note: Since Immunity arranges the memory dump in sets of 8 bytes, and there are 16 hexadecimal characters, it's pretty easy to see where something goes out of whack by running your eye down the final byte of each row of the memory dump. Eg. you may see:
12
1A
22
2A
We can now control the EIP. We could put our shellcode in memory and directly reference the address from the EIP; however, the location of the shellcode is bound to change with each invocation of the program. Instead, let's find a statically addressed JMP ESP, reference that in our overwritten SRP, and use that to bounce to the shellcode we'll place at ESP.
Using mona.py
, we'll find a JMP ESP that does not contain any of our bad characters using the following command:
!mona jmp -r esp -cpb "\x00\x0A"
If this approach returns no results, we can try again. First, we search the available modules and choose one where rebase, safeSEH, ASLR and NXCompat
are false. This is so we can get an address that is reliably in the same place each time the program is executed.
!mona modules
Next, we use another Metasploit script to generate the op codes for the operation we're looking for (JMP ESP
).
/usr/share/metasploit-framework/tools/exploit/nasm_shell.rb
nasm > jmp esp
00000000 FFE4 JMP ESP
Finally, we can search the module for these bytes. Make sure you use an address that does not contain any bad characters.
!mona -s "\xFF\xE4" -m slmfc.dll
Armed with JMP ESP addresses, update the exploit code to replace the SRP with one of the addresses.
Note: Use struct.pack()
to use the little-endian version of the address.
Generate some shellcode using msfvenom
. Remember to get the architecture and platform right.
Before lumping the shellcode into the exploit, there's one last thing to do. The default encoder used by Metasploit destroys bytes around ESP in the decoding process, which will likely overwrite some bytes of the shellcode. To get around this, we can generate some bytecode that moves the ESP pointer further up the stack first to protect the shellcode.
/usr/share/metasploit-framework/tools/exploit/metasm_shell.rb
metasm > sub esp,0x10
"\x83\xec\x10"
Note: Make sure the ESP is moved up in multiples of 4 bytes to avoid causing the process to fail.
Alternatively, we can add a few NOPs (\x90
) between the SRP and the shellcode to provide some padding.
Send it!!!
Register Name Function
-------------------------------------------------------------------------------
EBP Extended Base Pointer Marks the base of the stack.
ESP Extended Stack Pointer Marks the top of the stack.
EIP Extended Instruction Pointer Marks the location of the next instruction.
Note: The ESP (top of the stack) of a calling function is the EBP (base of the stack) of the called function.
The call procedure happens when a program calls a function. The program needs to put any parameters required by the function on the stack, then move execution to the space in memory that contains the functions instructions. The summarised process is as follows:
- Push arguments onto the stack.
- Push the address of the next instruction onto the stack (Allowing the program to return and continue execution).
- Modifies the EIP to the address of the function being called (Making the function the next instruction to be executed).
Immediately after the Call Procedure, the next code to execute is the Function Prologue, which is located at the beginning of the called function. A summary of the function prologue is as follows:
- PUSH EBP - Push the current value in EBP onto the stack.
- MOV EBP,ESP - Copy the current value of ESP into EBP, setting up the new base pointer.
- SUB ESP,<something> - Make room on the stack for local variables.
After a function has completed execution, execution must return to the instruction proceeding the instruction that called the function.
- MOV ESP,EBP - Move the stack back down to the area containing the Saved Return Pointer.
- POP EBP - Restore the saved EBP value back into the EBP register.
- RET - Return to the Saved Return Pointer.
jmp esp
push esp
retn
Tool Purpose
-------------------------------------------------------------------------------
Immunity Debugger A BOFers best friend.
Mona.py ???
!mona findsmp
!mona compare -a esp -f c:\badchar_test.bin
!mona jmp -r esp -cpb "\x00\x0A"
IDA
Pattern Create Create random bytes to identify the offset to the Saved Return Pointer.
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l LENGTH
Pattern Offset Find the offset of a pattern created from pattern create.
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 39654138
msfvenom Generate a payload.
Ctrl + F2 - Restart Program
Alt + F2 - Close Program
F2 - Toggle Breakpoint
F7 - Step Into
F8 - Step Over
F9 - Run Program
Ctrl + F9 - Run to next return
F12 - Pause Program
Alt + B - Breakpoints Window
Alt + C - CPU Window
- If you can't see background processes (Looking at you SLMail) in Immunity, try running Immunity as Administrator.
DEP is a hardware / software security control that attempts to identify malicious code and prevent it from executing on the system, raising an exception.
ASLR aims to make buffer overflows more difficult to execute by randomising how applications and DLLs are loaded into memory.
Decompiler - A tool that takes a binary (.exe, .dll etc.) and decompiles it into a high-level language such as C.
Disassembler - A tool that takes a binary and disassembles it into assembly code.
dobufferoverflowgood - Justin Steven
Finding Bad Characters - Bulb Security (Georgia Weidman)