物联网硬件安全

​ 物联网设备虽然是一个极度精简的设备,但是就其本质来讲仍然是是一个完整的计算机系统.在计算机系统的编码过程中必然有"调试"这样的需求.区别与传统的软件开发,物联网设备往往是在硬件层面支持/实现调试功能,与此对应的是硬件设备上往往会存在用于调试系统/软件的物理接口.通过调试接口可以直接获得大部分设备终端.此外在物联网领也可以利用uart或者jtag来提取设备的固件.本章就以当前市面上比较流行的uart作为讲解实例.

0x1 uart

​ 关于uart的基础知识在之前的章节中已经进行了的详细的介绍就不再这里赘述了.这里主要介绍uart的几个重要概念:

  1. uart一共有四个接口,分别为:RX,TX,GND,VCC

    1. RX负责接收数据
    2. TX负责发送数据
    3. GND接地,有的时候rx接受数据有问题,就要接上这个pin,一般也可不接
    4. VCC负责供电,一般是3.3v,这个pin一般不接更安全
  2. uart设备进行连接时应该是各自的RX与对面的TX之间建立链接
  3. 波特率:每秒钟发送的二进制位数.只有设置正确的比特率才能进行正常沟通,可以近似的理解为"无线电频率".
  4. 典型的波特率是300, 1200, 2400, 9600, 19200, 115200等.其中 9600/115200 是最常见的传输速度

​ uart链接建立后需要专门的软件来接入链接,一般推荐下面三个软件:

  1. putty
  2. minicom
  3. SecureCRT

主板上一般会标明uart接口,如果没有标明的话可以用下面的诀窍来判断

  1. 通过万用表蜂鸣声判断 GND
  2. GND与VCC短接造成短路来确定VCC
  3. RX,TX 试一下就行了

0x2 uart安装

​ 这一章将会一步一步带领大家完整的走通usb调试uart.主要是围绕硬件链接以及驱动安装来展开,在开始这一章节前需要读者准备好一个"USB转TTL"."USB转TTL"可以将电脑的usb接口转换成uart接口,这样才能用pc直连/调试目标设备.

首先需要准备好一个 usb转ttl模块,一般是下面这个样子

image-20210126143903118.png

接着直接将这个设备连接到电脑上,这时候打开设备管理器,会发现下面这个异常的设备,这是由于驱动没有安装好

image-20210126144045790.png

虽然驱动没有安装,但是设备型号识别出来了是FT232,在win10上大部分usb转ttl设备都存在驱动的问题,需要我们自己去安装,比如这款设备在其官网就有对应的驱动提供

image-20210126144317711.png

直接下载官网提供的驱动包进行安装,驱动安装完成后会出现如下提示界面

image-20210126144515406.png

这是在回到设备管理器,可以发现之前的异常设备消失了,取而代之的是下面这个设备

image-20210126144701670.png

到这里就已经完成了 设备的安装

记住这里的 COM3 这就是设备的识别码,后面链接时需要使用到这个名字

0x3 uart链接

​ 完成了设备的安装,接下来就是将刚刚安装好的usb转ttl连接到目标设备上,具体的安装线路如下图所示

image-20200307145102617.png

首先找到目标设备的uart接口,具体的寻找方式这里就不再阐述了,一般是下面这个样子

image-20210126145609653.png

接着按照 RX->TX,TX->RX,GND-GND的方式来连接,如下图

image-20210126145926023.png

注意到目前为止目标设备还没有通电,usb转ttl已经连接好设备,并且安装在计算机上了

0x4 软件链接

​ 之前的所有步骤都是在为链接uart做准备,目前已经准备妥当了,接下来就是用软件进行连接,这里选用windows平台使用比较方便的putty作为例子:

首先将putty的连接模式更改为串口Serial

image-20210126150414242.png

接着需要设置Serial Line以及Speed,他们分别为目标串口以及波特率

  • 这里的目标串口就是COM3,这是我们之前在设备管理器中获得的
  • 这里的波特率就用默认的9600,这是大多数设备的默认值

设置完成后窗口如下

image-20210126150702125.png

接下来直接点击链接即可

image-20210126150741890.png

接下来我们会卡在上面这个窗口,窗口的标题说明当前链接的是COM3设备,之所以卡在这里是因为目标设备还没有上电

接下来我们对目标设备通电/开机

image-20210126150950232.png

等待设备启动后就可以获得设备的终端了

image-20210126160458221.png

关于终端:

  1. 有的终端没有防护 可以直接获得系统内部的shell
  2. 有的终端需要专用的密码才能进

    需要配合后面讲的固件提取来分析出密码才能进
  3. 有的终端直接进入uboot,没有给系统的会话

    uboot的权限比操作系统还高(类似于 linux与grub之间的关系),操作一下以下也能获得系统会话

0x5 uboot渗透

​ 到此为止我们已经可以尝试对一些比较标准的设备通过uart来获得shell.但是有一部分设备对uart输出的shell进行了限制,给了一个精简过的shell或者直接给了uboot的shell,并没有把系统的shell暴露给uart.在这种情况下我们可以尝试对uboot修改来直接获得shell.因为uboot是引导系统的程序,因此理论上可以强制uboot给我们开启一个系统的shell.

uboot渗透一共有两个思路:

  1. uboot本身就有一些漏洞,可能是逻辑漏洞,也可能是给了一些高级权限
  2. 直接将uboot提取出来,进行修改后替换掉原始的uboot

本期以某电商平台上销量第一的网络摄像头作为案例:

  • 将摄像头拆解后可以发现焊在电路板上的uart引脚
  • 按照下图所示进行uart链接.焊点很小,要非常小心

IMG20210223135725.jpg

  • 调整波特率为115200
  • 通电后可以获得如下信息

image-20210223140254475.png

主板通电后直接运行的uboot,此时uboot给了我们两个选择:

  1. 按任意键就可以中断系统启动,从而进入uboot模式
  2. 忽略uboot中断就可以直接进入操作系统

    操作系统启动后只会在屏幕上输出一些日志信息,并不会给shell会话

我们这里选择直接进入uboot,尝试通过uboot获得操作系统的shell会话.下面就是进入uboot后的终端

image-20210223141955657.png

我们通过help命令来查看一些uboot的指令信息.获取到的指令信息如下

anyka$help
          ?       - alias for 'help'
base    - print or set address offset
bootm   - boot application image from memory
chpart  - change active partition
cmp     - memory compare
cp      - memory copy
crc32   - checksum calculation
devmem  - read or write register, now just read
downimage- downimage   - download and write All-Image to FLASH device,partiton table from ENV partition.
downjffs2fs- load usr.jffs2 tftp
downkernel- load uImage tftp
downrootfs- load root.sqsh4 tftp
downsquashfs- load usr.sqsh4 tftp
downuboot- load uboot tftp
env     - environment handling commands
erase   - erase FLASH memory
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls   - list files in a directory (default /)
flinfo  - print FLASH memory information
format  - erase uboot env
go      - start application at address 'addr'
help    - print command description/usage
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)
parts   - read out partitions table info.
parts_adjust-
adjust parts info. Each part's size,offset etc.

printenv- print environment variables
protect - enable or disable FLASH write protection
readcfg - read config from config.
reset   - Perform RESET of the CPU
run     - run commands in an environment variable
saveenv - save environment variables to persistent storage
setenv  - set environment variables
setloadaddr- set loadaddr to  config infor .
sf      - spi flash sub-system:
tfdownjffs2fs- load usr.jffs2 TF
tfdownkernel- load uImageTF
tfdownrootfs- load root.sqsh4TF
tfdownsquashfs- load usr.sqsh4TF
tfdownuboot- load u-boot.binTF
tfupdateimage- tfupdateimage   - download and write All-Image to FLASH device
updatecfg- update config from config infor table.
version - print monitor, compiler and linker version
  • 可以看到这个uboot的功能还是很完整的
  • 通过uboot我们可以对固件进行升级,此外还可以获取到一些系统启动的参数.

首先通过printenv指令来获取uboot当前的一些环境变量

anyka$printenv
              backuppage=ffffffff
baudrate=115200
boot_normal=readcfg; run read_kernel; bootm ${loadaddr}
bootargs=console=ttySAK0,115200n8 root=/dev/mtdblock4 rootfstype=squashfs init=/sbin/init mem=64M memsize=64M
bootcmd=run boot_normal
bootdelay=2
console=ttySAK0,115200n8
erase_env=sf probe 0:0 ${sf_hz} 0; sf erase 0x20000 0x2000
ethaddr=00:55:7b:b5:7d:f7
fs_addr=0x230000
init=/sbin/init
ipaddr=192.168.1.99
kernel_addr=31000
kernel_size=145748
loadaddr=81808000
memsize=64M
mtd_root=/dev/mtdblock4
netmask=255.255.255.0
read_kernel=sf probe 0:0 ${sf_hz} 0; sf read ${loadaddr} ${kernel_addr} ${kernel_size}
rootfstype=squashfs
serverip=192.168.1.1
setcmd=setenv bootargs console=${console} root=${mtd_root} rootfstype=${rootfstype} init=${init} mem=${memsize}
sf_hz=20000000
stderr=serial
stdin=serial
stdout=serial
update_flag=0
ver=U-Boot 2013.10.0-AK_V2.0.04 (Sep 07 2020 - 11:22:29)
vram=12M

Environment size: 950/4088 bytes
  • 上面列出的就是当前uboot所有的变量/配置信息
  • 其中最重要的参数就是bootargs
  • bootargs中指定了启动参数为init=/sbin/init

我们直接利用setenv修改启动参数init=/sbin/initinit=/bin/sh

setenv  bootargs console=ttySAK0,115200n8 root=/dev/mtdblock4 rootfstype=squashfs init=/bin/sh mem=64M memsize=64M

修改完成后使用printenv重新确认一下是否修改成功

image-20210223143624671.png

接着使用saveenv来保存环境变量

image-20210223144629291.png

  • 通过提示信息可以的得知配置已经保存成功
  • 接着重新启动设备

这一次我们不打断uboot,让uboot正常引导系统,当硬件初始化完成,开始载入系统时我们就立刻获得了shell会话

image-20210223145003063.png

Last modification:February 23, 2021
如果觉得我的文章对你有用,请随意赞赏