ADS es la funcionalidad de NTFS que sigue sorprendiendo a los analistas junior. Un archivo puede tener más de un atributo $DATA. El no nombrado es del que dir te muestra el tamaño. Cualquier otra cosa, cualquier cosa con dos puntos en su identificador, es invisible para las herramientas a las que la mayoría acude. Los atacantes lo saben. Microsoft lo sabe. El auditor que revise tu informe de IR debería saberlo también.
El mecanismo, en breve
En el registro MFT, el atributo de tipo 0x80 es $DATA. La cabecera lleva un nombre opcional. Un único registro puede llevar muchos atributos $DATA: uno sin nombre (el flujo primario) y cualquier número de nombrados. Desde el userland los direccionas con filename:streamname.
echo payload > readme.txt:nope
type readme.txt:nope
readme.txt tiene cero bytes según cualquier medida que muestre Explorer. El flujo nombrado nope contiene el payload. Mismo registro MFT. Misma entrada de índice del directorio padre. Dos atributos de datos independientes.
No es un bug. Es una decisión de diseño de 1993 que NTFS heredó de HPFS para permitir que Services for Macintosh adjuntara resource forks. Casi nadie usa ADS para eso ahora. Todos los demás, incluido Microsoft, lo usan para metadatos ad hoc.
Dónde el propio Windows deja ADS
Zone.Identifier es el famoso. Edge, Chrome, Firefox y Outlook lo añaden a cualquier cosa que cruzó un límite de seguridad. El contenido es un fragmento INI con la URL de origen, el referrer y una línea ZoneId=3 que activa las protecciones Mark-of-the-Web en Office y SmartScreen. Si estás leyendo una MFT y un binario en Downloads\ no tiene Zone.Identifier, pregúntate por qué. Alguien puede haber ejecutado Unblock-File o copiado el archivo a través de un archivo comprimido que descarta flujos.
Otros flujos bendecidos por Microsoft con los que te encontrarás:
$KSPen archivos de diseño de teclado de idiomas asiáticos.OECustomPropertyy compañía en adjuntos de Outlook guardados en disco.- Datos reparse
Wofen archivos comprimidos bajo WIMBoot y CompactOS. SmartScreenen ejecutables que Defender ha fingerprintado.encryptableen directorios de caché de ConfigMgr.
Estos aparecen constantemente. Aprende cómo se ve tu línea base antes de marcar flujos como sospechosos.
Qué hacen realmente los atacantes con ADS
Se repiten tres patrones:
- Almacenamiento de payload, lanzador separado. El archivo visible es benigno (un documento Word, un PDF, un archivo de licencia). El flujo nombrado contiene el PE real. WMI,
wmic process call createorundll32lanzalegit.docx:payload.exedirectamente. Defender sí escanea flujos nombrados hoy, pero muchos EDR aún no lo hacen cuando un flujo es creado por un proceso de confianza. - Escondite living-off-the-land. Payloads de PowerShell escritos en
ads:script.ps1y luego ejecutados conGet-Content -Stream. Sorprendentemente común en retenes de red team porque sobrevive a una búsqueda de IOC basada solo en rutas. - Persistencia en flujos alternativos de archivos del sistema.
C:\Windows\System32\drivers\etc\hosts:backdoores el ejemplo de manual. El archivo hosts parece intacto, la marca de tiempo puede incluso ser original, y la mayoría de herramientas de monitoreo de integridad de archivos nunca miran más allá del flujo sin nombre.
La propiedad compartida: no puedes verlos con dir, no puedes verlos en Explorer y no puedes verlos hasheando el archivo visible. Puedes verlos leyendo el registro MFT.
Detectarlos en un host en vivo
dir /R enumera flujos en cmd. Get-Item -Stream * de PowerShell hace lo mismo con una salida más limpia. streams.exe de Sysinternals recorre un árbol. Los tres funcionan bien en el volumen en el que estás. Ninguno ayuda si el volumen está offline o si no sabes qué archivos comprobar.
dir /R C:\Users\bob\Documents\
Get-ChildItem -Recurse | ForEach-Object { Get-Item $_.FullName -Stream * } |
Where-Object Stream -ne ':$DATA'
Esa segunda línea enumera todos los flujos no predeterminados en un árbol. Ejecútala en una instalación fresca de Windows y ya tendrás cientos de coincidencias, en su mayoría Zone.Identifier. Filtra a flujos mayores que unos cientos de bytes y el ruido baja rápido.
Por qué la MFT es la mejor lente
Los comandos en el host enumeran por archivo. Pierden lo que no pensaste en comprobar. La MFT no. Cada atributo $DATA, nombrado o no, se escribe en el registro en el atributo de tipo 0x80. Recorre la tabla, lista los atributos $DATA de cada registro con sus nombres y tamaños, y tendrás un inventario exhaustivo de todos los flujos del volumen en una sola pasada.
Algunas cosas que esto te da que la enumeración por archivo no:
- Flujos en archivos en directorios donde nunca habrías mirado, incluyendo
C:\Windows\Temp\yC:\$Recycle.Bin\. - Flujos en archivos eliminados. El registro MFT sobrevive a la eliminación; el ADS sigue listado en el flujo de atributos.
flseistatdel Sleuth Kit los mostrarán; también lo harán MFTECmd y la CLI deomerbenamram/mft. - Flujos residentes cuyo contenido se encuentra inline en el registro MFT. Pequeños payloads (loaders de PowerShell, blobs base64, configs codificadas) caben con frecuencia en el slack de un registro de 1.024 bytes. Puedes leerlos directamente del extracto de la MFT sin tocar el área de datos. Mira datos residentes para el umbral de tamaño.
- Nombres de flujos. La MFT preserva el nombre que el atacante eligió.
:payload.exeparece inocuo en una lista de tamaños de archivos; es llamativo cuando haces grep en un volcado de atributos buscandoexe.
El filtro de triage que realmente uso
Después de parsear la MFT con MFTECmd o mft_dump, exporto todo registro con más de un atributo $DATA. Luego descarto:
- Cualquier cosa cuyo nombre de flujo extra sea
Zone.Identifiery por debajo de 1 KB. - Cualquier cosa en
\Windows\WinSxS\(el almacén de manifiestos, lleno de flujos legítimos). - Cualquier cosa bajo un directorio de aplicación firmada por proveedor cuyo flujo sea una miniatura o clave de metadatos conocida.
Lo que queda es el conjunto de trabajo. En una estación limpia suelen ser menos de cien registros. En un host donde ha pasado algo interesante, los deltas se manifiestan inmediatamente.
Cruza los supervivientes con el diario USN para ver cuándo se creó o modificó por última vez cada flujo. Un atributo $DATA nombrado que apareció a las 02:14 y no se ha tocado desde entonces merece una mirada más cercana. Combina con Sysmon y los registros de eventos de seguridad si los tienes: Sysmon Event ID 15 (FileCreateStreamHash) es el único ID de evento que captura la creación de ADS con el hash del contenido del flujo.
Una nota sobre Defender
El Defender moderno sí escanea ADS por defecto. Es genuinamente bueno en el patrón fuerza bruta de "soltar un PE conocido como malo en un flujo". Es menos bueno con PowerShell pequeño y obfuscado oculto en flujos, y no siempre toca flujos en rutas excluidas. No asumas que el silencio de Defender es evidencia de ausencia.
Lecturas adicionales
- Microsoft, File Streams. La mecánica oficial, incluida la API
BackupRead/BackupWriteque copia todos los flujos. istatyflsdel Sleuth Kit para la enumeración offline que saca a relucir los ADS.- Documentación de Mark of the Web de Microsoft sobre lo que realmente hace
Zone.Identifiery cómo lo usa Office.