TP-LINK的一个400万像素的小摇头机,TL-IPC44AN,支持ONVIF协议,之前内网接入群晖Surveillance Station看看宝宝睡觉,现在已经几乎不用了。拆开了看看,想获取root shell,折腾了一晚也没搞定,把已经知道的信息记录下来,以后有灵感了再继续

TP的东西同一个型号会有不同的硬件版本,用到的方案会完全不同,就如TL-IPC44AN这个型号,我看到的已经有V1.0到V4.0四个版本,我这个还是最早的V1.0,CPU为国产星宸SSC327,集成了64M内存,另外有8M SPI闪存,RTL8188FTV无线网卡,CMOS型号看不出来

中断uboot

TTL很好接,主板边缘还贴心地给标记处了RX和TX,但uboot却很难进,进去也很难用。TP使用了双层uboot,第一层uboot可以通过键入slp中断启动进入,分区名叫factory_boot。第一层uboot会对第二层分区和剩下的kernel与rootfs分区做校验,都通过后才会进入第二层uboot,然后由第二层uboot启动内核。所以在第一层设置bootargsinit=/bin/sh是徒劳的

从启动日志中得到分区结构如下:

Creating 9 MTD partitions on "NOR_FLASH":
0x000000000000-0x00000002d800 : "factory_boot" size: 0x0002d800 (182KiB) }
0x00000002d800-0x000000030000 : "factory_info" size: 0x00002800 (10KiB) }
0x000000030000-0x000000040000 : "art" size: 0x00010000
0x000000040000-0x000000060000 : "config" size: 0x00020000
0x000000060000-0x000000080000 : "normal_boot" size: 0x00020000
0x000000080000-0x000000214000 : "kernel" size: 0x00194000
0x000000214000-0x0000007b0000 : "rootfs" size: 0x0059c000
0x0000007b0000-0x000000800000 : "rootfs_data" size: 0x000b0000
0x000000080000-0x000000800000 : "firmware" size: 0x00780000

第二层uboot无法中断,怀疑没有设置delay值,只能在第一层uboot下做有限的操作。

SigmaStar # print
baudrate=115200
bootdelay=1
bootfile=uImage
ethact=sstar_emac
ethaddr=00:00:23:34:45:68
ipaddr=192.168.1.60
loadaddr=0x21000000
netmask=255.255.255.0
serverip=192.168.1.100
stderr=serial
stdin=serial
stdout=serial

Environment size: 239/131068 bytes

uboot非常非常精简,精简到无以复加,help saveenv bootm这些基础命令都没有,根本没法玩,所有字母尝试了遍,能用的命令有

  1. tftp用法与常规的tftp无异
  2. setenv 设置环境参数,但是却没有saveenv,无法保存
  3. go
  4. sf读写SPI闪存
  5. bootp
  6. mac看名字就能猜到应该可以用来设置mac值
  7. initDbgLevel重置参数dbgLevel这个uboot参数
  8. dbg设置dbgLevel这个uboot参数的值,可用的值有’DISABLE’, ‘ERROR’, ‘INFO’, ‘TRACE’, ‘DEBUG’,‘BOOTTIME’,运行后会提示Unknown command ‘saveenv’ - try ‘help’
  9. http最后是可能唯一有点用的一个命令,只在TP上见到。运行后会开启一个http网页服务器,浏览器访问可以直接提交固件,用于救砖。所以如果TP的摄像头变砖了的话,可以试试接网线,然后访问192.168.1.60这个默认IP救砖

尝试进入shell

启动完成后会提示按回车键进入,但是却需要输入用户名密码。官方下载了这个型号的固件尝试分析

binwalk ../TL-IPC44AN-4\ V1.0\ 1.0.11\ Build\ 210820\ Rel.64750n.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
2112          0x840           xz compressed data
133632        0x20A00         uImage header, header size: 64 bytes, header CRC: 0xD462A2A7, created: 2021-08-20 09:59:08, image size: 1652704 bytes, Data Address: 0x20008000, Entry Point: 0x20008000, data CRC: 0xAE102F81, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "Linux-4.9.84"
135896        0x212D8         device tree image (dtb)
144332        0x233CC         device tree image (dtb)
147628        0x240AC         device tree image (dtb)
148579        0x24463         xz compressed data
148913        0x245B1         xz compressed data
1787904       0x1B4800        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 5831640 bytes, 1181 inodes, blocksize: 262144 bytes, created: 2021-08-20 09:59:13
7998720       0x7A0D00        gzip compressed data, from Unix, last modified: 2021-08-20 09:59:15
8022368       0x7A6960        gzip compressed data, from Unix, last modified: 2021-08-20 09:59:15
8045088       0x7AC220        gzip compressed data, from Unix, last modified: 2021-08-20 09:59:15

提取出其中的squashfs格式的rootfs分区,

cat etc/passwd
root:$1$HZiuXCuR$E7/TVi1wkhiE68N79kbkU0:0:0:root:/root:/bin/ash
nobody:*:65534:65534:nobody:/var:/bin/false
admin:*:500:500:admin:/var:/bin/false
guest:*:500:500:guest:/var:/bin/false
ftp:*:55:55:ftp:/home/ftp:/bin/false

$1$HZiuXCuR$E7/TVi1wkhiE68N79kbkU0搜不到现成的密码,暴力破解也不会,放弃这条路。

修改rootfs分区

将etc/passwd中的root密码删除后,使用mksquashfs重新打包。放入原固件内是肯定不行了,一看就有RSA签名,实际试了下也果然如此。再尝试使用tftp写入rootfs分区,reset后第一层的uboot提示无法通过romfs分区校验

固件写入地址分析

uboot下设置好ipaddr后运行http启动救砖服务器,浏览器访问,提交原始有签名校验的固件,将其固件写入过程的日志记录下来

Data will be downloaded at 0x21000000 in RAM
Upload file size: 8067172 bytes
Loading: #################################################################
         #################################

firmware RSA signiture check OK
firmware support my HwID
verifying uboot partition...
ok
verifying kernel and romfs partition...
ok
isp: device name supported
firmware check finished, ok to upgrade
HTTP upload is done! Upgrading...
Flash is detected (0x0C07, 0x20, 0x70, 0x17)
SF: Detected nor0 with total size 8 MiB
SF: 65536 bytes @ 0x30000 Read: OK
Flash is detected (0x0C07, 0x20, 0x70, 0x17)
SF: Detected nor0 with total size 8 MiB
_spi_flash_erase: addr 0x30000, len 0x10000 100%(cost 155 ms)
SF: 65536 bytes @ 0x30000 Erased: OK
_spi_flash_write to 0x30000, len 0x10000 from 0x23b41ac8 100%(cost 71 ms)
SF: 65536 bytes @ 0x30000 Written: OK
upgrade isp done
execute upgrade...
Flash is detected (0x0C07, 0x20, 0x70, 0x17)
SF: Detected nor0 with total size 8 MiB
_spi_flash_erase: addr 0x60000, len 0x7a0000 100%(cost 19027 ms)
SF: 7995392 bytes @ 0x60000 Erased: OK
_spi_flash_write to 0x60000, len 0x7a0000 from 0x21000800 100%(cost 13205 ms)
SF: 7995392 bytes @ 0x60000 Written: OK
HTTP ugrade is done! Rebooting...

可以看到升级程序会先将升级固件放入到内存0x21000000,然后将内存中offset 0x23b41ac8 size 0x10000这段数据写入到了mtd2(art)分区中,而这段数据并不来自固件,不知道写入的什么数据,只看到后面跟了句upgrade isp done

然后是写入固件,TP并没有按分区单独写入,而是将normal_bootkernelrootfsrootfs_data四个分区0x600000x800000合并在一起写入,写入的数据为固件0x800开始,size 0x7a0000

修改第二层uboot

从官方的固件提取出第二层uboot normal_boot,从0x40开始为xz压缩后的uboot镜像,提取出来后解压,放入HxD观察,没找到到bootargs,看来放到了mtd1 factory_info中,可惜无法查看。只有这些

bootcmd=sf probe 0;sf read 0x20008000 0x80000 0x300000;bootm 0x20008200
bootdelay=0
baudrate=115200

注意到了bootdelay=0,这应该就是无法中断第二层uboot的原因了。将其设置为5后保存,再xz压缩,放回normal_boot分区,修改头部的校验区,只找到了这些

uboot header

蓝色框0x0-0x3为magic number,绿色框0x0E-0x0F为红色箭头0x40处开始用于计算CRC32校验值的uboot xz压缩包的长度,根据实际长度改写。红色框就是红色箭头0x40处开始到uboot的xz压缩包结束的CRC32校验值。0x04-0xB不知道是做什么的,0x1C到0x1F貌似是固定的,不用更改。

只修改了校验长度和校验值后使用tftp写回闪存,没有通过uboot分区校验

validate local firmware...
TP Header at 21080000
verifying uboot partition...
failed
Uip boot...

Firmware check failed! ret -15
Enter recovery mode.

启动日志

附上正常启动的日志:

展开日志
00000021
00000021

IPL gf1d3932
D-01
64MB
BIST0_0001-OK
[SDMMC] NO SD!
Load IPL_CUST from NOR
offset:00004160
crc OK

IPL_CUST gf1d3932
MXP found at 0x0000f000
[SDMMC] NO SD!
Version: I6g9d4d0e62a554
DRAM:  64 MiB
WARNING: Caches not enabled
Using default environment

In:    serial
Out:   serial
Err:   serial
*******************************************
board_late_init for upgrade image
*******************************************
*******************************************
factory_boot gpio/pwm init
Flash is detected (0x0C07, 0x20, 0x70, 0x17)
SF: Detected nor0 with total size 8 MiB
SF: 256 bytes @ 0x30000 Read: OK
gpio/pwm count: 5
gpio init: gpio output 52 1
gpio debug MHal_GPIO_Pad_Set:606
gpio[52] is 1
gpio init: gpio output 16 1
gpio debug MHal_GPIO_Pad_Set:606
gpio[16] is 1
gpio init: gpio output 77 1
gpio debug MHal_GPIO_Pad_Set:606
gpio[77] is 1
gpio init: gpio output 76 0
gpio debug MHal_GPIO_Pad_Set:606
gpio[76] is 0
gpio init: gpio output 15 0
gpio debug MHal_GPIO_Pad_Set:606
gpio[15] is 0
*******************************************
Net:   MAC Address 00:00:23:34:45:68
Auto-Negotiation...
Link Status Speed:100 Full-duplex:1
sstar_emac
Autobooting in 1 seconds
copying flash to 0x21000000
Flash is detected (0x0C07, 0x20, 0x70, 0x17)
SF: Detected nor0 with total size 8 MiB
SF: 8388608 bytes @ 0x0 Read: OK
validate local firmware...
TP Header at 21080000
verifying uboot partition...
ok
verifying kernel and romfs partition...
ok
Uip boot...
Firmware check pass!
Flash is detected (0x0C07, 0x20, 0x70, 0x17)
SF: Detected nor0 with total size 8 MiB
SF: 131072 bytes @ 0x60000 Read: OK
[XZ] !!!reserved 0x21000000 length=0x 1000000 for xz!!
XZ params: in_addr 0x21000040,in_size 0x10000, out_addr 0x220a0000, out_size 0x40000
XZ: uncompress ret 7, size = 262144
▒# Starting application at 0x220A0000 ...

U-Boot 2015.01 (Aug 20 2021 - 17:55:38)

Version: I6g4722ec2
DRAM:  64 MiB
WARNING: Caches not enabled
Using default environment

In:    serial
Out:   serial
Err:   serial
*******************************************
board_late_init for upgrade image
gpio debug MHal_GPIO_Pad_Set:606
gpio[54] is 0
gpio debug MHal_GPIO_Pad_Set:606
gpio[55] is 0
gpio debug MHal_GPIO_Pad_Set:606
gpio[56] is 0
gpio debug MHal_GPIO_Pad_Set:606
gpio[57] is 0
gpio debug MHal_GPIO_Pad_Set:606
gpio[58] is 0
gpio debug MHal_GPIO_Pad_Set:606
gpio[59] is 0
*******************************************
Net:   MAC Address 00:30:1B:BA:02:DB
Auto-Negotiation...
Link Status Speed:100 Full-duplex:1
sstar_emac
Warning: sstar_emac using MAC address from net device

Flash is detected (0x0C07, 0x20, 0x70, 0x17)
SF: Detected nor0 with total size 8 MiB
SF: 3145728 bytes @ 0x80000 Read: OK
##  Booting kernel from Legacy Image at 20008200 ...
   Image Name:   Linux-4.9.84
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1652704 Bytes = 1.6 MiB
   Load Address: 20008000
   Entry Point:  20008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
ERR: Can't find KIMG header and initrd address, 0x00000000
atags:0x20000000

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.9.84 (jenkins@wlcilnx3) (gcc version 4.9.4 (Buildroot 2017.08-gc7bbae9) ) #1 PREEMPT Fri Aug 20 17:58:59 CST 2021
[    0.000000] CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr=50c53c7d
[    0.000000] CPU: div instructions available: patching division code
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] early_atags_to_fdt() success