[Tutorial] Reversing AXIS Q6032-E Network Camera Firmware



Hace tiempo que tenía ganas de escribir este post, si hay algo que me gusta del mundo del hacking es el reversing y todavía mas si hablamos de sistemas embebidos. En este post vamos a ver como extraer todos los archivos incluidos en una imagen de firmware.

Quiero avisar desde un principio que esto no es una ciencia exacta, por lo que lo que hagamos para esta imagen puede funcionar con el firmware de otra sistema o no, por lo que la utilidad de este texto es servir como guía para conocer la metodología de trabajo y las herramientas que harán nuestra vida mas fácil a la hora de buscar vulnerabilidades en este tipo de sistemas.

En primer lugar vamos a preparar nuestro arsenal de herramientas para estos menesteres:

  • Firmware Mod Kit es un set de herramientas para descompresión y reconstrucción del firmware.
  • Binwalk es una herramienta que reconoce las cabeceras de los archivos entre otras cosas. 
  • Comandos útiles del sistema: dd, strings, hexdump, gunzip, unzip, tar ...
Todo lo anterior excepto firmware mod kit viene integrado en Kali Linux por lo que si lo tenéis mano os ahorraréis el trabajo de instalarlo.

 Bien, empecemos. Lo primero será descargar la imagen de la página del vendor




Ahora que ya tenemos la imagen a nuestra entera disposición tenemos que saber a lo que nos enfrentamos por lo que utilizaremos los comandos file, strings y hexdump para hacernos una primera idea y lanzaremos binwalk para que nos aporte una visión general.

root@kali:~/Desktop/Firmwares# file Q6032-E_5_41_1_3.bin 
Q6032-E_5_41_1_3.bin: data

file no nos da un resultado concreto así que haremos la prueba con binwalk.

DECIMAL    HEX        DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
139074     0x21F42    gzip compressed data, from Unix, last modified: Fri May  3 13:26:13 2013, max compression
1835008    0x1C0000   JFFS2 filesystem, little endian 
10883365   0xA61125   Zip archive data, at least v2.0 to extract, name: "md/MotionDetection$MotionGroup.class"  
10885328   0xA618D0   Zip archive data, at least v2.0 to extract, name: "md/MotionDetection$3.class"  
10885576   0xA619C8   JFFS2 filesystem, little endian 
10904060   0xA661FC   GIF image data, version "89a", 14 x 10
10904140   0xA6624C   JFFS2 filesystem, little endian 
10913672   0xA68788   GIF image data, version "89a", 20 x 25
10913744   0xA687D0   JFFS2 filesystem, little endian 
10913876   0xA68854   GIF image data, version "89a", 20 x 25
10914040   0xA688F8   JFFS2 filesystem, little endian 
10914172   0xA6897C   GIF image data, version "89a", 20 x 25
10914336   0xA68A20   JFFS2 filesystem, little endian 
10914460   0xA68A9C   GIF image data, version "89a", 439 x 143
10915144   0xA68D48   JFFS2 filesystem, little endian 
10915528   0xA68EC8   GIF image data, version "89a", 9 x 9
10915588   0xA68F04   JFFS2 filesystem, little endian 
10915712   0xA68F80   GIF image data, version "89a", 13 x 9
10915776   0xA68FC0   JFFS2 filesystem, little endian 
10915904   0xA69040   GIF image data, version "89a", 9 x 9
10915968   0xA69080   JFFS2 filesystem, little endian 
10916100   0xA69104   GIF image data, version "89a", 9 x 9
10916164   0xA69144   JFFS2 filesystem, little endian 
10916288   0xA691C0   GIF image data, version "89a", 13 x 9
10916352   0xA69200   JFFS2 filesystem, little endian 
10916476   0xA6927C   GIF image data, version "89a", 9 x 9

La salida de binwalk no nos aclara muchas dudas pero si que revela lo que parece una cabecera comprimida con gzip y lo que parece un sistema de archivos jffs2. Para empezar por algún lado extraemos la cabecera y la descomprimimos.

root@kali:~/Desktop/Firmwares# dd if=Q6032-E_5_41_1_3.bin bs=1 skip=139074 of=cabecera_gzip.gz
25288918+0 registros leídos
25288918+0 registros escritos
25288918 bytes (25 MB) copiados, 55,2072 s, 458 kB/s

root@kali:~/Desktop/Firmwares# file cabecera_gzip.gz 
cabecera_gzip.gz: gzip compressed data, from Unix, last modified: Fri May  3 13:26:13 2013, max compression

root@kali:~/Desktop/Firmwares# gunzip cabecera_gzip.gz 
gzip: cabecera_gzip.gz: decompression OK, trailing garbage ignored

root@kali:~/Desktop/Firmwares# ls
binwalk-1.2.1  cabecera_gzip  fmk  hexdump.txt  Q6032-E_5_41_1_3.bin  strings.txt

root@kali:~/Desktop/Firmwares# file cabecera_gzip 
cabecera_gzip: SysEx File - Twister

Ahora que ya tenemos la cabecera extraída, ya hemos confirmado que el archivo es lo que dice ser y lo hemos descomprimido volvemos a usar binwalk sobre esta nueva imagen para visualizar su contenido.

DECIMAL    HEX        DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
522326     0x7F856    ELF
565624     0x8A178    ELF
2170896    0x212010   Linux kernel version "2.6.35+ (romain@eater-3) (gcc version 4.3.1 20080521 (prereleasersion 4.3.1 20080521 (prerelease) [gcc-4_3-branch revision 135"
2246244    0x224664   JFFS2 filesystem, little endian 
2621682    0x2800F2   CramFS filesystem, little endian size 95428638 hole_support CRC 0x2414be1, edition 4199030383, 199344166 blocks, 1107692991 files

Como se puede ver esta vez si que tenemos una salida lógica, dos binarios, una imagen del kernel y dos sistemas de archivos. Para acortar la logitud del post vamos a ir directamente a por los sistemas de archivos pero si cortásemos la imagen hasta el offset donde está el kernel y corriésemos strings sobre el nuevo archivo podríamos verificar que se trata realmente del kernel.

root@kali:~/Desktop/Firmwares# strings -n 9 Linux_kernel | head -10
Linux version 2.6.35+ (romain@eater-3) (gcc version 4.3.1 20080521 (prerelease) [gcc-4_3-branch revision 135713] (GCC 4.3.1 Axis release R95/1.95) ) #1 Fri May 3 13:26:13 CEST 2013
%s version %s (romain@eater-3) (gcc version 4.3.1 20080521 (prerelease) [gcc-4_3-branch revision 135713] (GCC 4.3.1 Axis release R95/1.95) ) %s
crisv32_pinmux_init
RSDTtZXxKW
I pause_on_oops
<2>BUG: recent printk recursion!
printk.time
deprecated_sysctl_warning
print_dropped_signal
orderly_poweroff

De la anterior lectura de binwalk sobre lo extraido de la cabecera gzip vemos que el sistema de archivos de la cabecera se encuentra en la posición 2246244, para extraerla restamos la posición del siguiente archivo a la posición del archivo que queremos extraer 2621682 -  2246244 = 375438 bytes que es el tamaño del archivo que queremos extraer.

Utilizamos dd de nuevo con estos parámetros y sacamos  este sistema de archivos.

root@kali:~/Desktop/Firmwares# dd if=cabecera_gzip bs=1 skip=2246244 count=375438 of=cabecera-fs.jffs2
375438+0 registros leídos
375438+0 registros escritos
375438 bytes (375 kB) copiados, 0,812931 s, 462 kB/s

root@kali:~/Desktop/Firmwares# file cabecera-fs.jffs2 
cabecera-fs.jffs2: Linux jffs2 filesystem data little endian

Por último utilizando firmware mod kit compilamos el módulo de jffs2 y descomprimimos el sistema de archivos.

root@kali:~/Desktop/Firmwares# ./fmk/src/jffs2/unjffs2 filesystem.jffs2
root@kali:~/Desktop/Firmwares/jffs2-root# ls 
bin  dev  etc  linuxrc  tmp  var

Ya hemos extraído el sistema de archivos contenido en la cabecera, pero como se puede intuir no está completo y el contenido de las carpetas extraídas está vacío así que vamos a volver a la imagen inicial y trabajar sobre ella para ver donde está todo el contenido que nos falta.

Para ello vamos a cortar la imagen desde el final de la cabecera gzip hasta el final con el mismo método que vimos anteriormente.



root@kali:~/Desktop/Firmwares# dd if=Q6032-E_5_41_1_3.bin bs=1 skip=1835008 of=main-fs.jffs2
23592984+0 registros leídos
23592984+0 registros escritos
23592984 bytes (24 MB) copiados, 51,6769 s, 457 kB/s

root@kali:~/Desktop/Firmwares# file main-fs.jffs2 
main-fs.jffs2: Linux jffs2 filesystem data little endian

root@kali:~/Desktop/Firmwares# ./fmk/src/jffs2/unjffs2 main-fs.jffs2 
46080+1 registros leídos
46080+1 registros escritos
23592984 bytes (24 MB) copiados, 0,221971 s, 106 MB/s
JFFS2 image mounted to jffs2-root

root@kali:~/Desktop/Firmwares# cd jffs2-root/
root@kali:~/Desktop/Firmwares/jffs2-root# ls -al
total 118
drwxr-xr-x 16 root root     0 ene  1  1970 .
drwxr-xr-x  5 root root  4096 sep 21 19:37 ..
drwxr-xr-x  2 root root     0 may  3 13:50 bin
drwxr-xr-x  5 root root     0 may  3 14:13 dev
-rw-r--r--  1 root root 71680 may  3 14:12 .dev.tar
lrwxrwxrwx  1 root root    13 may  3 13:22 etc -> mnt/flash/etc
drwxr-xr-x  7 root root     0 may  3 14:13 lib
drwxr-xr-x  2 root root     0 may  3 14:13 lib64
drwxr-xr-x  3 root root     0 may  3 14:13 libs
-rwxr-xr-x  1 root root  2442 may  3 13:49 linuxrc
drwxr-xr-x  8 root root     0 may  3 14:13 mnt
drwxr-xr-x  2 root root     0 may  3 14:13 proc
drwx------  2 root root     0 may  3 14:13 root
drwxr-xr-x  2 root root     0 dic  3  2010 sbin
drwxr-xr-x  2 root root     0 may  3 14:13 share
drwxr-xr-x  2 root root     0 may  3 14:13 sys
lrwxrwxrwx  1 root root     7 may  3 13:22 tmp -> var/tmp
drwxr-xr-x 10 root root     0 may  3 14:14 usr
drwxr-xr-x  2 root root     0 may  3 14:13 var
-rw-r--r--  1 root root 40960 may  3 14:12 .var.tar


Sobre el archivo creado usamos file y nos confirma que es un sistema de archivos jffs2 así que solo nos queda extraer con firmware mod kit el contenido y voilá! ya tenemos el sistema de archivos preparado para nuestro análisis. Como nota podéis ver que existen dos archivos .tar dentro que contienen mas partes del firmware. Para extraerlas solo tenemos que utilizar el típico tar xvf <nombrearchivo> y los archivos ya irán automaticamente a su carpeta.

Finalmente quedaría empezar el análisis de vulnerabilidades, pero eso quedará para otro día. Si despues de esto os veis con las ganas un buen punto para empezar es el interfaz web.

root@kali:~/Desktop/Firmwares/jffs2-root# cd usr/html/
root@kali:~/Desktop/Firmwares/jffs2-root/usr/html# ls -l
total 1834
-rw-r-----  2 root        53  15466 feb 28  2011 8021x.shtml
lrwxrwxrwx  2 root   root        18 may  3 13:49 about.shtml -> ../init.d/net.eth0
lrwxrwxrwx  2 root   root        16 may  3 13:49 action_day_night_mode.shtml -> ../init.d/net.lo
-rw-r-----  2 root        52  23357 may  3 13:58 action_notification.shtml
-rw-r-----  2 root        52  28707 may  3 13:58 action_ptz_control.shtml
-rw-r-----  2 root        52  14214 may  3 13:58 action_record_video.shtml
-rw-r-----  2 root        52  10879 may  3 13:58 action_rule_setup.shtml
lrwxrwxrwx  2 root   root        24 may  3 13:46 action_rules.shtml -> ../init.d/policykit_cert
-rw-r-----  2 root        52  36843 may  3 13:58 action_send_images.shtml
-rw-r-----  2 root        52  34996 may  3 13:58 action_send_videoclip.shtml
drwxr-xr-x  3 root   root         0 may  3 14:14 activex
-rw-r-----  2 root        52  33448 may  3 14:10 add_guardTour.shtml
lrwxrwxrwx  2 root   root        18 may  3 13:49 additional_condition.shtml -> ../init.d/mountall
-rw-r-----  2 root        52  20795 may  3 14:09 add_osdi.shtml
-rw-r-----  2 root        52  25357 may  3 14:10 add_recordTour.shtml
lrwxrwxrwx  2 root   root        15 may  3 13:49 add_tour.shtml -> ../init.d/issue

[...]

-rw-r-----  1 root        51   3475 may  3 13:56 viewer_index.shtml
-rw-r-----  1 root        53   6606 may  3 13:52 viewNetSettings.shtml
-rw-r-----  1 root        51  91521 may  3 13:56 view.shtml
-rw-r-----  1 root        52  10102 may  3 14:05 vmd.shtml




PD: Para los mas atentos, en la cabecera que se extrajo había un sistema de archivos que binwalk nos reconocía como CramFS. Cuando corté esa sección resultó que era un sistema de archivos squashFS que tenia hsqs como magic number. Tras intentar extraerlo de mil maneras no he sido capaz de conseguirlo. Probablemente hayan una herramienta personalizada para ello. El archivo pesaba 77Kb por lo que no debería de contener información importante. De todas formas si algún dia consigo extraerlo ya os contaré como.

drwxr-xr-x  4 root@kali:~/Desktop/Firmwares# hexdump -C file.squashfs | grep hs
00001100  68 73 71 73 e0 da ff 3d  16 01 01 11 7f 2d 54 d3  |hsqs...=.....-T.|

0 comentarios:

Publicar un comentario en la entrada

ShellShock Labs es un blog dedicado a seguridad y hacking en general, un lugar donde buscamos que la gente participe con sus opiniones.

Síguenos




Posts Populares