Cheatsheet

Firmware-RE-Cheatsheet: Binwalk y Extracción de Filesystems

Lectura Crítica de la Tabla de Binwalk

binwalk no es un extractor mágico; es un scanner de firmas. La tabla DECIMAL/HEXADECIMAL/DESCRIPTION es tu mapa de ataque. No asumas que la primera entrada es el kernel o la última es el filesystem.

  • DECIMAL: Offset absoluto en el archivo. Crítico para dd manual o para saltar cabeceras corruptas.
  • HEXADECIMAL: La misma posición en hex, útil para buscar en un hex editor.
  • DESCRIPTION: La firma. Aquí está el truco: binwalk puede reportar falsos positivos (firmas dentro de datos comprimidos o texto). Las entradas que importan son:
    • Filesystems: SquashFS little endian, version 4.0, CramFS filesystem, JFFS2 filesystem, UBIFS. Estas requieren herramientas externas, NO binwalk -e puro.
    • Compresores de kernel: gzip compressed data, LZMA compressed data. No extraigas el kernel inmediatamente; primero mira qué hay después.
    • Encabezados de bootloader: U-Boot, TRX header. Ayudan a mapear la estructura.

Patrón típico: [U-Boot/TRX] -> [Kernel gzip] -> [Padding/DTB] -> [SquashFS] -> [JFFS2/UBIFS para overlay]. Si ves un filesystem al principio y otro al final, el segundo suele ser la partición de datos de usuario (donde viven las claves/config).

Extracción: La Herramienta Correcta por Formato

binwalk -e falla silenciosamente con filesystems de vendor. Usa -e solo para firmware simple (router doméstico). Para penetrar, extrae con dd o binwalk -D y procesa manualmente.

Comando Base (extracción agresiva)

# Extrae TODO, incluso si binwalk no tiene handler específico
binwalk -e --dd='.*' firmware.bin
# Si el filesystem está anidado (ej. dentro de un UBI)
binwalk -Me --dd='.*' firmware.bin  # -M para recursivo

SquashFS (El estándar en IoT)

  • Estándar: unsquashfs rootfs.squashfs
  • Variantes de vendor (TP-Link, Zyxel, etc.): unsquashfs fallará con Unknown compression o Filesystem is not in little endian. Necesitas sasquatch (fork de ReFirmLabs).
# Compilar sasquatch (asumiendo que ya tienes las deps)
git clone https://github.com/devttys0/sasquatch.git
cd sasquatch && ./build.sh
# Extraer
truncate -s 100M squished.squashfs  # Arreglar tamaño si binwalk falla al identificar el final
sasquatch squished.squashfs -d output_dir

CramFS

Obsoleto pero presente en routers viejos. binwalk -e rara vez funciona si la tabla es custom.

# Extraer con cramfsck (del paquete cramfs-tools)
cramfsck -x output_dir cramfs_partition.bin
# Si el header está roto, reconstruirlo manualmente con binwalk
# Busca offsets y usa dd: dd if=firmware.bin bs=1 skip=<offset> of=part.cramfs

JFFS2

Siempre requiere jefferson. binwalk -e NO lo maneja.

pip3 install jefferson
jefferson jffs2_partition.bin output_dir
# Si es little-endian y falla, usa la opción -l (forzar little-endian)
jefferson -l jffs2_partition.bin output_dir

UBIFS (Ubiquitous File System)

Más complejo. Necesitas extraer la capa UBI primero. No busques UBIFS directamente con binwalk si no muestra el volumen UBI.

# 1. Extraer la imagen UBI (encontrada con binwalk como "UBI erase count header")
ubireader_extract_files ubi_partition.bin -o ubi_files/
# 2. Si falla, usar ubireader_extract_files -a (all volumes) y luego
#    buscar el volumen de rootfs (suele llamarse rootfs o ubi:rootfs)

Si binwalk muestra UBIFS filesystem directamente, puedes intentar binwalk -e, pero es raro. Prefiere ubireader_extract_files.

Flujo Rápido para Filesystems Anidados (Firmware Industrial/CPE)

Muchos firmwares son un contenedor (ej. TRX) -> kernel + squashfs. El SquashFS suele estar justo después del kernel. Si binwalk marca SquashFS pero unsquashfs falla, ejecuta binwalk -A (análisis de arquitectura) sobre el archivo extraído por dd para verificar si hay padding corrupto entre el kernel y el squashfs.

# Ejemplo: Extraer manualmente un squashfs en offset 0x2E1000
dd if=firmware.bin bs=1 skip=$((0x2E1000)) of=rootfs.squashfs
file rootfs.squashfs  # Debe decir "Squashfs filesystem"

Prioridad de Búsqueda Post-Extracción

Una vez tengas el rootfs extraído (fs/), NO busques credenciales primero. Sigue este orden para maximizar impacto:

1. Acceso Remoto y Criptografía (Top Prio)

# Claves SSH privadas (busca en todo el árbol, no solo en root/.ssh)
grep -r "BEGIN RSA PRIVATE KEY" --include="*.pem" --include="*.key" .
find . -name "id_rsa*" -o -name "*.ppk" -o -name "authorized_keys" 2>/dev/null

# Certificados y claves de cliente (para pivotar a infraestructura)
find . -name "*.p12" -o -name "*.cer" -o -name "*.crt" -o -name "*.key" | grep -v usr/share

# Buscar frases semilla de passwords o PINs en binarios de config
grep -R "admin\|password\|passwd\|pwd" etc/ 2>/dev/null | grep -v ".so"

2. Archivos de Configuración Críticos

# /etc/shadow: hasheado, pero si el algoritmo es DES/old, crackearlo fácil
cat etc/shadow | grep -v "^.*:\*\|^.*:!"

# Config de red y servicios internos (pivoting)
find . -name "*.conf" | xargs grep -l "server\|host\|url\|api\|token" 2>/dev/null
cat etc/config/dropbear 2>/dev/null  # Claves de dropbear si existe
cat etc/ssl/openssl.cnf 2>/dev/null

# Archivos de UCI (OpenWrt)
cat etc/config/*.uci 2>/dev/null
cat etc/config/network 2>/dev/null  # IPs internas o WAN

3. String Dump en Binarios (Parsing de Firmas Custom)

# Buscar URLs/IPs hardcodeadas en binarios y libs (no solo en texto plano)
grep -rao "https\?://[a-zA-Z0-9.\-]*" --include="*.so" --include="*.a" .
grep -rEao "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" --include="*.so" .

# Para binarios comprimidos con upx o custom, extraer strings primero
for f in $(find . -type f -name "*.bin"); do strings "$f" | grep -E "^(192|172|10)\." ; done

4. Ataque a Firmware Updates y Backdoors

# Buscar scripts de modificación de fw (ej. firmware.sh con lógica de cifrado)
find . -name "*.sh" | xargs grep -l "openssl\|aes\|des\|xor" 2>/dev/null

# Buscar puertos backdoor en binarios de servicio (ej. telnet en un bin)
strings usr/sbin/telnetd | grep -B2 -A2 "port\|debug\|backdoor"

Nota: Los fabricantes a menudo cambian permisos (chmod 777) en ejecutables de depuración. Busca binarios setuid:

find . -perm -4000 -exec ls -l {} \;