freeBuf
通过SD卡给某摄像头植入可控程序
2023-11-01 15:24:13

本文作者:qret2libc

0x01. 摄像头卡刷初体验

最近研究了手上一台摄像头的sd卡刷机功能,该摄像头只支持fat32格式的sd卡,所以需要先把sd卡格式化为fat32,另外微软把fat32限制了最大容量 32 G,所以也只能用不大于32G的sd卡来刷机。这里使用32G的sd卡来刷。

image

win10格式化sd卡命令,X是sd卡所在磁盘名。

format /FS:FAT32 X:

准备就绪,将固件直FIRMWARE.bin放SD卡根目录下, 长按reset键刷机。但是后面发现并未成功,刷完后成砖了,摄像头未能正常启动,此时刷入的还是正常固件,还未做任何篡改,却直接刷成砖,确实有点出师不利,一时间不知哪个环节出了问题。

0x02. 救“砖”行动

摄像头刷机后没能正常启动,考虑接上串口,看看哪里出了问题。

image

接上串口后,再次上电启动设备,观察到部分串口日志如下:

T 
IPL xxx
D-15
HW Reset
SPI 54M
IPL_CUST xxxx
MXP found at 0x0000f000
offset:00010000
XZ decomp_size=0x0004a19c
U-Boot 2015.01
WARNING: Caches not enabled
MMC:   MStar SD/MMC: 0
SF: Detected nor0 with total size 8 MiB
gpio debug MHal_GPIO_Pad_Set:603
gpio debug MHal_GPIO_Pad_Set:603
In:    serial
Out:   serial
Err:   serial
Net:   MAC Address E0:EF:02:88:AD:26
Auto-Negotiation...
Link Status Speed:100 Full-duplex:1
sstar_emac
gpio debug MHal_GPIO_Pad_Set:603
ddrsize 64
mtd_num 5, flash_size 0x00800000(8M)
To run up...
Using sstar_emac device
TFTP from server 192.168.1.99; our IP address is 192.168.1.10
Filename 'update.bin'.
Load address: 0x21000000
Loading: T T T T T T T T T T 
Retry count exceeded; starting again
Using sstar_emac device
TFTP from server 192.168.1.99; our IP address is 192.168.1.10
Filename 'update.bin'.
Load address: 0x21000000
Loading: T T T T T T T T T T

从日志信息可以看出,摄像头IP地址为192.168.1.10,tftp服务器地址为192.168.1.99,设备尝试从tftp服务器加载名为update.bin的固件失败。说明之前卡刷没有成功的情况下,现在设备上电后会主动尝试利用uboot中的tftp功能从192.168.1.99地址加载固件,但此时并不存在192.168.1.99服务器,所以摄像头上电后一直卡在这里,无法正常启动。

尝试利用tftp刷机拯救摄像头,由于设备启动时并不能成功打断uboot进入shell,所以我们无法直接通过uboot shell去修改默认的tftp服务器ip和其他操作,只能在PC上搭建一个tftp服务器并修改ip为192.168.1.99,将待刷固件命名为update.bin并放到tftp服务器文件目录。

tftp服务器准备就绪,再次上电启动设备,观察到设备成功从192.168.1.99服务器下载到固件,并写入flash,救“砖”成功。后面再次按照sd卡刷流程尝试刷入正常固件,终于没有再出现成“砖”的状况。

T 
IPL xxx
D-15
HW Reset
SPI 54M
IPL_CUST xxxx
U-Boot 2015.01
WARNING: Caches not enabled
MMC:   MStar SD/MMC: 0
SF: Detected nor0 with total size 8 MiB
gpio debug MHal_GPIO_Pad_Set:603
In:    serial
Out:   serial
Err:   serial
Auto-Negotiation...
sstar_emac
SF: Detected nor0 with total size 8 MiB
Erasing SPI flash..._spi_flash_erase: addr 0x30000, len 0x10000 100%(cost 248 ms)
Writing to SPI flash..._spi_flash_write to 0x30000, len 0x10000 from 0x23b01870 100%(cost 169 ms)
done
ddrsize 64
mtd_num 5, flash_size 0x00800000(8M)
To run up...
Using sstar_emac device
TFTP from server 192.168.1.99; our IP address is 192.168.1.10
Filename 'update.bin'.
Load address: 0x21000000
Loading: T #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ##############################
         237.3 KiB/s
done
Bytes transferred = 7114336 (6c8e60 hex)
head_crc32 9ba634e1 crc32 9ba634e1
MXIC REMS: 0xC2,0x16
SF: Detected nor0 with total size 8 MiB
...
...
SF: 1507328 bytes @ 0x40000 Written: OK
head_crc32 4d5121d7 crc32 4d5121d7
...
...
Erasing SPI flash..._spi_flash_erase: addr 0x30000, len 0x10000 100%(cost 255 ms)
Writing to SPI flash..._spi_flash_write to 0x30000, len 0x10000 from 0x23b018d0 100%(cost 175 ms)
done
resetting ...
##  Booting kernel from Legacy Image at 21000000 ...
   Image Name:   MVX4##I6B0xxxxxxxx
   Image Type:   ARM Linux Kernel Image (lzma compressed)
   Data Size:    1494344 Bytes = 1.4 MiB
   Load Address: 20008000
   Entry Point:  20008000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... 
[XZ] !!!reserved 0x21000000 length=0x 1000000 for xz!!
   XZ: uncompressed size=0x2e2000, ret=7
OK

Starting kernel ...

ox03. 分析卡刷固件校验

正常的sd卡刷流程大致如下,首先断电,将存储固件的sd卡插入摄像头,按住reset键,接通电源,此时摄像头就会加载sd卡固件进行刷机.在刷写固件的过程中,按住reset键的作用是强制摄像头进入IPL模式(Initial Program Loader),也称为恢复模式。这个模式允许设备加载存储在SD卡中的新固件并更新原有的固件。在IPL模式下,设备将不会自动运行已有的固件,而是等待从SD卡加载新的固件进行刷写。因此,按住reset键是为了保证设备能够正确地进入IPL模式,从而完成固件的更新。在这个日志中,可以看到 IPL(Initial Program Loader)已经成功地加载,并且检查通过。

IPL_CUST 固件的作用是启动 U-Boot,然后由 U-Boot 来加载并运行设备的操作系统。在这个过程中,U-Boot 会从 SD 卡上读取固件,然后将它加载到摄像头的内存中,并启动 Linux 内核。因此,加载 sd卡固件的程序在U-Boot中,从上面日志可以看到uboot启动固件时首先对固件做了crc校验,所以篡改固件后需要还需要考虑过crc校验才可能刷写成功。从uboot固件中也确实搜到上面日志中的crc校验相关字符串。

image

分析uboot中crc校验逻辑,逆向出修改固件后需要计算的相关字段。

image

image

0x04.定制文件系统

知道固件组成结构后,接下来就可以向固件文件系统中植入我们自己的程序,固件修改后,计算并调整固件中相应size和crc字段值,通过sd卡重新刷入设备。

使用buildroot编译一个包含telnet、ftp等功能的busybox,将新编译的busybox移植到摄像头原来的文件系统中。下载Buildroot ,选择编译配置。

make menuconfig

image

image

接着编译BusyBox,将telnetd编译进去。

make busybox-menuconfig

image以上设置完成后执行make进行编译,编译完成后在当前目录生成output文件夹,生成的telnetd是链接到busybox的,所以这里直接将生成的busybox移植到摄像头文件系统即可。将编译的busybox复制到固件文件系统/bin目录并命名为busybox_hack。

这里解包固件时记得要用root权限,因为摄像头是root用户,busybox_hack拷贝到摄像头文件系统中时也要注意修改文件的所属用户和组和其他文件一致。将busybox_hack添加到启动项中/etc_default/init.d/,并启动telnetd,-l 参数将其链接到/bin/sh,这样直接免密登录。

image

重新打包文件系统。

sudo mksquashfs ./squashfs-root/ out.fs -comp xz -b 64K -noappend

其中./squashfs-root是待打包的目录,out.fs是想要重新打包的文件名。-comp xz告诉 mksquashfs 使用 xz 压缩算法,-b 64K告诉 mksquashfs 使用 64K 的块大小。-noappend告诉 mksquashfs 不要将新文件附加到现有文件中。将out.fs覆写在原固件文件系统处并调整固件中相应size和crc字段值。

dd if=out.fs of=target.bin conv=notrunc bs=1 seek=1494600
if=out.fs 表示输入文件为 out.fs。
of=target.bin 表示输出文件为 target.bin。
conv=notrunc 表示不截断输出文件,即保留输出文件中的原有内容。
bs=1 表示每次读写一个字节。
seek=1494600 表示在输出文件中的偏移 1494600 处开始写入,这就相当于将输入文件拼接到输出文件的偏移 1494600 处

最后通过sd卡刷入固件,文件系统成功启动,telnetd也成功启动,通过telnet直接连接到摄像头shell。

image

本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏