串口调试是研究嵌入式设备的一个重要的手段,笔者前段时间受某厂商邀请测试摄像头的时候,厂商提供的固件是一个对部分elf进行更新的升级包,未能提供完整的文件系统,导致研究起来会有一些不便之处,而且可能会有一些版本不匹配的问题。当时是希望先从网络层面发现一个基础的注入漏洞,然后telnet连接上去把文件系统带出来,但是没能成功,于是就考虑串口调试。在此记录一下自己研究过程中的一些发现
这里指的串口一般是UART串口,一般设备上都是几个连在一起的孔洞:

(图为某厂商的路由器拆机图)
上面可能会标注"TX""RX""GND"字样,也可能没有。不过可以用电表测电压来进行识别(RX为高电平,TX与GND为低电平)
测试出TX,RX,GND过后可以通过UART转USB串口调试器以及跳线(一头焊接在孔洞上,一头连转换器)连接到电脑上进行串口调试(建议使用好的沾锡焊头,不然会焊坏QAQ)
但是笔者研究的这个设备它的串口是拆开后裸露的三个引脚:

当初是通过电表测试发现其中一个引脚是GND然后就猜测是UART串口,拿跳线焊上然后连接的时候排列组合一下发现使用串口调试软件能够正常通信(其实就是RX对TX,TX对RX):

至此我们就解决了怎么发现串口和如何连接的问题
解决了硬件层面的问题下面来说软件
笔者使用的调试软件是SecureCRT,官方下载链接如下:
SecureCRT - The rock-solid Telnet and SSH client for Windows, Mac, and Linux (vandyke.com)
具体用法为:
File->connect/quick connect->Serial(选择正确的串口号和波特率)->connect

配置好后连接上去的显示画面如下:

但是我们一开始不管按什么键都是没办法进行操作的,如果按回车还会出现如下字样:

然而如果我们重启然后狂按回车,就会进入uboot阶段:

uboot的shell有一些命令可以获取当前的一些配置信息和环境变量,更为严重的是它可以对设备的boot命令bootcmd以及boot的参数bootargs进行修改:

如上图,如果我们将bootargs的init从/linuxrc改成/bin/sh,就能在boot过后获取命令行:

所以有些厂商使用了比较保守的串口shell来阻止进行修改bootargs:
(图片来自好朋友狒星橙师傅)

像这种按上面的方式来就很困难了
我们是在执行/linuxrc之前获取的shell,那么一些诸如网络连接的初始化设置是没有完成的
但如果直接执行/linuxrc,会丢失这个shell,那么我们要么在断网的情况下把文件系统带出来,要么寻找其它思路把网络打开
一开始的想法
在没有网络连接的情况下,笔者一开始觉得可以把一些关键的elf,通过vim把它们的文本形式给复制出来,粘贴到一个文本文件中然后通过python或者其它工具把这个文本再给转换为一个elf文件。但是这个设备里面没有vim只有vi,vi没有vim那么丰富的功能,也不太可能直接复制全文。拿linuxrc这个文件举例,它的文本形式有1万多行,如果一页一页的粘贴,天都亮了,而且如果出现一个失误,还是不能弄出来
后续
放弃了这个思路,笔者就考虑一些本质上的东西
说到底这个linuxrc是个初始化文件,它的目的应该就是执行一些初始化的诸如elf或者.sh脚本,那么如果我们能找到它执行的东西手动去执行,应该也能达到初始化设置的目的
大家可能会想,如果直接执行init.d目录下的rcS不就好了?但是直接执行会报错,还是会有一些未初始化的东西
这个时候我们就可以采用逆向分析时候按“X”键进行交叉引用的思想,去找有没有脚本会用到rcS:
1 | grep - ri "rcS" . / 2 > / dev / null
|

果然会有,我们目光锁定到etc目录下的inittab,直接执行它,发现是和执行/linuxrc是一个效果也不会报错
至此我们就能够顺藤摸瓜,摸出一条完整的执行链(笔者当时是几个sh文件,一行一行去尝试的QAQ):
linuxrc->inittable->rcS->(因为涉及厂商安全隐私问题不与展示)......->wificonnect.sh
最后执行了这个wificonnect我们就可以连上网了,甚至不用执行打开摄像头的elf
连上网过后,有很多手段可以把文件系统拿出来,笔者这里介绍一个相对容易的手段
首先通过fdisk -l查看磁盘分区情况,一般比较大的就有很大可能存在文件系统
确定了过后通过以下指令把整个分区打包为一个bin文件(以mtdblock0为例):
1 | dd if = / dev / mtdblock0 of = . / route. bin
|
然后本地通过nc监听1234端口:
1 | nc - l - p 1234 > route. bin
|
设备上通过nc传递bin文件:
1 | nc 192.168 . 0.33 1234 < route. bin
|
然后本地就能通过binwalk解压这个bin文件获取文件系统了
还记得前面提到过如果我们按回车会出现的“xxxlogin字样”,如果输入些什么东西的话就会让我们输入密码
在开启23端口的情况下,如果我们telnet也会出现相同的login字样
猜测这两个东西可能用的是同一个密码,而且有很大的可能存在未授权。但是从/etc目录不能找到密码
那么密码就很可能在二进制文件里了
经过测试,这个“login字样”是在执行摄像头的两个关键elf之前就有了,于是我们把可能出现密码泄露的地方着眼于linuxrc这个elf文件
从中我们能找到一些很可疑的地方:

当我们输入错误密码的时候报错为“Login incorrect”,于是交叉引用到这个地方:

有个LABEL_34,找到goto它的地方:

发现有一些复杂的检查,直接逆向的困难非常大。但是我们传一个gdbserver上去进行调试,很快就能破解这个密码了,这里看着比较复杂的sub_497048其实是对"012345679"这个密码进行了一些变化,然后进行的比较,但如果直接用gdbserver上去看的话,可以直接看到变化结果,其实就是密码了
当时笔者拿到这个设备过后萌生了一个比较3岁的玩法hh

学习拆机调试路由器 - X1ng's Blog
西湖论剑 2020 IoT闯关赛 赛后整理 - clang裁缝店
[注意]看雪招聘,专注安全领域的专业人才平台!
最后于 2023-3-2 21:20
被Nameless_a编辑
,原因: