¿De que va este hilo?
A petición de otro user abro este hilo para hacer un seguimiento y ayudarnos en el proceso de destripar el firmware de esta camara.
¿Por que esta cámara y no la GoPro?
Porque es una cámara que ha ganado mucha popularidad y es competidora directa de la GoPro. Ademas la GoPro ya ha sido reverseada hasta la saciedad y no supone un reto.
http://goprouser.freeforums.org/hero3-black-firmware-studies-physical-teardown-photos-t10016.html
http://chdk.setepontos.com/index.php?topic=5890.0
https://www.druid.es/content/gopro-firmware-forensic
Vamos al turron
La imagen sobre la que basaremos el estudio la podeis descargar desde aqui:
http://www.sjcam.com/firmware/SJCAM_SJ4000_WIFI_0918.zip
He elegido la versión wifi porque tiene mas papeletas para encontrar cosas interesantes al añadir comunicación externa.
Herramientas que usaremos
-
Binwalk
-
Hexdump
-
Hexeditor
-
Comandos strings, dd, etc...
-
Debugger radare2, IDA...
-
Librerías de compresión
Nota: Estas son las que yo uso
Datos de la cámara extraidos del firmware:
-
SoC Ambarella A7 (Mismo que GoPro) : http://www.ambarella.com/products/sports-cameras
-
El RTOS que usa la camara es Windows CE y monta cygwin para emular diferentes partes del OS (Confirmado)
-
Las imágenes de actualización son partes del firmware completo (Por confirmar)
Primeros pasos sobre el firmware
Lo primero que he hecho ha sido intentar identificar ante que nos encontramos por lo que he usado el comando file, strings, hecho un volcado hexadecimal del binario y revisado la entropía del archivo.
Estos son los resultados:
root@uservm:~/SJ4000# file FW
FW: data
root@uservm:~/SJ4000# strings -n 9 FW | head -20
NT96655 1000000020100701
0LD:GS650
$pDRAMINFO
@W20140918V02
'^G Section-%.2ld: Range[0x%08X~
^R*** Math error: type=%d name="%s" arg1=%f
HCPU Exception in ISR! caus
%, by [%s:
^RAssert:`%s' is failed! (%s:%u)
%s(): ^N(_main begin)
(reg exp handler
kernel init
Install code s
for mempool
POOL_ID_STORAGE_NAND
FWS_BUFFER
DISP_OSD2
,GFX_IMAGE
DATEIMPRINT
^RFATAL:%s() calling flow (%08x)!
root@uservm:~/Desktop/SJ4000# hexdump -C FW | head -10
00000000 42 43 4c 31 4a dd 00 09 00 53 b3 d0 00 2e 91 ec |BCL1J....S......|
00000010 9d 00 04 00 80 00 00 00 00 9d 04 04 9d 08 08 9d |................|
00000020 10 10 9d 20 20 9d 0c 0c 4e 54 39 36 36 35 35 20 |... ...NT96655 |
00000030 31 30 30 30 30 30 30 30 32 30 31 30 30 37 30 31 |1000000020100701|
00000040 d0 b3 53 00 55 aa 7b 2f 9d 10 30 4c 44 3a 47 53 |..S.U.{/..0LD:GS|
00000050 36 35 30 20 20 20 20 9d 04 04 9d 04 14 ff ff ff |650 .........|
00000060 ff 9d 04 04 9d 24 70 44 52 41 4d 49 4e 46 4f 9d |.....$pDRAMINFO.|
00000070 08 40 9d 2c 3c 9d 04 04 53 54 52 47 9d 0c 40 9d |.@.,<...STRG..@.|
00000080 0e 1e 70 00 00 00 50 00 00 9d 05 82 23 f0 00 00 |..p...P.....#...|
00000090 00 10 9d 11 40 57 32 30 31 34 30 39 31 38 56 30 |....@W20140918V0|
De esto se pueden extraer varias cosas interesantes. Al sacarnos texto inteligible sabemos que el archivo no está cifrado pero su baja entropía puede ser un indicativo de que si que está comprimido. Si analizamos las cabeceras del hexadecimal nos encontramos con lo siguiente:
00000000 42 43 4c 31 4a dd 00 09 00 53 b3 d0 00 2e 91 ec |BCL1J....S......|
Con una rápida busqueda en Google nos encontramos con que BCL1 hace referencia a Basic Compression Library ademas de que los demas bytes hacen referencia al algoritmo de compresión LZ77.
Una vez descargada y compilada la BCL comprimimos un archivo de ejemplo para analizar la cabecera:
00000000 42 43 4c 31 81 66 00 09 00 54 68 e0 00 2f 2b bf |BCL1.f...Th../+.| < FIRMWARE
00000000 42 43 4c 31 00 00 00 09 00 00 4f 88 99 7f 45 4c |BCL1......O...EL| < LZ77 Ejemplo
Como se puede ver la estructura de bytes es la misma (HEADER [4Bytes] - 09 [Indica algoritmo]) los últimos 8 bytes indican el tamaño del archivo comprimido y sin comprimir (En Big Endian)
La unica diferencia entre nuestro firmware y el ejemplo son el quinto y sexto byte (81 66) pero despues de darle vueltas llegué a la conclusión de que son bytes basura generados a la hora de comprimir así que con un editor hexadecimal los puse a cero para que el descompresor no se vuelva loco. Dejandolo de la siguiente forma:
00000000 42 43 4c 31 81 66 00 09 00 54 68 e0 00 2f 2b bf |BCL1.f...Th../+.| < FIRMWARE
00000000 42 43 4c 31 00 00 00 09 00 54 68 e0 00 2f 2b bf |BCL1.f...Th../+.| < FIRMWARE Modificado
Al probar a descomprimirlo así el descompresor me tiraba un Segmentation Fault:
LZ77 decompress FW to test...
Input file: 3091395 bytes
Output file: 5531872 bytes
Segmentation fault
Lo primero que se me vino a la mente fue " Si la cabecera me dice el tamaño comprimido y descomprimido voy a castear esos bytes para ver cuantos bytes mide el archivo" así pude compararlo con los datos que me da al intentar descomprimir:
root@uservm:~/SJ4000# binwalk -C -o 0x0000008 -l 12 FW
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
8 0x8 Hex: 0x005468E0
Little Endian Quad: -4671588507655318528
Big Endian Quad: 23759209328749503
Little Endian Long: -530033664
Big Endian Long: 5531872
Little Endian Short: 21504
Big Endian Short: 84
Little Endian Date: Mon Mar 16 03:25:36 1953
Big Endian Date: Thu Mar 5 19:37:52 1970
12 0xC Hex: 0x002F2BBF
Little Endian Quad: 1126568834051840
Big Endian Quad: 13277425844618240
Little Endian Long: -1087688960
Big Endian Long: 3091391
Little Endian Short: 12032
Big Endian Short: 47
Little Endian Date: Sun Jul 14 20:10:40 1935
Big Endian Date: Thu Feb 5 13:43:11 1970
Y bingo, como vemos Output file es igual a Big Endian Long del primer caso, pero en input file tenemos una diferencia de 4 bytes:
3091395 - 3091391 = 4bytes
Esta diferencia es la que nos estaba causando el Segmentation fault así que para parchearlo rápidamente y poder seguir abrimos el código de BCL (bcl.c) y editamos lo siguiente (Alrededor de la línea 92):
Compilamos de nuevo la librería y ya podemos descomprimir el firmware sin problema.
A partir de aqui me he estancado un poco aunque no veo que sea un camino sin salida. Con la nueva imagen descomprimida vuelvo a empezar por el principio (Tiramos file, strings, hexdump, binwalk y reanalizamos la entropia).
-
file no devuelve ningun resultado así que supongo que el firmware consta de varias partes
-
strings nos devuelve mas cosas que antes (Y podemos sacar cadenas interesantes)
-
Binwalk nos devuelve un puñado de falsos positivos
-
El analisis de entropia enseña un gran bloque al final del archivo que aun no he logrado identificar
Echando un ojo al nuevo volcado hexadecimal veo algunas cosas interesantes pero que no logro identificar, como por ejemplo:
00000000 00 04 00 80 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000050 4e 54 39 36 36 35 35 20 31 30 30 30 30 30 30 30 |NT96655 10000000|
00000060 32 30 31 30 30 37 30 31 d0 b3 53 00 55 aa 7b 2f |20100701..S.U.{/|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000080 4c 44 3a 47 53 36 35 30 20 20 20 20 20 20 20 20 |LD:GS650 |
00000090 00 00 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 |................|
000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000000c0 44 52 41 4d 49 4e 46 4f 20 20 20 20 20 20 20 20 |DRAMINFO |
000000d0 ff ff ff ff ff ff ff ff 00 00 00 00 00 00 00 00 |................|
000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000100 53 54 52 47 49 4e 46 4f 20 20 20 20 20 20 20 20 |STRGINFO |
00000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 70 00 |..............p.|
00000120 00 00 50 00 00 00 80 00 00 00 f0 00 00 00 10 00 |..P.............|
00000130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000140 57 32 30 31 34 30 39 31 38 56 30 32 00 00 00 00 |W20140918V02....|
00000150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000180 00 68 1a 40 7f 00 5a 33 10 80 1b 3c 74 b1 7b 27 |[email protected]...<t.{'|
00000190 20 d8 7a 03 00 00 7b 8f 08 00 60 03 00 00 00 00 | .z...{...`.....|
000001a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
*
00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00000240 75 ed 03 08 00 00 00 00 00 00 00 00 00 00 00 00 |u...............|
00000250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
NT96655 es el modelo de la cámara, 20100701 supongo que la primera versión, W20140918V02 es la versión actual del firmware. Lo interesante es la disposición de los datos con la misma estructura de bytes. Y la cabecera 00 04 00 80 que llama la atención entre tanto cero (Si a alguien le suena de algo que avise :3).
¿Que necesito saber para ayudar?
Si después de lo que has leído aun no te has perdido eres bienvenido a echar una mano.
Notas finales
Abro el hilo para ver si entre todos podemos ir sacando algo en claro y poder darles a los usuarios de esta cámara (yo no lo soy) algún hack interesante. Esto no va a ser un tutorial de reversing así que para cualquier duda (Duda y no curso completo) podéis mandarme un MP.
Seguiré actualizando con los nuevos hallazgos segun vaya sacando algo interesante.