Análisis del Espacio Slack y Artefactos del Sistema de Archivos
Cuándo Usarlo
- Al buscar datos ocultos o residuales en el espacio slack del sistema de archivos
- Para analizar las entradas de la Tabla de Archivos Maestra (MFT) de NTFS en busca de metadatos de archivos eliminados
- Al reconstruir operaciones de archivos a partir del Diario de Cambios USN
- Para detectar Flujos de Datos Alternativos (ADS) utilizados para ocultar datos o malware
- Durante el análisis forense profundo que requiere un examen más allá de la recuperación de archivos estándar
Prerrequisitos
- Imagen de disco forense con sistema de archivos NTFS
- Herramientas de The Sleuth Kit (TSK): istat, icat, fls, blkls, blkstat
- MFTECmd (Eric Zimmerman) para el análisis de MFT
- MFTExplorer para el análisis interactivo de MFT
- Comprensión de las estructuras NTFS (MFT, $UsnJrnl, $LogFile, ADS)
- Python con analyzeMFT o la biblioteca mft para el análisis automatizado
Flujo de Trabajo
Paso 1: Identificar y Extraer Artefactos del Sistema de Archivos NTFS
# Determinar el diseño de la partición
mmls /casos/caso-2024-001/imagenes/evidencia.dd
# Extraer archivos clave del sistema NTFS
# $MFT - Tabla de Archivos Maestra
icat -o 2048 /casos/caso-2024-001/imagenes/evidencia.dd 0 > /casos/caso-2024-001/ntfs/MFT
# $UsnJrnl:$J - Diario de Cambios USN
icat -o 2048 /casos/caso-2024-001/imagenes/evidencia.dd 62-128 > /casos/caso-2024-001/ntfs/UsnJrnl_J
# $LogFile - Registro de transacciones
icat -o 2048 /casos/caso-2024-001/imagenes/evidencia.dd 2 > /casos/caso-2024-001/ntfs/LogFile
# Extraer todo el espacio slack del volumen
blkls -s -o 2048 /casos/caso-2024-001/imagenes/evidencia.dd > /casos/caso-2024-001/ntfs/espacio_slack.raw
# Obtener información del sistema de archivos
fsstat -o 2048 /casos/caso-2024-001/imagenes/evidencia.dd | tee /casos/caso-2024-001/ntfs/info_fs.txt
Paso 2: Analizar la Tabla de Archivos Maestra (MFT)
# Analizar MFT con MFTECmd (Eric Zimmerman)
MFTECmd.exe -f "C:\casos\ntfs\MFT" --csv "C:\casos\analisis\" --csvf analisis_mft.csv
# Analizar con analyzeMFT (Python)
pip install analyzeMFT
analyzeMFT.py -f /casos/caso-2024-001/ntfs/MFT \
-o /casos/caso-2024-001/analisis/analisis_mft.csv \
-c
# Análisis personalizado de MFT con Python
python3 << 'PYEOF'
from mft import PyMft
import csv
mft = PyMft(open('/casos/caso-2024-001/ntfs/MFT', 'rb').read())
archivos_eliminados = []
archivos_sospechosos = []
for entrada in mft.entries():
if entrada is None:
continue
nombre_archivo = entrada.get_filename()
if nombre_archivo is None:
continue
esta_eliminado = not entrada.is_active()
es_directorio = entrada.is_directory()
creado = entrada.get_created_timestamp()
modificado = entrada.get_modified_timestamp()
mft_modificado = entrada.get_mft_modified_timestamp()
tamano = entrada.get_file_size()
# Marcar archivos eliminados para recuperación
if esta_eliminado and not es_directorio and tamano > 0:
archivos_eliminados.append({
'nombre_archivo': nombre_archivo,
'tamano': tamano,
'creado': str(creado),
'modificado': str(modificado),
'numero_entrada': entrada.entry_number
})
# Detectar manipulación de marcas de tiempo (MFT modificado != $SI modificado)
si_modificado = entrada.get_si_modified_timestamp()
fn_modificado = entrada.get_fn_modified_timestamp()
if si_modificado and fn_modificado:
if abs((si_modificado - fn_modificado).total_seconds()) > 86400: # diferencia >1 día
archivos_sospechosos.append({
'nombre_archivo': nombre_archivo,
'si_modificado': str(si_modificado),
'fn_modificado': str(fn_modificado),
'delta': str(si_modificado - fn_modificado)
})
print(f"=== ARCHIVOS ELIMINADOS (metadatos recuperables) ===")
print(f"Total: {len(archivos_eliminados)}")
for f in archivos_eliminados[:20]:
print(f" [{f['modificado']}] {f['nombre_archivo']} ({f['tamano']} bytes)")
print(f"\n=== POSIBLE MANIPULACIÓN DE MARCAS DE TIEMPO ===")
print(f"Total sospechosos: {len(archivos_sospechosos)}")
for f in archivos_sospechosos[:10]:
print(f" {f['nombre_archivo']}: $SI={f['si_modificado']}, $FN={f['fn_modificado']} (delta: {f['delta']})")
PYEOF
Paso 3: Analizar el Espacio Slack en Busca de Datos Ocultos
# Buscar cadenas en el espacio slack
strings -a /casos/caso-2024-001/ntfs/espacio_slack.raw > /casos/caso-2024-001/analisis/cadenas_slack.txt
# Buscar patrones específicos en el espacio slack
grep -iab "contraseña|secreto|confidencial|tarjeta.de.credito|ssn" \
/casos/caso-2024-001/ntfs/espacio_slack.raw > /casos/caso-2024-001/analisis/palabras_clave_slack.txt
# Analizar el slack individual de archivos
python3 << 'PYEOF'
import struct
# El slack de archivo consiste en:
# 1. Slack RAM: bytes entre el final del archivo y el siguiente límite de sector (lleno con contenido RAM o ceros)
# 2. Slack de unidad: sectores restantes en el clúster después del último sector del archivo
# Analizar slack para entradas MFT específicas
# Usando Sleuth Kit para obtener slack de archivo para un archivo específico
import subprocess
# Obtener detalles del archivo
resultado = subprocess.run(
['istat', '-o', '2048', '/casos/caso-2024-001/imagenes/evidencia.dd', '14523'],
capture_output=True, text=True
)
print(resultado.stdout)
# La salida muestra las ejecuciones de datos - el último clúster puede contener datos slack
# Calcular tamaño del slack: (tamaño_asignado - tamaño_archivo) bytes
PYEOF
# Buscar firmas de archivos en el espacio slack (archivos incrustados)
foremost -t jpg,pdf,zip -i /casos/caso-2024-001/ntfs/espacio_slack.raw \
-o /casos/caso-2024-001/tallados/slack_tallado/
# Usar bulk_extractor para encontrar datos estructurados en slack
bulk_extractor -o /casos/caso-2024-001/analisis/extraccion_masiva/ \
/casos/caso-2024-001/ntfs/espacio_slack.raw
Paso 4: Analizar el Diario de Cambios USN
# Analizar el diario USN con MFTECmd
MFTECmd.exe -f "C:\casos\ntfs\UsnJrnl_J" --csv "C:\casos\analisis\" --csvf diario_usn.csv
# Análisis del diario USN en Python
pip install pyusn
python3 << 'PYEOF'
import struct
import csv
from datetime import datetime, timedelta
def analizar_registro_usn(datos, desplazamiento):
"""Analizar un único USN_RECORD_V2."""
if desplazamiento + 8 > len(datos):
return None, desplazamiento
longitud_registro = struct.unpack_from('<I', datos, desplazamiento)[0]
if longitud_registro < 56 or longitud_registro > 65536 or desplazamiento + longitud_registro > len(datos):
return None, desplazamiento + 8
version_principal = struct.unpack_from('<H', datos, desplazamiento + 4)[0]
if version_principal != 2:
return None, desplazamiento + longitud_registro
ref_mft = struct.unpack_from('<Q', datos, desplazamiento + 8)[0] & 0xFFFFFFFFFFFF
ref_padre = struct.unpack_from('<Q', datos, desplazamiento + 16)[0] & 0xFFFFFFFFFFFF
usn = struct.unpack_from('<Q', datos, desplazamiento + 24)[0]
marca_tiempo = struct.unpack_from('<Q', datos, desplazamiento + 32)[0]
razon = struct.unpack_from('<I', datos, desplazamiento + 40)[0]
informacion_origen = struct.unpack_from('<I', datos, desplazamiento + 44)[0]
id_seguridad = struct.unpack_from('<I', datos, desplazamiento + 48)[0]
atributos_archivo = struct.unpack_from('<I', datos, desplazamiento + 52)[0]
longitud_nombre = struct.unpack_from('<H', datos, desplazamiento + 56)[0]
desplazamiento_nombre = struct.unpack_from('<H', datos, desplazamiento + 58)[0]
nombre = datos[desplazamiento + desplazamiento_nombre:desplazamiento + desplazamiento_nombre + longitud_nombre].decode('utf-16-le', errors='ignore')
# Convertir FILETIME de Windows a datetime
ts = datetime(1601, 1, 1) + timedelta(microseconds=marca_tiempo // 10)
# Decodificar banderas de razón
razones = []
banderas_razon = {
0x01: 'DATA_OVERWRITE', 0x02: 'DATA_EXTEND', 0x04: 'DATA_TRUNCATION',
0x10: 'NAMED_DATA_OVERWRITE', 0x20: 'NAMED_DATA_EXTEND',
0x100: 'FILE_CREATE', 0x200: 'FILE_DELETE', 0x400: 'EA_CHANGE',
0x800: 'SECURITY_CHANGE', 0x1000: 'RENAME_OLD_NAME', 0x2000: 'RENAME_NEW_NAME',
0x4000: 'INDEXABLE_CHANGE', 0x8000: 'BASIC_INFO_CHANGE',
0x10000: 'HARD_LINK_CHANGE', 0x20000: 'COMPRESSION_CHANGE',
0x40000: 'ENCRYPTION_CHANGE', 0x80000: 'OBJECT_ID_CHANGE',
0x100000: 'REPARSE_POINT_CHANGE', 0x200000: 'STREAM_CHANGE',
0x80000000: 'CLOSE'
}
for bandera, desc in banderas_razon.items():
if razon & bandera:
razones.append(desc)
registro = {
'marca_tiempo': ts.strftime('%Y-%m-%d %H:%M:%S'),
'nombre_archivo': nombre,
'entrada_mft': ref_mft,
'entrada_padre': ref_padre,
'razones': '|'.join(razones),
'usn': usn
}
return registro, desplazamiento + longitud_registro
# Analizar el diario
with open('/casos/caso-2024-001/ntfs/UsnJrnl_J', 'rb') as f:
datos = f.read()
registros = []
desplazamiento = 0
while desplazamiento < len(datos) - 8:
registro, desplazamiento = analizar_registro_usn(datos, desplazamiento)
if registro:
registros.append(registro)
else:
desplazamiento += 8 # Saltar ceros
# Filtrar eventos de eliminación
eliminaciones = [r for r in registros if 'FILE_DELETE' in r['razones']]
creaciones = [r for r in registros if 'FILE_CREATE' in r['razones']]
cambios_nombre = [r for r in registros if 'RENAME_NEW_NAME' in r['razones']]
print(f"Total de registros USN: {len(registros)}")
print(f"Creaciones de archivos: {len(creaciones)}")
print(f"Eliminaciones de archivos: {len(eliminaciones)}")
print(f"Cambios de nombre de archivos: {len(cambios_nombre)}")
print("\n=== ELIMINACIONES RECIENTES ===")
for r in eliminaciones[-20:]:
print(f" [{r['marca_tiempo']}] ELIMINADO: {r['nombre_archivo']} (MFT#{r['entrada_mft']})")
# Escribir el diario completo a CSV
with open('/casos/caso-2024-001/analisis/diario_usn.csv', 'w', newline='') as f:
escritor = csv.DictWriter(f, fieldnames=['marca_tiempo', 'nombre_archivo', 'entrada_mft', 'entrada_padre', 'razones', 'usn'])
escritor.writeheader()
escritor.writerows(registros)
PYEOF
Paso 5: Detectar y Analizar Flujos de Datos Alternativos
# Listar todos los Flujos de Datos Alternativos en la imagen
find /mnt/evidencia -exec getfattr -d {} \; 2>/dev/null | grep -i "ads|zona|flujo"
# Usando Sleuth Kit para encontrar ADS
fls -r -o 2048 /casos/caso-2024-001/imagenes/evidencia.dd | grep ":" | \
tee /casos/caso-2024-001/analisis/lista_ads.txt
# Extraer contenido específico de ADS
# Formato: icat imagen inodo:nombre_ads
icat -o 2048 /casos/caso-2024-001/imagenes/evidencia.dd 14523:flujo_oculto \
> /casos/caso-2024-001/analisis/ads_extraido.bin
# Verificar flujos Zone.Identifier (seguimiento de origen de descarga)
fls -r -o 2048 /casos/caso-2024-001/imagenes/evidencia.dd | grep "Zone.Identifier" | \
while read linea; do
inodo=$(echo "$linea" | awk '{print $2}' | tr -d ':')
echo "=== $linea ==="
icat -o 2048 /casos/caso-2024-001/imagenes/evidencia.dd "${inodo}:Zone.Identifier" 2>/dev/null
echo ""
done > /casos/caso-2024-001/analisis/identificadores_zona.txt
# El contenido de Zone.Identifier revela:
# [ZoneTransfer]
# ZoneId=3 (3 = Internet, indica que el archivo fue descargado)
# ReferrerUrl=https://sitio-malicioso.com/payload.exe
# HostUrl=https://cdn.sitio-malicioso.com/payload.exe
Conceptos Clave
| Concepto | Descripción |
|---|---|
| Slack de archivo | Espacio no utilizado entre el final del archivo y el límite del clúster que contiene datos residuales |
| Slack RAM | Porción del slack desde el final del archivo hasta el límite del sector (históricamente lleno con RAM) |
| MFT ($MFT) | Tabla de Archivos Maestra - base de datos de metadatos NTFS con entradas para cada archivo |
| Diario USN ($UsnJrnl) | Diario de cambios que registra todas las modificaciones de archivos/directorios en NTFS |
| Flujos de Datos Alternativos | Característica de NTFS que permite múltiples flujos de datos por archivo (almacenamiento oculto) |
| $STANDARD_INFORMATION | Atributo MFT con marcas de tiempo modificables por aplicaciones de modo usuario |
| $FILE_NAME | Atributo MFT con marcas de tiempo solo modificables por el kernel |
| Manipulación de marcas de tiempo | Técnica anti-forense que modifica las marcas de tiempo de archivos para evitar la detección |
Herramientas y Sistemas
| Herramienta | Propósito |
|---|---|
| MFTECmd | Analizador MFT y del diario USN de Eric Zimmerman con salida CSV |
| MFTExplorer | Herramienta GUI interactiva para análisis de MFT |
| analyzeMFT | Analizador MFT en Python con salida CSV/JSON |
| The Sleuth Kit | Kit de herramientas forenses de sistema de archivos (fls, icat, blkls, istat) |
| bulk_extractor | Extracción de características de datos sin procesar, incluido el espacio slack |
| NTFS Log Tracker | Herramienta para analizar registros de transacciones $LogFile |
| streams.exe | Herramienta Sysinternals para listar Flujos de Datos Alternativos NTFS |
| Plaso | Herramienta de super-línea de tiempo que analiza MFT y el diario USN |
Escenarios Comunes
Escenario 1: Detección Anti-Forense mediante Manipulación de Marcas de Tiempo Comparar las marcas de tiempo de $STANDARD_INFORMATION con las de $FILE_NAME en las entradas MFT, marcar archivos donde las marcas de tiempo $SI preceden a las marcas de tiempo $FN (imposible en operación normal), identificar archivos con marcas de tiempo manipuladas como evidencia de manipulación deliberada, correlacionar con otra evidencia de línea de tiempo.
Escenario 2: Datos Ocultos en Flujos de Datos Alternativos Escanear ADS adjuntos a archivos más allá del Zone.Identifier estándar, extraer contenido de ADS para análisis, verificar ejecutables o documentos ocultos almacenados en ADS, correlacionar la creación de ADS con la línea de tiempo de actividad del usuario, documentar hallazgos para evidencia.
Escenario 3: Reconstrucción de Archivos Eliminados desde MFT Analizar MFT en busca de entradas inactivas (eliminadas), extraer nombres de archivos, tamaños y marcas de tiempo de archivos eliminados, recuperar contenido de archivos usando icat si los clústeres de datos no han sido sobrescritos, construir lista de archivos de evidencia eliminados, correlacionar con eventos de eliminación del Diario USN.
Escenario 4: Reconstrucción de Actividad de Archivos desde el Diario USN Analizar el Diario de Cambios USN para el período de investigación, identificar eventos de creación, modificación, cambio de nombre y eliminación de archivos, reconstruir la secuencia de operaciones de archivos, detectar evidencia de preparación de datos (patrón crear, copiar, comprimir, eliminar), identificar borrado forense de archivos.
Formato de Salida
Análisis de Artefactos del Sistema de Archivos:
Volumen: NTFS (Partición 2, 465 GB)
Tamaño de Clúster: 4096 bytes
Análisis MFT:
Entradas Totales: 456,789
Archivos Activos: 234,567
Entradas Eliminadas: 12,345 (8,901 con metadatos recuperables)
Archivos con Marcas de Tiempo Manipuladas: 23 (discrepancia SI/FN detectada)
Diario USN:
Registros Analizados: 2,345,678
Rango de Fechas: 2024-01-01 a 2024-01-20
Creaciones de Archivos: 45,678
Eliminaciones de Archivos: 23,456
Cambios de Nombre de Archivos: 12,345
Flujos de Datos Alternativos:
Total ADS Encontrados: 1,234
Zone.Identifier: 890 (archivos descargados)
ADS Personalizados/Sospechosos: 5 (datos ocultos detectados)
Espacio Slack:
Slack Total: 12.3 GB
Aciertos de Palabras Clave: 45 (contraseñas, tarjetas de crédito)
Archivos Tallados: 23 desde espacio slack
Hallazgos Sospechosos:
- 23 archivos con marcas de tiempo manipuladas
- 5 archivos con ADS ocultos que contienen datos
- USN muestra eliminación masiva el 2024-01-18 (anti-forense)
...
[truncado para traducción]