Ingeniería inversa de un router doméstico con binwalk. ¿Confías en el software de tu router?

Ingeniería inversa de un router doméstico con binwalk. ¿Confías en el software de tu router?

Hace unos días, decidí hacer ingeniería inversa del firmware de mi enrutador usando binwalk.

Me compré un TP-Link Archer C7 enrutador doméstico. No es el mejor enrutador, pero para mis necesidades es suficiente.

Cada vez que compro un nuevo enrutador, instalo OpenWRT. ¿Por qué? Generalmente, los fabricantes no se preocupan mucho por el soporte de sus enrutadores y con el tiempo el software se vuelve obsoleto, surgen vulnerabilidades y así sucesivamente, ya entiendes. Por eso prefiero el firmware open-source OpenWRT, que es bien soportado por la comunidad.

Después de descargar OpenWRT, también descargué la última imagen del firmware para mi nuevo Archer C7 desde el sitio oficial y decidí analizarlo. Solo por diversión y para hablar de binwalk.

¿Qué es binwalk?

Binwalk es una herramienta de código abierto para el análisis, ingeniería inversa y extracción de imágenes de firmware.

Creada en 2010 por Craig Heffner, binwalk puede escanear imágenes de firmware y encontrar archivos, identificar y extraer imágenes de sistemas de archivos, código ejecutable, archivos comprimidos, bootloaders y kernels, formatos de archivo como JPEG y PDF, y mucho más.

Puedes usar binwalk para realizar ingeniería inversa de firmware para entender cómo funciona. Buscar vulnerabilidades en archivos binarios, extraer archivos y buscar backdoors o certificados digitales. También se pueden encontrar opcodes para un montón de CPU diferentes.

Puedes descomprimir imágenes de sistemas de archivos para buscar ciertos archivos de contraseñas (passwd, shadow, etc.) e intentar romper hashes de contraseñas. Puedes realizar un análisis binario entre dos o más archivos. Puedes realizar un análisis de entropía de datos para buscar datos comprimidos o claves de cifrado codificadas. Todo esto sin necesidad de acceso al código fuente.

En general, todo lo necesario está ahí 🙂

¿Cómo funciona binwalk?

La característica principal de binwalk es su escaneo por firmas. Binwalk puede escanear una imagen de firmware para buscar varios tipos de archivos y sistemas de archivos embebidos.

¿Conoces la utilidad de línea de comandos file?

file /bin/bash
/bin/bash: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), linked dynamically, interpreter /lib64/l, para GNU/Linux 3.2.0, BuildID[sha1]=12f73d7a8e226c663034529c8dd20efec22dde54, stripped

Comando fileque mira el encabezado del archivo y busca una firma (número mágico) para determinar el tipo de archivo. Por ejemplo, si un archivo comienza con la secuencia de bytes 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A, ella sabe que este es un archivo PNG. En Wikipedia hay una lista de firmas de archivos comunes.

Binwalk funciona de manera similar. Pero en lugar de buscar firmas solo al comienzo del archivo, binwalk escaneará todo el archivo. Además, binwalk puede extraer archivos encontrados en la imagen.

Herramientas file y binwalk utiliza la biblioteca libmagic para identificar firmas de archivos. Pero binwalk también admite una lista de firmas mágicas personalizadas para buscar archivos comprimidos / archivados, encabezados de firmware, núcleos de Linux, cargadores, sistemas de archivos, etc.

¿Vamos a divertirnos?

Instalación de binwalk

Binwalk es compatible con varias plataformas, incluyendo Linux, OSX, FreeBSD y Windows.

Para instalar la última versión de binwalk, puedes descargar el código fuente y seguir las instrucciones de instalación o guía breve, disponible en el sitio web del proyecto.

Binwalk tiene muchas opciones diferentes:

$ binwalk

Binwalk v2.2.0
Craig Heffner, ReFirmLabs
https://github.com/ReFirmLabs/binwalk

Uso: binwalk [OPTIONS] [FILE1] [FILE2] [FILE3] ...

Opciones de escaneo de firma:
    -B, --signature              Escanea el archivo(s) de destino en busca de firmas de archivo comunes
    -R, --raw=              Escanea el archivo(s) de destino en busca de la secuencia de bytes especificada
    -A, --opcodes                Escanea el archivo(s) de destino en busca de firmas de código ejecutable comunes
    -m, --magic=           Especifica un archivo mágico personalizado para usar
    -b, --dumb                   Desactiva las palabras clave de firma inteligente
    -I, --invalid                Muestra resultados marcados como inválidos
    -x, --exclude=          Excluye resultados que coincidan con 
    -y, --include=          Muestra solo resultados que coincidan con 

Opciones de extracción:
    -e, --extract                Extrae automáticamente los tipos de archivo conocidos
    -D, --dd=      Extrae firmas de , asigna a los archivos una extensión de  y ejecuta 
    -M, --matryoshka             Escanea recursivamente los archivos extraídos
    -d, --depth=            Limita la profundidad de recursión de matryoshka (por defecto: 8 niveles de profundidad)
    -C, --directory=        Extrae archivos/carpetas a un directorio personalizado (por defecto: directorio de trabajo actual)
    -j, --size=             Limita el tamaño de cada archivo extraído
    -n, --count=            Limita el número de archivos extraídos
    -r, --rm                     Elimina los archivos tallados después de la extracción
    -z, --carve                  Tallar datos de archivos, pero no ejecutar utilidades de extracción
    -V, --subdirs                Extrae en subdirectorios nombrados por el desplazamiento

Opciones de entropía:
    -E, --entropy                Calcula la entropía del archivo
    -F, --fast                   Utiliza un análisis de entropía más rápido, pero menos detallado
    -J, --save                   Guarda la trama como un PNG
    -Q, --nlegend                Omite la leyenda del gráfico de entropía
    -N, --nplot                  No genera un gráfico de trama de entropía
    -H, --high=           Establece el umbral de activación de entropía del borde ascendente (por defecto: 0.95)
    -L, --low=            Establece el umbral de activación de entropía del borde descendente (por defecto: 0.85)

Opciones de diferencia binaria:
    -W, --hexdump                Realiza un hexdump / diferencia de un archivo o archivos
    -G, --green                  Muestra solo las líneas que contienen bytes que son iguales en todos los archivos
    -i, --red                    Muestra solo las líneas que contienen bytes que son diferentes en todos los archivos
    -U, --blue                   Muestra solo las líneas que contienen bytes que son diferentes en algunos archivos
    -u, --similar                Muestra solo las líneas que son iguales entre todos los archivos
    -w, --terse                  Diferencia todos los archivos, pero solo muestra un hexdump del primer archivo

Opciones de compresión RAW:
    -X, --deflate                Escanea en busca de flujos de compresión deflate en bruto
    -Z, --lzma                   Escanea en busca de flujos de compresión LZMA en bruto
    -P, --partial                Realiza un escaneo superficial, pero más rápido
    -S, --stop                   Detiene después del primer resultado

Opciones generales:
    -l, --length=           Número de bytes a escanear
    -o, --offset=           Comienza el escaneo en este desplazamiento de archivo
    -O, --base=             Agrega una dirección base a todos los desplazamientos impresos
    -K, --block=            Establece el tamaño del bloque de archivo
    -g, --swap=             Invierte cada n bytes antes de escanear
    -f, --log=             Registra resultados en un archivo
    -c, --csv                    Registra resultados en un archivo en formato CSV
    -t, --term                   Formatea la salida para ajustarse a la ventana del terminal
    -q, --quiet                  Suprime la salida a stdout
    -v, --verbose                Habilita una salida detallada
    -h, --help                   Muestra la salida de ayuda
    -a, --finclude=         Solo escanea archivos cuyos nombres coincidan con esta expresión regular
    -p, --fexclude=         No escanea archivos cuyos nombres coincidan con esta expresión regular
    -s, --status=           Habilita el servidor de estado en el puerto especificado

Escaneado de imágenes

Comencemos buscando las firmas de los archivos dentro de la imagen (imagen del sitio TP-Link).

Ejecutando binwalk con el parámetro —signature:

$ binwalk --signature --term archer-c7.bin

DECIMINAL       HEXADECIMAL     DESCRIPCIÓN
------------------------------------------------------------------------------------------
21876         0x5574          Cadena de versión de U-Boot, "U-Boot 1.1.4-g4480d5f9-dirty (20 de
                              mayo de 2019 - 18:45:16)"
21940         0x55B4          Tabla de polinomios CRC32, big endian
23232         0x5AC0          Encabezado de uImage, tamaño del encabezado: 64 bytes, CRC del encabezado:
                              0x386C2BD5, creado: 2019-05-20 10:45:17, tamaño de la imagen:
                              41162 bytes, Dirección de Datos: 0x80010000, Punto de Entrada:
                              0x80010000, CRC de datos: 0xC9CD1E38, SO: Linux, CPU: MIPS,
                              tipo de imagen: Imagen de Firmware, tipo de compresión: lzma, nombre de
                              imagen: "imagen de u-boot"
23296         0x5B00          Datos comprimidos LZMA, propiedades: 0x5D, tamaño del diccionario:
                              8388608 bytes, tamaño descomprimido: 97476 bytes
64968         0xFDC8          Documento XML, versión: "1.0"
78448         0x13270         Encabezado de uImage, tamaño del encabezado: 64 bytes, CRC del encabezado:
                              0x78A267FF, creado: 2019-07-26 07:46:14, tamaño de la imagen:
                              1088500 bytes, Dirección de Datos: 0x80060000, Punto de Entrada:
                              0x80060000, CRC de datos: 0xBB9D4F94, SO: Linux, CPU: MIPS,
                              tipo de imagen: Imagen de Múltiples Archivos, tipo de compresión: lzma,
                              nombre de imagen: "MIPS OpenWrt Linux-3.3.8"
78520         0x132B8         Datos comprimidos LZMA, propiedades: 0x6D, tamaño del diccionario:
                              8388608 bytes, tamaño descomprimido: 3164228 bytes
1167013       0x11CEA5        Sistema de archivos Squashfs, little endian, versión 4.0,
                              compresión:xz, tamaño: 14388306 bytes, 2541 inodos,
                              tamaño de bloque: 65536 bytes, creado: 2019-07-26 07:51:38
15555328      0xED5B00        Datos comprimidos gzip, desde Unix, última modificación: 2019-07-26
                              07:51:41

Ahora tenemos mucha información sobre esta imagen.

La imagen utiliza U-Boot como cargador de arranque (encabezado de la imagen en la dirección 0x5AC0 y la imagen comprimida del cargador en la dirección 0x5B00). A partir del encabezado de uImage en la dirección 0x13270, sabemos que la arquitectura del procesador es MIPS y el núcleo de Linux es la versión 3.3.8. Y basándonos en la imagen encontrada en la dirección 0x11CEA5, podemos ver que rootfs es el sistema de archivos squashfs.

Ahora descomprimamos el cargador (U-Boot) usando el comando dd:

$ dd if=archer-c7.bin of=u-boot.bin.lzma bs=1 skip=23296 count=41162
41162+0 registros entrantes
41162+0 registros salientes
41162 bytes (41 kB, 40 KiB) copiados, 0.0939608 s, 438 kB/s

Dado que la imagen está comprimida con LZMA, necesitamos descomprimirla:

$ unlzma u-boot.bin.lzma

Ahora tenemos la imagen de U-Boot:

$ ls -l u-boot.bin
-rw-rw-r-- 1 sprado sprado 97476 Feb  5 08:48 u-boot.bin

¿Qué tal buscar el valor por defecto para bootargs?

$ strings u-boot.bin | grep bootargs
bootargs
bootargs=console=ttyS0,115200 board=AP152 rootfstype=squashfs init=\/etc\/preinit mtdparts=spi0.0:128k(factory-uboot),192k(u-boot),64k(ART),1536k(uImage),14464k@0x1e0000(rootfs) mem=128M

Variable de entorno U-Boot bootargs se utiliza para pasar parámetros al núcleo de Linux. Y a partir de lo anterior, entendemos mejor la memoria flash del dispositivo.

¿Qué tal si extraemos la imagen del núcleo de Linux?

$ dd if=archer-c7.bin of=uImage bs=1 skip=78448 count=1088572
1088572+0 registros en
1088572+0 registros fuera
1088572 bytes (1,1 MB, 1,0 MiB) copiados, 1,68628 s, 646 kB/s

Podemos verificar que la imagen se ha extraído correctamente con el comando file:

$ file uImage
uImage: u-boot legacy uImage, MIPS OpenWrt Linux-3.3.8, Linux/MIPS, Multi-File Image (lzma), 1088500 bytes, Vie Jul 26 07:46:14 2019, Load Address: 0x80060000, Entry Point: 0x80060000, Header CRC: 0x78A267FF, Data CRC: 0xBB9D4F94

El formato del archivo uImage es básicamente una imagen del núcleo de Linux con una cabecera adicional. Ahora eliminemos esta cabecera para obtener la imagen final del núcleo de Linux:

$ dd if=uImage of=Image.lzma bs=1 skip=72
1088500+0 registros en
1088500+0 registros fuera
1088500 bytes (1,1 MB, 1,0 MiB) copiados, 1,65603 s, 657 kB/s

La imagen está comprimida, así que descomprimámosla:

$ unlzma Image.lzma

Ahora tenemos la imagen del núcleo de Linux:

$ ls -la Image
-rw-rw-r-- 1 sprado sprado 3164228 Feb  5 10:51 Image

¿Qué podemos hacer con la imagen del núcleo? Podríamos, por ejemplo, buscar cadenas en la imagen y encontrar la versión del núcleo de Linux y obtener información sobre el entorno utilizado para compilar el núcleo:

$ strings Image | grep "Linux version"
Linux version 3.3.8 (leo@leo-MS-7529) (gcc version 4.6.3 20120201 (prerelease) (Linaro GCC 4.6-2012.02) ) #1 Lun May 20 18:53:02 CST 2019

A pesar de que el firmware fue lanzado el año pasado (2019) cuando escribo este artículo, utiliza una versión antigua del núcleo de Linux (3.3.8) lanzada en 2012, compilada con una versión muy antigua de GCC (4.6) también de 2012!
(nota del traductor, ¿todavía confías en tus routers en la oficina y en casa?)

Con la opción --opcodes también podemos usar binwalk para buscar instrucciones de máquina y determinar la arquitectura del procesador de la imagen:

$ binwalk --opcodes Image
DECIMAL       HEXADECIMAL     DESCRIPCIÓN
--------------------------------------------------------------------------------
2400          0x960           instrucciones MIPS, epílogo de función
2572          0xA0C           instrucciones MIPS, epílogo de función
2828          0xB0C           instrucciones MIPS, epílogo de función

¿Qué pasa con el sistema de archivos raíz? En lugar de extraer la imagen manualmente, utilicemos la opción binwalk --extract:

$ binwalk --extract --quiet archer-c7.bin

El sistema de archivos raíz completo se extraerá en un subdirectorio:

$ cd _archer-c7.bin.extracted/squashfs-root/

$ ls
bin  dev  etc  lib  mnt  overlay  proc  rom  root  sbin  sys  tmp  usr  var  www

$ cat etc/banner
     MM           NM                    MMMMMMM          M       M
   $MMMMM        MMMMM                MMMMMMMMMMM      MMM     MMM
  MMMMMMMM     MM MMMMM.              MMMMM:MMMMMM:   MMMM   MMMMM
MMMM= MMMMMM  MMM   MMMM       MMMMM   MMMM  MMMMMM   MMMM  MMMMM'
MMMM=  MMMMM MMMM    MM       MMMMM    MMMM    MMMM   MMMMNMMMMM
MMMM=   MMMM  MMMMM          MMMMM     MMMM    MMMM   MMMMMMMM
MMMM=   MMMM   MMMMMM       MMMMM      MMMM    MMMM   MMMMMMMMM
MMMM=   MMMM     MMMMM,    NMMMMMMMM   MMMM    MMMM   MMMMMMMMMMM
MMMM=   MMMM      MMMMMM   MMMMMMMM    MMMM    MMMM   MMMM  MMMMMM
MMMM=   MMMM   MM    MMMM    MMMM      MMMM    MMMM   MMMM    MMMM
MMMM$ ,MMMMM  MMMMM  MMMM    MMM       MMMM   MMMMM   MMMM    MMMM
  MMMMMMM:      MMMMMMM     M         MMMMMMMMMMMM  MMMMMMM MMMMMMM
    MMMMMM       MMMMN     M           MMMMMMMMM      MMMM    MMMM
     MMMM          M                    MMMMMMM        M       M
       M
 ---------------------------------------------------------------
   For those about to rock... (%C, %R)
 ---------------------------------------------------------------

Ahora podemos hacer muchas cosas diferentes.

Podemos buscar archivos de configuración, hashes de contraseñas, claves criptográficas y certificados digitales. Podemos analizar archivos binarios para buscar errores y vulnerabilidades.

Con qemu y chroot incluso podemos ejecutar (emular) un archivo ejecutable desde la imagen:

$ ls
bin  dev  etc  lib  mnt  overlay  proc  rom  root  sbin  sys  tmp  usr  var  www

$ cp /usr/bin/qemu-mips-static .

$ sudo chroot . ./qemu-mips-static bin/busybox
BusyBox v1.19.4 (2019-05-20 18:13:49 CST) binario de múltiples llamadas.
Copyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko
y otros. Licenciado bajo GPLv2.
Vea la distribución de origen para el aviso completo.

Uso: busybox [función] [argumentos]...
   o: busybox --list[-full]
   o: función [argumentos]...

    BusyBox es un binario de múltiples llamadas que combina muchas utilidades Unix comunes
en un solo ejecutable. La mayoría de las personas crearán un enlace a busybox para cada función que desean usar y BusyBox
    actuará como lo que se invocó.

Funciones actualmente definidas:
    [, [[, addgroup, adduser, arping, ash, awk, basename, cat, chgrp, chmod, chown, chroot, clear, cmp, cp, crond, crontab, cut, date, dd, delgroup, deluser, dirname, dmesg, echo, egrep, env, expr, false,
    fgrep, find, free, fsync, grep, gunzip, gzip, halt, head, hexdump, hostid, id, ifconfig, init, insmod, kill, killall, klogd, ln, lock, logger, ls, lsmod, mac_addr, md5sum, mkdir, mkfifo, mknod, mktemp,
    mount, mv, nice, passwd, pgrep, pidof, ping, ping6, pivot_root, poweroff, printf, ps, pwd, readlink, reboot, reset, rm, rmdir, rmmod, route, sed, seq, sh, sleep, sort, start-stop-daemon, strings,
    switch_root, sync, sysctl, tail, tar, tee, telnet, test, tftp, time, top, touch, tr, traceroute, true, udhcpc, umount, uname, uniq, uptime, vconfig, vi, watchdog, wc, wget, which, xargs, yes, zcat

¡Genial! Pero ten en cuenta que la versión de BusyBox es 1.19.4. Es una versión muy antigua de BusyBox, lanzada en abril de 2012.

Así que TP-Link lanza la imagen del firmware en 2019 utilizando software (GCC toolchain, kernel, BusyBox, etc.) de 2012!

Ahora entiendes por qué siempre instalo OpenWRT en mis enrutadores?

Esto no es todo

Binwalk también puede realizar un análisis de entropía, imprimir datos de entropía sin procesar y generar gráficos de entropía. Generalmente, una alta entropía se observa cuando los bytes en la imagen son aleatorios. Esto puede significar que la imagen contiene un archivo cifrado, comprimido u ofuscado. ¿Un clave de cifrado escrita a mano? ¿Por qué no?

Ingeniería inversa de un router doméstico con binwalk. ¿Confías en el software de tu router?

También podemos usar el parámetro --raw para buscar una secuencia personalizada de bytes sin procesar en la imagen o el parámetro --hexdump para realizar un volcado hexadecimal que compara dos o más archivos de entrada.

Las firmas personalizadas pueden ser añadidas a binwalk ya sea a través de un archivo de firmas personalizadas especificado en la línea de comandos con el parámetro --magic, o añadiéndolas al directorio $ HOME / .config / binwalk / magic.

Puedes encontrar más información sobre binwalk en documentación oficial.

La extensión de binwalk

Hay un API de binwalk, implementado como un módulo de Python, que puede ser utilizado por cualquier script de Python para realizar escaneos de binwalk programáticamente, y la utilidad de línea de comandos binwalk puede ser casi completamente replicada en solo dos líneas de código Python.

import binwalk
binwalk.scan()

Con la API de Python también puedes crear plugins en Python para personalizar y extender binwalk.

También existe un plugin IDA y una versión en la nube Binwalk Pro.

Entonces, ¿por qué no descargas una imagen de firmware de Internet y pruebas binwalk? Prometo que te divertirás mucho 🙂

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster