2019/03/20

Jugando con los rayos 1: obteniendo el firmware via serial


Al contexto de esto se llega por el índice.

Los pasos son escribir "tpl" para acceder al monitor y con

md offset length

ir bajando la memoria. Si oprimís enter tiene autoincremento.

Comencé poniendo un peso en la tecla pero no escala, no no. Así que a recordar expect:

#!/usr/bin/expect --
spawn /usr/bin/miniterm.py /dev/ttyUSB1 115200
expect {
  "Autobooting in 1 seconds*" {
    send "tpl\n"
    expect {
      "db12x> " {
         send "md
9f020000 20\n"
         while 1 {
           expect "db12x> " {
             send "\n"
           }
         }
      }
    }
  }
}



y su invocación:

expect capture.tcl > 9f020000.hex

Tras limpiar un poquito con grep, lo convertimos a binario:

grep ":" 9f020000.hex | xxd -r > 9f020000.bin

y ese binario le corremos binwalk:

binwalk -e 9f020000.bin





Te preguntarás de dónde salió la elección de la dirección 9f020000.

db12x> printenv
 

bootargs=console=ttyS0,115200 root=31:02 rootfstype=squashfs init=/sbin/init mtdparts=ath-nor0:256k(u-boot),64k(u-boot-env),6336k(rootfs),1408k(uImage),64k(mib0),64k(ART)
 

bootcmd=bootm 0x9f020000

De paso nos queda este muy útil script, para no tener que estar tipeando "tpl" a gran velocidad:

#!/usr/bin/expect --
spawn /usr/bin/miniterm.py /dev/ttyUSB1 115200
expect {
  "Autobooting in 1 seconds*" {
    send "tpl\n"
    expect {
      "db12x> " {
         interact
         }
      }
    }
  }
}


binwalk obtiene todo excelentemente de las imágenes de firwmare bajadas de tplink, pero de estos volcados no.

La idea seguiente es buscar el firmware.bin en los volcados:

sudo apt install yara



yara es una herramienta para investigar malware, que tiene la capacidad de buscar patrones de datos en archivos, lo cual me viene muy bien para lo que necesito que es hallar el firmware en el dump de memoria de un router dañado por un rayo, si es que es posible.


Mediante acceso al puerto serial del router puedo hacer dumps de la memoria si arranco el monitor que tiene. El router es un TP-LINK WDR3600n.

Tengo la esperanza de que parte de ese dump corresponda a la memoria flash así no tengo que conseguir o armar la pinza soic8 y programar la lectura de la flash, otra nota aparte.

Por el otro tengo varios firmwares, asi que la idea es buscar en dump los firmwares hasta ver si coinciden.


¿Qué hay que buscar? 



Las letritas en hexadecimal.

¿Cómo buscarlo?



sudo apt install yara

ok?

Y crear las reglas, por ejemplo, en yara/rule-firmware.yara

rule Firmware
{
  strings:
    $hex_string = {

      01 00 00 00 54 50 2d 4c  49 4e 4b 20 54 65 63 68
    }

  condition:
    $hex_string
}


Luego ejecutar

yara yara/rule-firmware.yara capture

Sería conveniente que en la carpeta capture sólo estén los binarios, pues yara busca en todo.

Ah, antes, para controlar que todo esté funcionando, podemos buscar algo que sabemos que vamos a encontrar, no olvidemos que nunca antes hemos usado yara y no tenemos idea de que trae ni vamos a leer el manual hasta que nos trabemos:




Acá hemos obtenido unos hexa () que hemos puesto en la regla yara/rule-control.yara y buscado en capture/00000000.bin


Volviendo, tras ejecutar la búsqueda, lo hemos hallado en capture/9f020000.bin, pero no sabemos cual de los tres firmwares es y nos sería útil saber en que punto difieren los firmwares, un poco de bash y listo:




tenemos que hacer una regla para cada firmware tal que llegue hasta un poco más hallá de la diferencia, tipo hasta 0x4f, ok?

Tenemos entonces un archivo de reglas para los tres firmwares que bajamos:


rule Firmware_1
{
  strings:
    $hex_string = {
      01 00 00 00 54 50 2d 4c  49 4e 4b 20 54 65 63 68
      6e 6f 6c 6f 67 69 65 73  00 00 00 00 76 65 72 2e
      20 31 2e 30 00 00 00 00  00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
      36 00 00 01 00 00 00 01  00 00 00 00 f1 63 1c 98
    }
 

  condition:
    $hex_string
}
rule Firmware_2
{
  strings:
    $hex_string = {
      01 00 00 00 54 50 2d 4c  49 4e 4b 20 54 65 63 68
      6e 6f 6c 6f 67 69 65 73  00 00 00 00 76 65 72 2e
      20 31 2e 30 00 00 00 00  00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
      36 00 00 01 00 00 00 01  00 00 00 00 fd 6a 69 c2
    }

  condition:
    $hex_string
}
rule Firmware_3
{
  strings:
    $hex_string = {
      01 00 00 00 54 50 2d 4c  49 4e 4b 20 54 65 63 68
      6e 6f 6c 6f 67 69 65 73  00 00 00 00 76 65 72 2e
      20 31 2e 30 00 00 00 00  00 00 00 00 00 00 00 00
      00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
      36 00 00 01 00 00 00 01  00 00 00 00 19 2d 99 29
    }

  condition:
    $hex_string
}


Ufa!! no encuentra ninguno, achiquemos... quitándole la quinta linea coincide, eso significa que el firmware que tenemos no es el que bajamos. Vamos a tener que tomar otro camino mientras.

Si recordamos que el objetivo es bajar el firmware en el router, tendríamos que verificar tomando entre el match de la regla y la longitud del firmware si es un firmware.




Si en capture/9f020000.bin, antes de 9F7F0200 (9f020000 + 7d0200) tenemos unos pocos bytes distintos de cero y luego todos ceros y luego todos 0xff, podríamos sospechar que es lo que buscamos. De un modo un otro, tomando el segmento 9f020000 .. 9F7F0200 como si fuera un firmware y ejecutándole binwalk, deberíamos obtener algo parecido a lo que se obtiene de cualquier otro firmware.

Mirando para atras, nos pudimos haber arreglado sin yara. De hecho, no he podido obtener el desplazamiento del match en el archivo y tuve que buscar con grep en el .hex. Pero claro, eso lo sé ahora.

Procedimiento completo


  1. expect capture.tcl | tee 9f020000.hexdump.noisy
  2. grep -P \
    '^[0-9a-f]{8}:( [0-9a-f]{8}){4}    .{16}' \ 9f020000.hexdump.noisy > 9f020000.hexdump
  3. dos2unix 9f020000.hexdump
  4. cut -b 11-45 9f020000.hexdump > 9f020000.hex
  5. xxd 9f020000.hex -r -p > 9f020000.bin
  6. binwalk -e  9f020000.bin

 

Explicaciones


  1. El script capture.tcl invoca el monitor y le pide que haga dump indefinidamente, hasta que uno decida cortar. Para eso está el tee, que va salvando en el archivo mientras muestra en pantalla.
  2. El grep limpia el ruido de todo el diálogo, sólo deja el volcado.
  3. El dos2unix arregla los saltos de linea.
  4. El cut quita las direcciones y el render para que no le molesta a...
  5. El xxd convierte de notación hexadecimal a binario.
  6. El binwalk extrae lo que haya dentro del binario.

Y luego hacemos

cat _9f020000.bin.extracted/squashfs-root/etc/shadow 

que nos da...

root:$1$GTN.gpri$DlSyKvZKMR9A9Uj9e9wR3/:15502:0:99999:7:::

que es lo mismo que teníamos en los otros firmwares, fallamos, no hemos podido ingresar al linux funcionando

Solo nos resta averiguar que firmware es, ¿no?

Un recurso sería buscar el md5 del volcado y los firmwares, pero aunque los archivos comprimidos están, los descomprimidos no. Comprimir el volcado no debería servir, pues debería haberse aplicado exactamente la misma compresión, mmhhh, probemos igual.

for level in {1..9} ; do
   zip firmware$level.zip -"$level" ../capture3/9f020000.bin
done

Lástima que no puedo saber cual es el nombre del archivo original, que forma parte del .zip o sea que influye al hash, dead end.

Dejo acá los hashes de los firmares que tengo...


768584458745f2a5e2ed24cb77ba3d8c  wdr3600v1_en_3_14_1_up_boot(141022).bin
25f0d01aaa74a00a929330d75887a200  wdr3600v1_en_3_14_1_up_boot(150302).bin
faf0c2b2128141c587f06a27d7fabe6a  wdr3600v1_en_3_14_3_up_boot(150518).bin


y del que obtuve:



20b3566386a50ea3afb7fb8330736edb  9f020000.bin


Estos son los que se obtienen en el sitio oficial


7e21d127116d48d0a05e54fc78636ebc  TL-WDR3600_V1_141022.zip
56cf77919b60c32cc6bb49b991881baa  TL-WDR3600_v1_150302.zip
efbdeebd5c85fdb857d23e17d22c4970  TL-WDR3600_V1_150518.zip


No me alcanza, quiero saber que está pasando... dirdiff es mi nueva esperanza.

Esto es dirdiff contra el último oficial, TL-WDR3600_V1_150518:


Primero no veia nada, cuando activé "options -> show files that are identical" me apareció así. Lo comparé con los anteriores y se mantuvo idéntico, sólo cambiando la fecha de modificación. Quedan dos archivos más:


200.7z
7E3C60.7z

que en el los firmwares oficiales tienen otro nombre:

20400.7z
3E60.7z

0328325baa82949c0c063df84b8b6718 _wdr3600v1_en_3_14_3_up_boot(150518)/20400.7z
9f92aa0eaa3d4ebe53660aba5d1d78e5 _wdr3600v1_en_3_14_3_up_boot(150518)/3E60.7z


3d1b44907feb914380a05eb4ccdd2d13 _wdr3600v1_en_3_14_1_up_boot(141022)/20400.7z
f6c55acfa5a2beacf86bccea88ef7be7 _wdr3600v1_en_3_14_1_up_boot(141022)/3E60.7z


c4220429117cbd64cb4372fed422c858 _wdr3600v1_en_3_14_1_up_boot(150302)/20400.7z
ea8a66b8071a63b5ab04bc649b09f8ba _wdr3600v1_en_3_14_1_up_boot(150302)/3E60.7z


348c14f63d8947f43c8d11d6afd0ed38  _wdr3600v1_en_3_14_3_up_boot(150518)/20400
eef72299e5c46f3796cb4c6ce63cf936  _9f020000/7E3C60



Los filesystems son idénticos:

da91975154424bd4e088a8a3f5b808d6 v1_en_3_14_3_up_boot(150518)/120200.squashfs
da91975154424bd4e088a8a3f5b808d6 _9f020000.bin.extracted/100000.squashfs

Esto amerita mucho más investigación, pero como se rompió el router, por ahora no puedo avanzar más.








No hay comentarios:

Publicar un comentario