PWN华为HG8120C光猫(二)
由 李晓岚 在 2016年05月20日发表
上一篇博文中,由于厂商采取了一定的安全预防措施,试图通过UART来PWN ONT HG8120C的尝试出人意料的失败了,但是这并不能摧毁我不达目的不罢休的决心,又尝试了多种方法,还是未能成功。难道非得使用直接读写Flash芯片(这种方法风险较大,可能损坏设备。同时设备也不能用,会断网,家里人会很生气,后果很严重。所以在还有其它可能的情况下,是不会轻易使用这种方法的。)这个终极法宝了?几乎绝望之际,想起来网上流传的厂商维护使能工具,又燃起了一丝希望。
维护使能工具能做什么
该工具用于厂商售后,所谓使能,就是开启设备的维护模式,并关闭防火墙对telnet 23端口的访问限制。使能后,telnet终端能够完成的设备维护的全部操作(UART得到的命令行其实就是这个telnet终端),但对于我的目的,得到root shell并运行tcpdump
来说,毫无用处。所以,引起我兴趣的不是使能后能做什么,而是使能工具如何和设备交互,发出使能命令的,说不定也能发出其它命令,比如就像我期望的tcpdump
。
维护使能工具的工作原理
该工具是运行的Windows上的一个可执行文件,想了解其工作原理,有两个办法:一是对exe进行逆向工程,二是抓包分析其发送的数据(其实不能算分析,纯粹瞎猜各个字节的意义,然后小心求证罢了)。使用dumpbin查看exe文件:
D:\tmp>dumpbin /summary ONT.exe
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Dump of file D:\tmp\ONT.exe
File Type: EXECUTABLE IMAGE
Summary
2000 .text
2000 HWB8zP1w
1000 LEXmTy1n
216000 QrVbjeUa
20E000 lS8TSGXu
29000 niBTgJWZ
1000 sfW0L9wz
从section name来看,应该加过壳,逆向工程难度未知,那就试试抓包吧。
11:26:03.559243 IP 192.168.1.2.819 > 255.255.255.255.6877: UDP, length 244
11:26:03.568366 IP 192.168.1.2.918 > 224.0.0.99.4891: UDP, length 1220
11:26:03.770581 IP 192.168.1.2.918 > 224.0.0.99.4891: UDP, length 1220
11:26:03.771255 IP 192.168.1.2.918 > 224.0.0.99.4891: UDP, length 1220
11:26:03.803305 IP 192.168.1.2.918 > 224.0.0.99.4891: UDP, length 1220
11:26:03.805057 IP 192.168.1.2.918 > 224.0.0.99.4891: UDP, length 1220
11:26:03.805933 IP 192.168.1.2.918 > 224.0.0.99.4891: UDP, length 1220
11:26:03.836141 IP 192.168.1.2.918 > 224.0.0.99.4891: UDP, length 1220
11:26:03.836869 IP 192.168.1.2.918 > 224.0.0.99.4891: UDP, length 1220
在第一个广播包中,发现了224.0.0.99
和4891
,于是猜测第一个UDP广播包是敲门砖,告诉设备后续数据包的目的IP和端口,其中还包括了后续数据包的个数和大小。后面的数据包就更简单了,几个固定值,包序号,数据长度,\0
填充和数据。为了克服UDP丢包问题,每个数据包都进行了多次重传。有了这些信息,很容易就可以从抓包的数据中,拼凑出完整的payload(其实,使能工具运行起来后,壳已经将数据解压,抓取其内存镜像,就能从中获取到完整的payload,只是不好确定payload和其它数据的边界而已)。有了payload后,对其使用常用的CRC16,CRC32,MD5,SHA-1等摘要算法,马上就发现了广播包中也包含也payload的CRC32信息。
将完整的payload保存为payload.bin,使用strings查看:
leexiaolan@localhost $ strings payload.bin
HWNP
120|130|140|141|150|160|170|171|180|190|1B1|1A1|1A0|1B0|1D0|1F1|201|211|221|230|240|260|261|270|271|280|281|291|2A1|431|
file:/var/UpgradeCheck.xml
UPGRDCHECK
file:/mnt/jffs2/equipment.tar.gz
MODULE
file:/mnt/jffs2/ProductLineMode
UNKNOWN
file:/mnt/jffs2/TelnetEnable
UNKNOWN
file:/tmp/duit9rr.sh
UNKNOWN
file:/var/efs
...
poo2
#! /bin/sh
var_etc_version_file="/etc/version"
var_etc_version=""
var_version_1="V100R006C00SPC130"
var_version_2="V200R006C00SPC130"
var_version_3="V300R013C00SPC106"
var_version_4="V300R013C10SPC108"
var_etc_version_V=""
var_etc_version_R=""
...
有趣的东西终于出现了,看起来有个像shell脚本的字符串。仔细深入查看发现:
#设置打开telnet的控制节点
HW_Open_Telnet_Ctree_Node()
{
var_node_telnet=InternetGatewayDevice.X_HW_Security.AclServices
#set telnet
EnableLanTelnetValue="1"
cp -f $var_jffs2_current_ctree_file $var_current_ctree_bak_file
$var_pack_temp_dir/aescrypt2 1 $var_current_ctree_bak_file $var_current_ctree_file_tmp
mv $var_current_ctree_bak_file $var_current_ctree_bak_file".gz"
gunzip -f $var_current_ctree_bak_file".gz"
#set TELNETLanEnable
cfgtool set $var_current_ctree_bak_file $var_node_telnet TELNETLanEnable $EnableLanTelnetValue
if [ 0 -ne $? ]
then
echo "ERROR::Failed to set TELNETLanEnable!"
fi
#encrypt var_default_ctree
gzip -f $var_current_ctree_bak_file
mv $var_current_ctree_bak_file".gz" $var_current_ctree_bak_file
$var_pack_temp_dir/aescrypt2 0 $var_current_ctree_bak_file $var_current_ctree_file_tmp
rm -f $var_jffs2_current_ctree_file
cp -f $var_current_ctree_bak_file $var_jffs2_current_ctree_file
return 0
}
原来是给ONT设备发送了一个shell脚本来开启telnet。嗯,这看起来很像我要的执行任意代码的入口。
转机
如果能继续把payload的文件结构分析(瞎猜)清楚,就能修改payload中的脚本,运行我自己的代码了。至于如何发送修改过后的payload,这个大可不必自己写个程序来实现维护使能工具那套逻辑,使用原始工具使能telnet后,通过telnet终端使用load pack
命令从FTP
或TFTP
加载payload即可。还有另一个好处就是,维护使能工具必须在未接入运营商网络的情况下使用,而load pack
没有这个限制。离目标PWN越来越近了,后篇将分析payload结构,并修改和运行我自己的payload。
PS: 上述信息经过华为PSIRT确认,不会对用户或网络带来风险。
comments powered by Disqus