国庆回老家,看到爷爷一个人看IPTV的时候,遥控按错了就看不了电视了,爷爷年纪大了,耳朵也不好使了,给他买的智能手机也不会打电话,只懂得发起微信视频,我打回去还不懂如何接,有时候真是有话都说不清楚。趁着放假几天,我就逆向了PT632 G2光猫的固件,实现远程控制家里的所有联网设备,以后再跟我说电视看不了,我直接远程操作一下就可以了。

测试发现佛山电信使用的公网IP,不用使用云服务器进行远程端口映射,只需要使用动态域名解析就可以访问路由器,PT632这个光猫自带了ez-ipupdate这个软件,但是并不支持3322的动态域名解析服务,而且这个功能也并不能通过WEB管理页面开启。使用ssh管理路由器,可以对要控制的设备进行端口映射,随时随地都能管理网关内的设备。

博主vasvir提供了破解ZTE-H108NS路由器的思路,PT632_G2使用的是tclinux,我是通过关键词tclinux找到这个博客的,博主写了三篇博文详细叙述了他的破解过程。每一篇我都反复阅读和调试,才确认他的思路同样可以应用到PT632这个系列的光猫上。但存在一些不同的地方,毕竟不是一样的路由器,比如提取固件的方法,他是直接在官网下载的,我是用netcat dump出来的;固件的头部有不一样的地方,有三个信息点必须填上,不然就算通过了CRC校验算法,也会刷机失败的;还有就是压缩和解包工具不同,使用的文件系统版本不同。

bootloader分区就不要轻易去碰,变砖了就要把Flash吹下来上编程器。动手之前需要了解光猫的基本信息:

  1. CPU是Ralink MT751020 SOC,64M内存,64M闪存,分区情况如下表所示
  2. Bootloader、Web界面管理的中国电信超级用户名:telecomadmin,密码:nE7jA%5m
  3. TTL Text Console、Telnet的用户名:admin,密码:1234或TeleCom_1234

启用Telnet服务的方法:登录Web管理后台,在地址栏输入http://192.168.1.1/cgi-bin/telnet.asp,勾选启用

dev: size erasesize name 说明
mtd0: 40000 20000 bootloader 最好别碰,小心变砖
mtd1: 40000 20000 romfile 保存配置文件
mtd2: 001614eb 20000 kernel 内核1
mtd3: 006d0000 20000 rootfs 根文件系统1
mtd4: 1000000 20000 tclinux 保存固件1
mtd5: 001614eb 20000 kernel_slave 内核2
mtd6: 006d0000 20000 rootfs_slave 根文件系统2
mtd7: 1000000 20000 tclinux_slave 保存固件2
mtd8: 400000 20000 jffs2  
mtd9: 001c0000 20000 reservearea  

1 提取固件

这型号的光猫是不带USB口的,提取固件需要用netcat实时传到本地主机。darkerego提供了多个常用的mips架构的程序。 假如本机地址为192.168.1.2

git clone https://github.com/darkerego/mips-binaries
cd mips-binaries
#用http协议传
python -m SimleHTTPServer 8000 &
#用ftp协议传
sudo pip install pyftpdlib
#ftp服务器默认的端口是2121
python -m pyftpdlib &
netcat -l -p 7000 > tclinux.bin
# 路由器地址192.168.1.1
cd /tmp
wget http://192.168.1.1:8000/netcat
ftpget -P 2121 192.168.1.2 netcat /tmp/netcat
chmod +x netcat
#-c 当到达标准输入结尾就关闭连接
dd if=/dev/mtd3 | netcat 192.168.1.2 7000 -c

保险起见,可以把所有分区都备份下来,万一把光猫刷挂了,可以随时恢复过来。 提取到tclinux.bin之后,就相当于拿到官方的固件,这个bin文件是分区的镜像,并非官方固件,用010 Editor可以看到固件的实际大小为0x855A86。

2 解包固件

博主vasvir逆向分析出了tclinux使用的CRC算法,写了个叫tcrevenge程序放到了github上,我也用IDA Pro分析了一下反汇编代码,算法是一致的,我们可以通过该程序计算提取到的固件的校验码,比对固件中的校验码,检查一下CRC算法是否正确,结果发现原程序缺少了三个信息点,导致生成的校验码不一致。

用010 Editor查看提取到的根文件系统1614EB.squashfs,发现它是使用默认参数压缩生成的。但是我原封不动,仅仅使用默认参数进行压缩,打包出来的squashfs-root.sq比原来的大,原本的根文件系统差不多把分区都占满了,如果重新打包文件大了,就塞不下其他任何软件了,这让我纠结了好久。尝试使用squashfs各个版本的压缩工具去打包根文件系统,都没有发现能打包成同样大小的。我选择了squashfs 3.0文件系统工具去打包,打包出来的文件就比原来的小一点,我觉得旧的压缩格式可能也能兼容,但很不幸刷进去就挂掉了,最终还是摆脱不了使用调试线救砖。

有了调试线的帮助,在添加软件定制固件前,可以大胆地先进行一些验证性的试验:

  1. 用提取到的根文件系统1614EB.squashfs、kernel和tcrevenge生成header重新打包固件,比对二进制数据是否一致,验证tcrevenge程序的正确性。
  2. 使用不同的压缩参数重新打包根文件系统,用修改好的tcrevenge程序生成新的固件,试刷固件,验证定制固件的可行性。

    dd if=tclinux.bin of=tclinux.bin.orig bs=1 count=$((0x855A86))
    sudo apt-get install binwalk squashfs-tools
    #需要用root权限执行,解包的根文件系统中包含设备文件
    sudo binwalk -e tclinux.bin.orig
    #提取kernel
    cd _tclinux.bin.org.extracted
    #生成的压缩文件跟原来的不一致,尝试过多个版本的压缩工具,没有找到压缩结果一致的,这一步纠结了很久
    mksquashfs squashfs-root squashfs-root.sq -comp lzma
    #重新打包固件
    dd if=../tclinux.bin.orig of=kernel skip=256 count=`binwalk ../tclinux.bin.orig | awk '/Squash/ {print $1 - 256;}'` bs=1
    tcrevenge -k kernel -s 1614EB.squashfs -o header
    #用010 Editor对比生成的固件和提取的固件,发现了校验头文件中少3个信息点,修改tcrevenge程序
    cat header kernel squashfs-root.sq padding > tclinux.bin.new
    #用压缩比更高的参数压缩根文件系统,生成新的固件,成功刷入光猫中
    mksquashfs squashfs-root squashfs-root.sq -comp lzma -b 524288
    tcrevenge -k kernel -s squashfs-root.sq -o header
    cat header kernel squashfs-root.sq padding > tclinux.bin.new

3 解压根文件系统

特别要注意,解压根文件系统的时候,会创建设备文件,需要root权限,在上一步中忘记使用root权限运行binwalk -e命令,可以把squashfs-root文件夹删掉,用unsquashfs重新解压根文件系统。

sudo rm -rf squashfs-root
sudo unsquashfs 1614EB.squashfs

4 添加软件

根文件系统的空间十分有限,我只为路由器添加用于动态域名解析的ez-ipupdate和用于sshd服务的dropbear,光猫上自带了ez-ipupdate程序,却无法通过WEB管理界面启用ddns服务,而且不支持3322动态域名解析服务,需要自己编译3322提供的ez-ipupdate源代码。我也懒得修改cgi程序以支持Web管理,直接把配置信息放在了固件当中。根文件系统实在没有空间放下sshd,只能使用功能稍弱一点的dropbear,有了这两个软件就已经能满足我的需求了。

4.1 ez-ipupdate

设置交叉编译工具链很麻烦,uClibc.org提供了包含mips,arm,amd64等多种Qemu的虚拟机镜像,系统里包含完整的编译工具链,免去设置环境变量的麻烦,缺点就是编译的速度稍慢。

wget https://uclibc.org/downloads/binaries/0.9.30/system-image-mips.tar.bz2
tar xvf system-image-mips.tar.bz2
cd system-image-mips
# 给虚拟机新增一个ext2镜像,默认会挂载到/home目录
qemu-img create -f raw disk.ext2 2G
sudo losetup /dev/loop0 hardisk.ext2
sudo mkfs.ext2 /dev/loop0
sudo mount /dev/loop0 /mnt
sed 's/$/& -hdb disk.ext2/' -i run-emulator.sh
#下载3322提供的源代码
sudo curl http://img.pubyun.com/download/ez-ipupdate-3.0.11b8.tar.gz -o /mnt/ez-ipupdate.tar.gz
sudo tar xvf /mnt/ez-ipupdate.tar.gz -C /mnt
sudo umount /mnt
sudo losetup -d /dev/loop0
#启动虚拟机
./run-emulator.sh
#编译ez-ipupdate
cd /home/ez-ipupdate-3.0.11b8/
./configure
make
#复制编译结果ez-ipupdate到主机上
scp ez-ipupdate wing@10.0.2.2:/home/wing/Workspace/pt632_g2/_tclinux.bin.orig.extracted/squashfs-root/usr/bin/
#添加ez-ipupdate配置文件qdns.conf
cd /home/wing/Workspace/pt632_g2/_tclinux.bin.orig.extracted/squashfs-root/usr/etc
$username=
$passswd=
$your_ddns_domain=
sudo cat > qdns.conf << EOF
service-type=qdns
user=$username:$passwd
host=$your_ddns_domain
interface=ppp24
max-interval=2073600
cache-file=/tmp/ez-ipupdate.cache
EOF

4.2 dropbear

cd /home/wing/Workspace/pt632_g2/_tclinux.bin.orig.extracted/squashfs-root/usr
sudo -s
curl https://raw.githubusercontent.com/darkerego/mips-binaries/master/dropbearmulti -o bin/dropbear
mkdir etc/dropbear
#生成host_key
ssh-keygen -t dss -f etc/dropbear/dropbear_dss_host_key
ssh-keygen -t rsa -f etc/dropbear/dropbear_rsa_host_key
ssh-keygen -t ecdsa -f etc/cdropbear/dropbear_ecdsa_host_key
#添加authorized_keys
mkdir etc/.ssh
cat /home/wing/.ssh/id_rsa.pub >> etc/.ssh/authorized_keys
touch etc/script/dropbear.sh
chmod +x etc/script/dropbear.sh
cat > script/dropbear.sh << EOF
#!/bin/sh
/sbin/arp -s 192.168.1.254 FF:FF:FF:FF:FF:FF
echo "wing:x:0:0:root:/tmp:/bin/sh" >> /tmp/etc/passwd
echo "export PATH=/userfs/bin:/usr/sbin:/bin:/usr/bin:/sbin" > /tmp/.profile
/bin/mkdir -m 0700 -p /tmp/.ssh
cat /usr/etc/.ssh/authorized_keys > /tmp/.ssh/authorized_keys
/bin/chmod 600 /tmp/.ssh/authorized_keys
#-s 禁止密码登录
#-a 远程端口转发监听所有接口
/usr/bin/dropbear -s -a
/userfs/bin/ez-ipupdate -d -c /etc/qdns.conf
EOF
#开机自动运行
echo "/usr/script/dropbear.sh" >> etc/init.d/rcS

5 打包固件

# 压缩根文件系统
mksquashfs squashfs-root squashfs-root.sq -comp lzma -b 524288
# 生成CRC校验头
tcrevenge -k kernel -s squashfs-root.sq -o header
# 合并header、kernel和root.squashfs
cat header kernel squashfs-root.sq padding > tclinux.bin.new

6 刷机

Last Updated 2018-10-14 日 23:38.
Created by Emacs 25.1.1 (Org mode 9.1.14)