Dumpear la flash vía BOOTLOADER RTL867X de un router H108N v2.3

Model 	ZXHN H108N V2.3
Hardware Version 	V1.1
Software Version 	V2.3.0_ES1C5
Boot Loader Version 	V1.1.0
DSL Firmware Version 	4923c118

En este caso vamos a intentar conseguir el volcado de la flash y acceso como root para el dipositivo ZTE H108N v2.3. Como siempre la versión de la flash es determinante ya que cada firmware puede diferir bastante. En este caso es la versión V2.3.0_ES1C5.

Una alternativa un poco más complicada pero efectiva es conseguir acceso a nuestro router usando UART/RS232, acceder al bootloader, y usar comandos del bootloader para volcar la memoria del dispositivo.

Conectarnos al puerto serie

Adjunto las capturas de pantalla para identificar los pines y como conectarnos al puerto serie.

Como es habitual usamos microcom y nos conectamos al dispositivo:

$ microcom -p /dev/ttyUSB0

Es muy recomendable en mi opinión, guardar un bootlog completo ya que nos será muy útil a la hora de entender la organización del a flash y direcciones de memoria, y poder consularlo de manera cómoda y sencilla.

En mi caso antes de iniciar el router, accedo al menú de microcom y configuro el log de la sesión. Para acceder al menú hay que presionar ctrl + 4 y ejecutar el comando log <logfile>, y posteriormente escribir exit para salir del menú. Ej:

> log zte-h108n-bootlog.log
exit

Este es mi bootlog: https://gitlab.com/-/snippets/3680856

Acceder al bootloader

Si observamos el bootloog, hay dos opciones al iniciar el dispositivo: console y debug.

Start to decompress!
Booting
Press '1' to enter BOOT console...
Press '2' to enter DEBUG mode......

Ext. phy is not found. 
Boot from NOR/SPI flash

To read reset key,if on,to update
https://gitlab.com/-/snippets/3

Presionamos 1 y accedemos a la consola del bootloader, y escribimos help para ver qué opciones tenemos:
Booting
Press '1' to enter BOOT console...
Press '2' to enter DEBUG mode......
Ext. phy is not found. 
Boot from NOR/SPI flash

To read reset key,if on,to update
(c)Copyright Realtek, Inc. 2011
Project RTL8676 LOADER (LZMA)
Version V1.1.0 (Mar  5 2013 19:39:22)

<RTL867X>help
help
info
reboot
run [app addr] [entry addr]
r [addr]
w [addr] [val]
d [addr] <len>
resetcfg
mac ["clear"/"osk"/mac address]
bootline
entry [address]
load [address]
xmodem [address]
tftp [ip] [server ip] [file name]
web
flashsize [256(k)/128(k)/1(M)/2(M)/4(M)/8(M)/16(M)]
memsize ROW[2k/4k/8k/16k] COL[256/512/1k/2k/4k] BANK[2/4]
uart [0(enable)/1(disable)]

Como siempre, cuanta más información recopilemos, mejor, por eso vamos a echar un vistazo a info y a bootline

<RTL867X>info
(c)Copyright Realtek, Inc. 2011
Project RTL8676 LOADER (LZMA)
Version V1.1.0 (Mar  5 2013 19:39:22)

<RTL867X>BootLine: 
MAC Address [0]: 00:23:79:11:22:33
Entry Point: 0x80000000
Load Address: 0x80000000
Application Address: 0xBD020000
Flash Size: 16M
Memory Configuration: ROW:8K COL:512 Bank:4Banks
MII Selection: 0 (0: Int. PHY  1: Ext. PHY)
UART is enabled

Más adelante veremos que tanto el entry proint como application address nos serán de ayuda.

Dumpear la flash

Para evitar las limitaciones del sistema operativo, usamos el bootloader que nos permite volcar por consola direcciones de memoria. Lo que haremos es poner a logear microcom dumplear toda la flash, por consola, limpiar el fichero y convertirlo a binario, luego pasaremos binwalk para identificar y extraer contido del firmware.

Entonces, con el router en el bootloader, como vimos anteriormente, configuramos el log control + 4 y log zte-h108n-wholeflash.hex y exit. Con esto ya empezamos a logear el contenido.

A continuación dumpeareamos la flash usando el comando d, para ello necesitamos saber la dirección de memoria donde empezar a leer y la longitud a leer.

d 0xbd000000 0x1000000

Le damos al enter, y a esperar unas horas…

Cómo identificar las zonas de memoria a dumpear.

Para poder identificar dónde está la zona de memoria que corresponde a la flash, tendremos que leer detenidamente el bootlog, ya que nos da la información necesaria para entender el mapa de memoria del dispositivo.

En este caso lo importante es:

flash device: 0x800000 at 0xbd000000
spi probe...
SFCR:0xb8001200 SFCSR:0xb8001208 SFDR:0xb800120c
can not get SPI chip driver!

MXIC matched!!get SPI chip driver!
Flash size is 0x1000000 
Physically mapped flash: Found an alies 0x1000000 for the chip at 0x0, mxic device detect.
Creating 7 MTD partitions on "Physically mapped flash":
0x000000000000-0x000001000000 : "whole_flash"
0x000000000000-0x000000020000 : "bootloader"
0x000000020000-0x000000080000 : "userconfig"
0x000000080000-0x000000600000 : "filesystem1"
0x000000600000-0x000000840000 : "kernel1"
0x000000840000-0x000000a80000 : "kernel2"
0x000000a80000-0x000001000000 : "filesystem2"

Como vemos la memoria flash comienza en 0xbd000000

flash device: 0x800000 at 0xbd000000

El tamaño de la flash es 0x1000000

Flash size is 0x1000000

Extraer la imagen binaria del volcado hexadecimal

Una vez que el volcado haya termiando ( dura horas ) deberías echar un ojo al fichero de log zte-h108n-wholeflash.hex por si hubiera alguna linea extra de log que no nos interesa. El fichero de log tiene un aspecto como este:

d 0xBD000000 0x1000000
0xBD000000: 10 00 00 FF 00 00 00 00 10 00 01 05 00 00 00 00 ................
0xBD000010: 00 00 00 00 00 00 00 00 10 00 FF F9 00 00 00 00 ................
0xBD000020: 10 00 FF F7 00 00 00 00 10 00 FF F5 00 00 00 00 ................
0xBD000030: 10 00 FF F3 00 00 00 00 10 00 FF F1 00 00 00 00 ................
0xBD000040: 10 00 FF EF 00 00 00 00 10 00 FF ED 00 00 00 00 ................

La herramienta que nos permite convertir este volcado hexadecimal a binario es xdd o hacertelo a mano claro. En mi caso como necesito unos ligeros cambios en el fichero para que xdd lo lea correctamente, hago lo siguiente:

cat zte-h108n-wholeflash.hex | sed 's/^.*0x//g' | xxd -r > zte-h108n-wholeflash.bin

Este comando elimina «0x» del comienzo de linea y lo pasa a xdd. El problema es que como tenemos una dirección base de 0xBD000000, tenemos desde la dirección 0x00000000 a la 0xBD000000 solamente con 0. Eso son gigas en el disco sin necesidad.

Supuestamente se podría usar xdd de esta manera para evitar este comportamiento

xxd -r -s "-0xBD000000"

Aunque en mi caso no funciona y lo soluciono, cortando el fichero. Es muy cutre, pero eficaz.

dd if=zte-h108n-wholeflash.bin of=zte-h108n-wholeflash.strip.bin skip=$((0xBD000000)) iflag=skip_bytes,count_bytes

Analizar la memoria flash con binwalk

Binwalk es una herramienta excepcional para la búsqueda de estructuras. En nuestro caso lanzamos binwalk directamente para ver qué identifica.

$ binwalk  zte-h108n-wholeflash.strip.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
131708        0x2027C         Zlib compressed data, compressed
197244        0x3027C         Zlib compressed data, compressed
230012        0x3827C         Zlib compressed data, compressed
237580        0x3A00C         Zlib compressed data, compressed
250492        0x3D27C         PEM RSA private key
251455        0x3D63F         PEM certificate
262780        0x4027C         Zlib compressed data, compressed
270232        0x41F98         Zlib compressed data, compressed
270452        0x42074         Zlib compressed data, compressed
270724        0x42184         Zlib compressed data, compressed
328316        0x5027C         Zlib compressed data, compressed
524288        0x80000         Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 4227847 bytes, 869 inodes, blocksize: 131072 bytes, created: 2015-06-22 08:45:55
6291712       0x600100        LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 4704904 bytes
8651008       0x840100        LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 4704904 bytes
11010048      0xA80000        Squashfs filesystem, little endian, version 4.0, compression:lzma, size: 4227847 bytes, 869 inodes, blocksize: 131072 bytes, created: 2015-06-22 08:45:55

Es importante recuperar ahora otra parte del bootlog en la que se muestran las zonas de memoria de la flash

Creating 7 MTD partitions on «Physically mapped flash»:
0x000000000000-0x000001000000 : «whole_flash»
0x000000000000-0x000000020000 : «bootloader»
0x000000020000-0x000000080000 : «userconfig»
0x000000080000-0x000000600000 : «filesystem1»
0x000000600000-0x000000840000 : «kernel1»
0x000000840000-0x000000a80000 : «kernel2»
0x000000a80000-0x000001000000 : «filesystem2»

Podemos ver las coincidencias de las particiones de la memoria con lo que encuentra binwalk. Hay una ligera diferencia de los comienzos de bloques pero podemos observar que son cabeceras y que realmente las estructuras lzma o sqashfs están justamente donde binwalk las localiza.

Para acabar una forma sencilla de seccionar el fichero de la flash en las partes correspondientes y trabajar con el sería así:

dd if=zte-h108n-wholeflash.strip.bin of=bootloader count=$((0x20000)) iflag=skip_bytes,count_bytes
dd if=zte-h108n-wholeflash.strip.bin of=userconfig skip=$((0x20000)) count=$(( $((0x80000)) - $((0x20000)) )) iflag=skip_bytes,count_bytes
dd if=zte-h108n-wholeflash.strip.bin of=filesystem1 skip=$((0x80000)) count=$(( $((0x600000)) - $((0x80000)) )) iflag=skip_bytes,count_bytes
dd if=zte-h108n-wholeflash.strip.bin of=kernel1 skip=$((0x600000)) count=$(( $((0x840000)) - $((0x600000)) )) iflag=skip_bytes,count_bytes
dd if=zte-h108n-wholeflash.strip.bin of=kernel2 skip=$((0x840000)) count=$(( $((0xa80000)) - $((0x840000)) )) iflag=skip_bytes,count_bytes
dd if=zte-h108n-wholeflash.strip.bin of=filesystem2 skip=$((0xa80000)) count=$(( $((0x1000000)) - $((0xa80000)) )) iflag=skip_bytes,count_bytes

Siguientes pasos…

En próximos artículos entramos a analizar el contenido de filesystem para localizar las credenciales que nos permitan acceder al dispositivo como root, o como cualquier otro usuario.

También hablaremos de como descifrar y cifrar el fichero de configuración del modelo H108N

Para acabar formas alternativas de conseguir información acerca del dispositivo cuando no tenemos acceso a él.


Publicado

en

,

por

Comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.