闲鱼20包邮购得这款400万像素的小摇头机,型号AP6PCM03,是360为移动制造的和家亲定制机型。卖家说被绑定了所以卖这么便宜,收到发现又能直接添加到和家亲App中,捡了个便宜。不过坑爹的移动连观看直播都必须先购买云存储套餐,而且还按分辨率收费,要看满血400万像素的1440P画面的话还得多掏钱,算是开了眼界了。
20块买的摄像头还得每月给移动掏至少15才能用?气得我直接拿起了螺丝刀拆了它
硬件配置
- SoC:Ingenic君正 T31ZX,单核1.5GHz
- CMOS:格科微 GC4653 靶面1/3" 像素尺寸2.0x2.0um
- RAM:SoC内置128MB DDR2
- ROM:32MB NOR
- 镜头:4mm M12带IR-CUT
- 其他配置:带红外补光灯,PTZ,WiFi+有线连接,TF卡卡槽,语音对讲
20块能买到这么丰富的配置也算值了,换成海康萤石至少得多加个零
备份原始固件
折腾任何机器的第一步永远是备份 接上TTL串口,波特率115200,uboot任意键中断,记录下printenv
isvp_t31# print
baudrate=115200
bootargs=console=ttyS1,115200n8 mem=66M@0x0 rmem=62M@0x4200000 init=/linuxrc rootfstype=squashfs root=/dev/mtdblock5 rw mtdparts=jz_sfc:256k(boot),1792k(kernel),1792k(rootfs),11456k(user),1792k(kernel2),1792k(rootfs2),11456k(user2),2304k(mtd),-(factory)
bootcmd=sdupdate;sf probe;sf read 0x80600000 0x0ef0000 0x1C0000; bootm 0x80600000
bootdelay=1
ethact=Jz4775-9161
ethaddr=00:d0:d0:00:95:27
gatewayip=193.169.4.1
ipaddr=193.169.4.81
loads_echo=1
netmask=255.255.255.0
serverip=193.169.4.2
stderr=serial
stdin=serial
stdout=serial
能使用的命令有
isvp_t31# help
? - alias for 'help'
base - print or set address offset
boot - boot default, i.e., run 'bootcmd'
boota - boot android system
bootd - boot default, i.e., run 'bootcmd'
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
chpart - change active partition
cmp - memory compare
coninfo - print console devices and information
cp - memory copy
crc32 - checksum calculation
echo - echo args to console
env - environment handling commands
ethphy - ethphy contrl
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
gettime - get timer val elapsed,
go - start application at address 'addr'
help - print command description/usage
loadb - load binary file over serial line (kermit mode)
loads - load S-Record file over serial line
loady - load binary file over serial line (ymodem mode)
loop - infinite loop on address range
md - memory display
mm - memory modify (auto-incrementing address)
mmc - MMC sub system
mmcinfo - display MMC info
mtdparts- define flash/nand partitions
mw - memory write (fill)
nm - memory modify (constant address)
ping - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
reset - Perform RESET of the CPU
run - run commands in an environment variable
saveenv - save environment variables to persistent storage
sdupdate- auto upgrade file from mmc to flash
setenv - set environment variables
sf - SPI flash sub-system
sleep - delay execution for some time
source - run script from memory
tftpboot- boot image via network using TFTP protocol
version - print monitor, compiler and linker version
还不错,刚以为没有阉割的时候就发现saveenv命令无法保存,tftp命令也没有上传功能。直接启动进系统看看。
回车后提示需要输入密码才能进去shell,尝试了几个简单的密码发现都不对,网上也收不到前人的分享。无果后再次进去uboot,修改bootargs
内init=/bin/sh
,因为无法保存环境变量,所以直接run bootcmd
启动,顺利直接进入shell,运行/etc/init.d/rcS
,发现/dev/
下依然为空,想在这备份闪存的想法也落空,一番尝试无果后放弃。
天无绝人之路,发现这台摄像头带TF卡卡槽,而且uboot内也有mmc
命令,便想应该可以把NOR闪存备份到TF卡上,实操如下
sf probe 0
sf read 0x8060000 0x0 0x2000000
mmc erase 0x0 0x10000
mmc write 0x8060000 0x0 0x10000 #本人TF卡block size为512Bytes
拔卡插入到电脑,dd if=/dev/mmcblk0 of=ap6pcm03_fulldump.bin bs=32768
,得到32MB的完整闪存备份,根据启动日志里的分区表分割得到如下分区备份镜像:
[ 0.442736] Creating 9 MTD partitions on "jz_sfc":
[ 0.447680] 0x000000000000-0x000000040000 : "boot"
[ 0.453038] 0x000000040000-0x000000200000 : "kernel"
[ 0.458499] 0x000000200000-0x0000003c0000 : "rootfs"
[ 0.464029] 0x0000003c0000-0x000000ef0000 : "user"
[ 0.469336] 0x000000ef0000-0x0000010b0000 : "kernel2"
[ 0.474962] 0x0000010b0000-0x000001270000 : "rootfs2"
[ 0.480521] 0x000001270000-0x000001da0000 : "user2"
[ 0.485976] 0x000001da0000-0x000001fe0000 : "mtd"
[ 0.491179] 0x000001fe0000-0x000002000000 : "factory"
获取root密码
很简单常见的结构,主要三个kernel, rootfs和user分区都有两块互为备份,rootfs分区为squashfs文件系统,mtd为jffs2。
把rootfs挂载出来,查看/etc/shadow
得到hash后的root密码
root:$1$fL41PBYl$yNygtpB92IyBwCn7QVvqc/:0:0:99999:7:::
Google也搜不到记录,看来不是一个常见的密码,就不用想暴力破解了。好在squashfs文件系统有方便的解包和打包工具,修改passwd和shadow文件清空root密码,使用mksquashfs重新打包得到清空了root密码的rootfs分区镜像,再使用tftp下载到闪存,启动后顺利进入完整的shell环境
进入无人之地
Linux version 3.10.14__isvp_swan_1.0__ (hlh@serverforbuild) (gcc version 4.7.2 (Ingenic r2.3.3 2016.12) ) #57 PREEMPT Thu Mar 25 14:42:16 CST 2021
~ # cat /proc/cpuinfo
system type : Swan
machine : Unknown
processor : 0
cpu model : Ingenic Xburst V0.0 FPU V0.0
BogoMIPS : 1391.00
wait instruction : yes
microsecond timers : no
tlb_entries : 32
extra interrupt vector : yes
hardware watchpoint : yes, count: 1, address/irw mask: [0x0fff]
isa : mips32r1
ASEs implemented :
shadow register sets : 1
kscratch registers : 7
core : 0
VCED exceptions : not available
VCEI exceptions : not available
Hardware : isvp
Serial : 00000000 00000000 00000000 00000000
[@Ingenic:system_rw]# df -h
Filesystem Size Used Available Use% Mounted on
/dev/root 1.4M 1.4M 0 100% /
tmpfs 29.7M 12.0K 29.7M 0% /dev
tmpfs 29.7M 40.0K 29.6M 0% /tmp
tmpfs 29.7M 0 29.7M 0% /run
tmpfs 29.7M 176.0K 29.5M 1% /var
/dev/mtdblock6 5.7M 5.7M 0 100% /usr
/dev/mtdblock7 2.3M 180.0K 2.1M 8% /system_rw
[@Ingenic:system_rw]# mount
rootfs on / type rootfs (rw)
/dev/root on / type squashfs (ro,relatime)
tmpfs on /dev type tmpfs (rw,relatime)
proc on /proc type proc (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /tmp type tmpfs (rw,relatime)
tmpfs on /run type tmpfs (rw,nosuid,nodev,relatime,mode=755)
tmpfs on /var type tmpfs (rw,nosuid,nodev,relatime,mode=755)
sysfs on /sys type sysfs (rw,relatime)
/dev/mtdblock6 on /usr type squashfs (ro,relatime)
/dev/mtdblock7 on /system_rw type jffs2 (rw,relatime)
usr
分区只读,存放了厂家的二进制和配置文件,mtd
为可读分区,挂载到/system_rw
,用于存储动态参数,factory
分区无文件系统,直接存放二进制的SN/MAC/CMEI等出厂信息,还有用于注册到和家亲服务器的验证信息,实测修改过SN后和家亲无法上线
开机自启动telnetd
vi /system_rw/rc.local
,在最后加入如下命令以开机自启动telnetd
/sbin/telnetd &
echo "telnetd running"
顺利变转与救砖
正开心把玩中,uboot毫无征兆地挂了。上电无法进入uboot,这可算彻底变砖了,把玩还没超过十分钟。一番搜索君正T31的资料,找到了芯片手册,发现君正芯片的启动流程,无论BOOT_SEL如何设置,从NOR启动失败后都会自动尝试从SD卡启动,如果依然失败,会继续尝试从USB接口启动,形如SFC->MSC0->MSC1->USB->SFC。而这台摄像头又带有TF卡卡槽,所以理论上应该可以把uboot写入到TF卡来启动救砖。
但君正不同启动介质的uboot还不一样,之前备份的NOR闪存上的uboot并不能用于SD卡启动,还得自己从头编译。还好Github上找到了别人分享的君正T31 SDK,内含T31的uboot源码和编译工具。
编译用于SD卡启动的uboot
解压toolchain目录下的gcc_472 -> mips-gcc472-glibc216-64bit-r2.3.3.7z,将其bin目录路径添加到系统环境变量中。进入opensource/uboot
目录,执行如下命令
make distclean #清除旧配置
make isvp_t31_msc0_ddr128M
得到用于SD卡启动的uboot镜像uboot-with-spl.bin
。插入TF卡读卡器,将uboot镜像写入到TF卡17KB偏移处
dd if=./u-boot-with-spl.bin of=/dev/mmcblk0 seek=34
这里详细记录下我踩的一个坑,dd的seek参数作用为skip N obs-sized blocks at start of output
,意为跳过写入对象的前N block,注意单位是block,而不是KBytes。我所使用的TF卡block size为512Bytes,所以17KB就是34 block。这个细节导致我浪费了很多时间,一直使用seek=17参数
不出意外的话应该能从TF卡启动uboot了,之后再通过tftp或者mmc写入之前备份的原始uboot或其他分区镜像。看来只要有TF卡插槽的话,君正芯片的板子很难真正变转。
刷入第三方固件
略。。。