Pregunta:
Estoy tratando de extraer el firmware de una cámara IP. Estoy buscando un servicio durmiente que podría ser una gran amenaza. Según nmap
no hay servicios en ejecución como telnet, SSH, FTP o similares; solo hay unos pocos puertos abiertos, como HTTP, RSTP y unknown
. El firmware es jvs3516cs-7601.bin de Jovision (mi ipcam es un clon) y proviene de la sucursal alemana de la empresa. He probado todos los pasos habituales para el análisis pero no he tenido mucho éxito. Instalé todas las herramientas habituales de análisis de firmware (lzmao, squash, cpio, cramfs) e intenté extraer el firmware con gzip
, unzip
, 7z
y binwalk
sin suerte.
# binwalk -Bv jvs3516cs-7601.bin
Scan Time: 2018-06-13 17:52:52
Target File: /root/jvs3516cs-7601.bin
MD5 Checksum: 8903156ca04081c393e16d6dff1580a0
Signatures: 344
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
# binwalk -EJ jvs3516cs-7601.bin
DECIMAL HEXADECIMAL ENTROPY
--------------------------------------------------------------------------------
0 0x0 Falling entropy edge (0.316584)
270336 0x42000 Rising entropy edge (0.993798)
1904640 0x1D1000 Falling entropy edge (0.724715)
2031616 0x1F0000 Rising entropy edge (0.993043)
7753728 0x765000 Falling entropy edge (0.362255)
Entropy Exception: 'float' object cannot be interpreted as an integer
# xxd -a jvs3516cs-7601.bin | head
00000000: 5c1b 44f5 50ef dbfa 50ef dbfa 50ef dbfa \.D.P...P...P...
00000010: 50ef dbfa 50ef dbfa 50ef dbfa 50ef dbfa P...P...P...P...
00000020: 040c c49f e40c c49f 440b c49f 240b c49f ........D...$...
00000030: 840b c49f 640a c49f c40a c49f 3c49 700d ....d.......<Ip.
00000040: 441f 473f 441f 440e 441f 441f b91f 441f D.G?D.D.D.D...D.
00000050: 401f 473f 2a2f 2c1f 441f 441f b91f 441f @.G?*/,.D.D...D.
00000060: 4c1f 473f 441f 440d 441f 441f b91f 441f L.G?D.D.D.D...D.
00000070: 481f 473f 273f 381f 441f 441f b91f 441f H.G?'?8.D.D...D.
00000080: 541f 473f 441f 440e 441f 441f b91f 441f T.G?D.D.D.D...D.
00000090: 501f 473f 2a2f 2c1f 441f 441f b91f 441f P.G?*/,.D.D...D
# fdisk -l jvs3516cs-7601.bin
Disk jvs3516cs-7601.bin: 7,4 MiB, 7798784 bytes, 15232 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
¿Hay alguien con mejores ideas que las mías? Gracias por adelantado.
PD También hay un jvs3516cs-7601-ver.bin con el interior:
#####################3
#file format:
#module=name, the name want to update. such as boot,kernel,fs,config ...
#ver=3, version of the module
#offset=0, offset in the file
#size=0x100000, size in byte
#dev=/dev/mtdblock/0, dev used to update
#
module=uboot
ver=20
offset=0
size=0x40000
dev=/dev/mtdblock0
module=kernel
ver=3
offset=0x40000
size=0x1B0000
dev=/dev/mtdblock1
module=fs
ver=5608
offset=0x1F0000
size=0x580000
dev=/dev/mtdblock2
product=JVS-HI3516CS-7601
fileSize=0x770000
checksum=0x4b0163fa
Respuesta:
Ahora no tengo el tiempo para ayudarte en todo el camino , pero creo que puedo ayudarte a empezar. Pensemos como una empresa que trata de ofuscar algo al profano, ¿verdad? La primera opción suele ser xor
bit a bit.
Ya conocemos las compensaciones de los bits y piezas, gracias a jvs3516cs-7601-ver.bin
.
Ahora, mirar jvs3516cs-7601.bin
en un editor hexadecimal jvs3516cs-7601.bin
un patrón fascinante: 44 1F
(o D.
). Por lo general, esperaríamos ver bastantes 00
ocurrencias en datos con esta entropía (inicio del archivo), pero en cambio vemos ese patrón D.
No me preguntes si hay alguna conexión con el nombre de un desarrollador o algo así, pero ahora tenemos una teoría funcional. Es posible que el archivo .bin
se haya borrado por palabra con 0x1F44
(o 0x441F
si es Big Endian). Extracto:
5C 1B 44 F5 50 EF DB FA 50 EF DB FA 50 EF DB FA
50 EF DB FA 50 EF DB FA 50 EF DB FA 50 EF DB FA
04 0C C4 9F E4 0C C4 9F 44 0B C4 9F 24 0B C4 9F
84 0B C4 9F 64 0A C4 9F C4 0A C4 9F 3C 49 70 0D
44 1F 47 3F 44 1F 44 0E 44 1F 44 1F B9 1F 44 1F
40 1F 47 3F 2A 2F 2C 1F 44 1F 44 1F B9 1F 44 1F
4C 1F 47 3F 44 1F 44 0D 44 1F 44 1F B9 1F 44 1F
48 1F 47 3F 27 3F 38 1F 44 1F 44 1F B9 1F 44 1F
54 1F 47 3F 44 1F 44 0E 44 1F 44 1F B9 1F 44 1F
50 1F 47 3F 2A 2F 2C 1F 44 1F 44 1F B9 1F 44 1F
64 1F 47 3F 44 1F 44 04 44 1F 44 1F B9 1F 44 1F
60 1F 47 3F A5 5F 38 1F 44 1F 44 1F B9 1F 44 1F
6C 1F 47 3F 54 1F 44 1F 44 1F 44 1F B9 1F 44 1F
AC 1F 47 3F 4B 1F 44 1F 44 1F 44 1F 44 1F 59 1F
6C 1F 47 3F 44 1F 44 1F 44 1F 44 1F 61 37 44 1F
6C 1F 47 3F 44 1F 44 1F 44 1F 44 1F 41 4F 44 1F
6C 1F 47 3F 45 1F 44 1F 44 1F 44 1F 41 4F 44 1F
40 1F 44 0F EE 15 44 1F 44 1F 44 1F 19 1F 44 1F
El siguiente pequeño script de Python toma el conocimiento de jvs3516cs-7601-ver.bin
y lo coloca en la variable parts
(una lista de tripletes/tuplas). Luego abre el archivo de entrada (no hay errores sofisticados o manejo de ruta aquí, así que ejecútelo desde la misma carpeta en la que se encuentra jvs3516cs-7601.bin
) y lee las partes una por una y luego las vuelca en un archivo de salida según el contenido de la tupla. :
# Tested with Python 2.7!
import io
import struct
parts = [("uboot.img", 0, 0x40000), ("kernel.img", 0x40000, 0x1B0000), ("fs.img", 0x1F0000, 0x580000)]
inpname = "jvs3516cs-7601.bin"
with io.open(inpname, "rb") as infile:
for nm, offset, size in parts:
infile.seek(offset)
x = infile.read(size)
assert len(x) / 2, "%s has odd length." % (nm)
newx = ""
for woffs in range(0, len(x), 2):
word = struct.unpack("H", x[woffs:woffs+2])
val = word[0] ^ 0x1F44 # the magic xor value we assume based on "D."
newx += struct.pack("H", val)
assert len(newx) == len(x), "Input and output size differ."
assert len(newx) == size, "Output size (%d) for %s differs from expected value %d." % (len(newx), nm, size)
with io.open(nm, "wb") as outf:
outf.write(newx)
El resultado son tres archivos que, después de una mirada superficial, parecen auténticos. Es decir, la uImage desofuscada, la imagen del kernel y la imagen del sistema de archivos.
Una vez que tenemos esos archivos, usar el file
en el shell da algo como esto:
$ file *.img
fs.img: Squashfs filesystem, little endian, version 4.0, 5722880 bytes, 614 inodes, blocksize: 262144 bytes, created: Fri Oct 20 10:32:21 2017
kernel.img: u-boot legacy uImage, Linux-3.0.8, Linux/ARM, OS Kernel Image (Not compressed), 1644712 bytes, Thu Nov 5 07:18:50 2015, Load Address: 0x80008000, Entry Point: 0x80008000, Header CRC: 0xAAC0A340, Data CRC: 0x1FDABC77
uboot.img: data
No estoy seguro de por qué no reconoce la imagen de U-Boot. Pero también podría ser un cargador patentado que reemplace lo que antes era una imagen de U-Boot.
Si crea una carpeta rootfs
y tiene instalado el paquete (Debian) squashfuse
, puede ejecutar sudo mount -t squashfs fs.img rootfs
para montar la imagen SquashFS. El resultado se verá así:
$ ls -l rootfs/
total 2
drwxrwxrwx 2 root root 1386 2017-09-30 08:11 bin
drwxrwxrwx 2 1001 1001 3 2006-04-19 06:05 boot
drwxrwxrwx 2 1001 1001 3 2017-06-30 05:57 dev
drwxrwxrwx 7 root root 259 2017-10-20 12:32 etc
drwxrwxrwx 5 root root 149 2017-09-30 08:11 home
lrwxrwxrwx 1 1001 1001 9 2013-09-23 12:46 init -> sbin/init
drwxrwxrwx 2 1001 1001 650 2014-05-04 08:36 lib
lrwxrwxrwx 1 1001 1001 11 2013-09-23 12:46 linuxrc -> bin/busybox
drwxrwxrwx 2 1001 1001 3 2006-04-19 06:04 lost+found
-rwxrwxrwx 1 1001 1001 1341 2011-04-21 05:40 mkimg.rootfs
-rwxrwxrwx 1 1001 1001 431 2011-04-21 05:40 mknod_console
drwxrwxrwx 2 1001 1001 3 2006-04-19 06:05 mnt
drwxrwxrwx 2 1001 1001 3 2008-05-21 11:17 nfsroot
drwxrwxrwx 2 1001 1001 3 2006-04-19 06:04 opt
drwxrwxrwx 2 1001 1001 3 2006-04-19 06:04 proc
drwxrwxrwx 7 root root 143 2017-09-30 08:11 progs
drwxrwxrwx 2 1001 1001 31 2013-08-22 03:35 root
drwxrwxrwx 2 1001 1001 878 2017-10-20 12:32 sbin
drwxrwxrwx 2 1001 1001 3 2006-04-19 06:05 share
drwxrwxrwx 2 1001 1001 3 2006-04-19 06:04 sys
drwxrwxrwx 2 1001 1001 3 2006-04-19 10:46 tmp
drwxrwxrwx 6 1001 1001 62 2013-08-22 03:35 usr
drwxrwxrwx 3 1001 1001 26 2013-08-22 03:35 var
lrwxrwxrwx 1 root root 10 2017-10-20 12:32 wifi -> /home/wifi
Entonces parece que el SquashFS es legible y sólido. Al menos esa parte ha sido verificada.
Ahora, como mencioné al principio, no tengo tiempo para verificar mis hallazgos hasta el momento, pero mis hallazgos le darán una pista de la mentalidad de los desarrolladores de la empresa y qué más pueden tener en la tienda. Parece el verdadero negocio, pero es posible que haya pasado por alto algunos detalles. De cualquier manera, esto debería ayudarlo a comenzar.