IoT安全入门04

第四章 物联网固件层安全讲解

0x01 文件系统详解

1. 文件系统简介

1.1 文件系统简介

文件系统是操作系统用于明确存储设备(常见是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。

image-20220823155713987

根文件系统简介

根文件系统首先是内核启动时所mount的第一个文件系统,内核代码影像文件保存在根文件系统中,而系统引导启动程序会在跟文件系统挂在之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。

image-20220823155921906

文件系统实现

FileSystem

常见嵌入式文件系统

FileSystemCom

df -ahT:查看当前系统的所有文件系统

LinuxVFS

2. 常见的文件系统

2.1 常见的文件系统-Flash

jffs/jffs2:

  • JFFS文件系统最早是由瑞典Axis Communications 公司基于Linux2.0的内核为嵌入式系统开发的文件系统。JFFS2是RedHat公司基于JFFS开发的闪存文件系统,最初是针对RedHat公司的嵌入式产品eCos开发的嵌入式文件系统。
  • Jffs2:日志闪存文件系统版本2 (Journalling Flash FileSystem v2)
    主要用于NOR型闪存,基于MTD驱动层,特点是:可读写的、支持数据压缩的、基于哈希表的日志型文件系统,并提供了崩溃/掉电安全保护,提供“写平衡”支持等
  • 缺点:当文件系统已满或接近满时,因为垃圾收集的关系而使jffs2的运行速度大大放慢

image-20220823160521074

yaffs/yaffs2:Yet Another Flash File System

  • yaffs/yaffs2是专为嵌入式系统使用NAND型闪存而设计的一种日志型文件系统。
  • 与jffs2相比,它减少了一些功能(例如不支持数据压缩),所以速度更快,挂载时间很短,对内存的占用较小。
  • yaffs/yaffs2自带NAND芯片的驱动,并且为嵌入式系统提供了直接访问文件系统的API,用户可以不使用Linux中的MTD与VFS,直接对文件系统操作。当然,yaffs也可与MTD驱动程序配合使用
  • yaffs与yaffs2的主要区别在于,前者仅支持小页(512 Bytes)NAND闪存,后者则可支持大页(2KB)NAND闪存。同时,yaffs2在内存空间占用、垃圾回收速度、读/写速度等方面均有大幅提升

image-20220823160831338

Cramfs:Compressed ROM File System

  • Cramfs是Linux的创始人Linus Torvalds参与开发的一种只读的压缩文件系统。它基于MTD驱动程序。
  • 在cramfs文件系统中,每一页(4KB)被单独压缩,可以随机页访问,其压缩比高达2:1,为嵌入式系统节省大量的Flash存储空间,使系统可通过更低容量的FLASH存储相同的文件,从而降低系统成本。
  • Cramfs文件系统以压缩方式存储,在运行时解压缩,所以不支持应用程序以XIP(eXecute In Place,芯片内执行)方式运行,所有的应用程序要求被拷到RAM里去运行。
  • 它的速度快,效率高,其只读的特点有利于保护文件系统免受破坏,提高了系统的可靠性。
  • 缺陷:它的只读属性同时又是它的一大缺陷,使得用户无法对其内容对进扩充

squashfs:

  • squashfs可以将整个文件系统或者某个单一的目录压缩在一起,存放在某个设备,某个分区或者普通的文件中。如果你将其压缩到一个设备中,那么你可以将其直接mount起来使用;而如果它仅仅是个文件,你可以将其当为一个loopback设备使用。
  • 特点:
    • 数据(data),节点(inode)和目录(directories )都被压缩。
    • 保存了全部的32位UID/GIDS和文件的创建时间. (注: cramfs是8位,没有创建时间)。
    • 支持多达4G的文件系统. (cramfs是16M)。
    • 节点和目录都是高度压缩,而且都是存储在字节边界(packed on byte boundaries)
    • squashfs可以允许块大小(block size)达32Kb(1. x)和64kb(2.x), 这样可以达到比4K块大小更大的压缩率。
    • squashfs 2引进了碎片块(fragment blocks)的概念: 一种将许多比块size小的文件存储在一个块中,以达到更大的压缩率

UBIFS

  • nokiaI程师在the university of Szeged大学帮助下开发的新的Flash
    filesystem。UBIFS可以认为是JFFS2文件系统的下一代。UBIFS文件系统是专门为大容量FLASH嵌入式移动设备设计的,挂载UBIFS文件系统必须有mtd接口,而普通的PC机通常都不用mtd管理磁盘。
  • UBIFS通过子系统UBI处理与MTD device之间的动作。与JFFS2一样,UBIFS建构于MTD device之上,因而与一般的block device不兼容。
  • UBIFS及其使用的UBI子系统,是一种用在大容量flash,上的文件系统。
  • 特点:可扩展性,快速mount,write-back支持,异常unmount适应度,快速I/0,on-the_ flight compression,可恢复性,完整性

2.2 常见的文件系统-内存

Ramdisk

  • Ramdisk是将一部分固定大小的内存当作分区来使用。它并非一个实际的文件系统,而是一种将实际的文件系统装入内存的机制,并且可以作为根文件系统。将一些经常被访问而又不会更改的文件(如只读的根文件系统)通过Randisk放在内存中,可以明显地提高系统的性能。
  • 在Linux的启动阶段,initrd提供了一套机制,可以将内核映像和根文件系统一起载入内存。

ramfs/tmpfs

  • Ramfs是Linus Torvalds开发的一种基于内存的文件系统,工作于虚拟文件系统(VFS)层,不能格式化,可以创建多个,在创建时可以指定其最大能使用的内存大小。
  • Ramfs/tmpfs文件系统把所有的文件都放在RAM中,所以读/写操作发生在RAM中,可以用ramfs/ tmpfs来存储一些临时性或经常要修改的数据,例如/ tmp和/var目录,这样既避免了对Flash存储器的读写损耗,也提高了数据读写速度。
  • Ramfs/ tmpfs相对于传统的Ramdisk的不同之处主要在于:不能格式化,文件系统大小可随所含文件内容大小变化。
  • Tmpfs的一个缺点是当系统重新引导时会丢失所有数据。

2.3 常见的文件系统-网络文件系统

网络文件系统NFS(Network File System)

  • NFS是由Sun开发并发展起来的一项在不同机器、不同操作系统之间通过网络共享文件的技术。在嵌入式Linux系统的开发调试阶段,可以利用该技术在主机上建立基于NFS的根文件系统,挂载到嵌入式设备,可以很方便地修改根文件系统的内容。

2.4 常见的文件系统-虚拟文件系统

procfs

/proc 文件系统是一个虚拟文件系统,通过它可以使用一种新的方法在Linux内核空间和用户间之间进行通信。在**/proc** 文件系统中,我们可以将对虚拟文件的读写作为与内核中实体进行通信的一种手段,但是与普通文件不同的是,这些虚拟文件的内容都是动态创建的。

# -t 是指定文件系统类型,第二个参数是挂载设备,因为是内核设备,所以写none,第三个参数是挂载目录

mount -t proc none /proc

# 或者在 /etc/fstab条目下添加

none /proc proc defaults 0 0

在fstab下添加会在开机以后自动挂载

tmpfs

  • tmpfs ( temporary filesystem )是Linux特有的文件系统,标准挂载点是/dev/shm,默认大小是实际内存的一半,如下图所示。当然,用户也可以将tmpfs挂载在其他地方。tmpfs可以使用物理内存,也可以使用swap交换空间。
  • tmpfs有些像虚拟磁盘( ramdisk),但ramdisk是一个块设备,而且需要一个mkfs之类的命令格式化后才能使用。而tmpfs是一个独立的文件系统,不是块设备,只要挂载,就可以立即使用。
  • tmpfs特点:
    • 临时性
    • 快速读写能力
    • 动态收缩

0x02 常见嵌入式操作系统详解

1. 操作系统简介

1.1 操作系统简介

操作系统(英语: Operating System,,缩写: OS)是一组主管并控制计算机操作、运用和运行硬件、软件资源和提供公共服务来组织用户交互的相互关联的系统软件程序,同时也是计算机系统的内核与基石。操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入与输出设备、操作网络与管理文件系统等基本事务。操作系统也提供一个让用户与系统交互的操作界面。

image-20220827101854708

1.2 操作系统的作用

  • 用户界面(GUI)
  • 进程管理
  • 内存管理
  • 文件系统
  • 网络通信
  • 设备管理
  • ······

1.3 操作系统的分类

根据内核结构划分:

  • 微内核(Windows)
  • 宏内核(Linux)

根据用途划分:

  • 通用操作系统(PC等)
  • 嵌入式操作系统(物联网设备等)
  • 专用操作系统(军事、医疗等)

根据信号处理的实时性划分:

  • 实时操作系统(RTOS,Vxworks等)
  • 分时操作系统(Linux等)

2. 嵌入式操作系统

2.1 分时操作系统

分时操作系统(time-sharing):

  • 计算机科学中对资源的一种共享方式,利用多道程序与多任务处理使多个用户可以同时使用一台计算机。
  • 把计算机与许多终端用户连接起来,分时操作系统将系统处理机时间与内存空间按一定的时间间隔,轮流地切换给各终端用户的程序使用。由于时间间隔很短,每个用户的感觉就像他独占计算机一样。分时操作系统的特点是可有效增加资源的使用率。
  • 时间片:是把计算机的系统资源(尤其是CPU时间)进行时间,上的分割,每个时间段称为一个时间片,每个用户依次轮流使用时间片。
  • 分时技术:把处理机的运行时间分为很短的时间片,按时间片轮流把处理机分给各联机作业使用。

Linux

Linux内核(英语: Linux kernel ),是一种开源个类Unix操作系统宏内核。整个Linux操作系统家族基于该内核部署拉传统计算机平台(如个人计算机搭服务器,以Linux发行版个形式)搭各种嵌入式平台,如路由器、无线接入点、专用小交换机、机顶盒、FTA接收器、智能电视、数字视频录像机、网络附加存储(NAS)等。 工作拉平板电脑、智能手机搭智能手表个Android操作系统同样通过Linux内核提供个服务完成自身功能。

image-20220827102615587

Linux目录结构

image-20220827102748745

image-20220827102813726

image-20220827102833128

Linux Kernel

image-20220827102901055

Linux镜像

image-20220827102928902

2.2 RTOS

  • 实时操作系统( Real-time operating system, RTOS ) ,又称即时操作系统,它会按照排序运行、管理系统资源,并为开发应用程序提供一致的基础。

  • 实时操作系统与一般的操作系统相比,最大的特色就是“实时性”,如果有一个任务需要执行,实时操作系统会马上(在较短时间内)执行该任务,不会有较长的延时。这种特性保证了各个任务的及时执行。

  • 设计实时操作系统的首要目标不是高的吞吐量,而是保证任务在特定时间内完成,因此衡量一个实时操作系统坚固性的重要指标,是系统从接收一个任务,到完成该任务所需的时间,其时间的变化称为抖动。可以依抖动将实时操作系统分为两种:硬实时操作系统及软实时操作系统,硬实时操作系统比软实时操作系统有更少的抖
    动:

    • 硬实时操作系统必须使任务在确定的时间内完成。
    • 软实时操作系统能让绝大多数任务在确定时间内完成。
  • 实时操作系统与一般的操作系统有着不同的调度算法。普通的操作系统的调度器对于线程优先级等方面的处理更加灵活;而实时操作系统追求最小的中断延时和线程切换延时。

  • 通常都会有最基础的内核,以及外加上去的模块,像是文件系统、网络协议堆栈和应用、设备驱动程序等模块。

常见RTOS

image-20220827103426742

Vxworks

特点:

  • Vxworks既是一个操作系统,又是一个可以运行的最小基本程序
  • Vxworks有BSP(可以认为是一种低层驱动),可以减小驱动程序的编写过程
  • Vxworks具有强大的调试能力,可以在没有仿真器的情况下,通过串口调试
  • Vxworks具有软件DEBUG功能,可以对软件部分进行模拟调试
  • Vxworks具有丰富的函数库
  • 同时Vxworks自带TCP/IP协议栈

image-20220827103729222

image-20220827103747683

image-20220827103801538

image-20220827103816747

0x03 固件分析环境搭建&&常用分析工具详解

1. 固件分析环境搭建

1.1 系统选择

image-20220828150716964

这里视频里建议用低版本的ubuntu,但是由于自己部署低版本出问题稍微有亿点多,所以这里我用的是Attify安全团队他们部署好的专用于物联网渗透测试和安全分析的一个虚拟机镜像AttifyOS,最新版是基于ubuntu18.04,上边已经提前安装好了很多常用的软件,比较节省时间,当然也可以选择自己部署环境。

Github仓库地址如下:https://github.com/adi0x90/attifyos

1.2 固件提取

image-20220828150923916

dd:

image-20220828150955042

image-20220828151010530

image-20220828151024701

binwalk:

项目地址:https://github.com/ReFirmLabs/binwalk

image-20220828151139212

如果熵为0则未加密,否则,基本上是加密的。(这句好像是错的,请自己查证下)

image-20220828151224948

image-20220828151238625

image-20220828151303726

image-20220828151311354

image-20220828151321716

1.2 二进制应用分析

  1. angr
  2. IDA
  3. Ghidra
  4. Gdb(gef/pwndbg/peda)

angr:

image-20220828151515084

image-20220828151534059

image-20220828151553278

image-20220828151606502

image-20220828151622479

1.4 固件模拟

image-20220828151656506

Qemu

image-20220828151711011

image-20220828151719780

image-20220828151730855

image-20220828151748526

Firmadyne

image-20220828151906926

Firmadyne依赖Binwalk和Qemu

image-20220828151956270

image-20220828152010114

image-20220828152029875

Firmware Analysis Toolkit

image-20220828152213894

提供一些敏感文件查找等等插件

0x04 固件提取详解

1. 固件获取

固件获取是指:手中没有固件,如何获取.bin等类型的固件

1.1 固件

  • 固件(firmware),是一种嵌入在硬件设备中的软件(可简单理解为嵌入式设备的操作系统)。通常它是位于特殊应用集成电路(ASIC)或可变成逻辑器件(PLD)之中的内存或EEPROM或PROM里,有的可以让用户更新。可以应用在非常广泛的电子产品中,从遥控器,计算器到电脑中的键盘、硬盘,甚至工业机器人中都可以看见它的身影。

    image-20230316162638310

1.2 固件获取

  • 官方或售后获取固件
  • 从第三方网站或者专门的人获取固件
  • 抓取升级包的地址
  • 逆向升级软件获取升级接口
  • 使用编程器从Flash中读取固件
  • 通过调试接口,进入设备提取固件
  • 用逻辑分析仪获取信息
  1. 从官网、FTP服务器下载固件或售后处获取固件

    image-20230316163251842

    缺点:官方提供的版本不完整;固件加密或者官网不提供

  2. 从第三方网站下载固件或找专门的人购买

    缺点:提供的型号不完整;需要花钱

  3. 抓取升级包的地址

    工具:HUB/Wireshark/ettercap

    在线升级:抓包,分析固件地址,下载固件

    新老固件通吃:

    • 升级前记录下固件版本和名称
    • 升级后,根据命名规则拼接老固件地址
  4. 逆向升级软件获取升级接口

    厂家提供上位机升级软件(例如:手机端APP),升级软件在升级前,现在上位机解密固件,在传输不加密的固件到设备升级的方式

    逆向分析,解密升级固件部分:抓取数据包

  5. 使用编程器从Flash中读取固件

    将芯片的引脚连接到编程器对应的引脚进行读取

    image-20230316164337031

    步骤:1.拆下芯片;2.使用编程器进行提取;3.将Flash焊回电路板

    在未拆解芯片的情况下提取固件:

    image-20230316164629299

    image-20230316164732373

  6. 通过调试接口,进入U-BOOT提取固件

    获取U-BOOT交互式shell

    image-20230316165002908

  7. 利用逻辑分析仪获取信息

    image-20230316165248154

    image-20230316165322693

2. 固件提取

固件提取是指:已经有固件,如何从.bin等类型的固件中提取数据、文件系统等。

  • strings
  • hexdump
  • file
  • binwalk
  • fdisk
  • dd
  • GUI hex
  1. strings

    strings命令在对象文件或者二进制文件中查找可打印的字符串。字符串是4个或更多可打印字符的任意序列,以换行符或空字符结束。strings命令对识别随机对象文件很有用。命令参数如下所示:

    image-20230316170304582

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ strings test.bin | head -n 20
    signature=wrgac43s_dlink.2015_dir822c1
    dev=/dev/mtdblock/1
    type=firmware
    cs6b
    @!!
    @$<
    @$<
    @8!$
    ···
  2. hexdump

    hexdump命令一般用来查看二进制文件的十六进制编码,但实际上他能查看任何文件,而不只限于二进制文件。命令参数如下所示:

    image-20230316171022481

    示例:

    image-20230317153108851

  3. file命令用来探测给定文件类型。file命令对文件的检查分为文件系统、魔法幻数检查和语言检查3个过程。命令参数如下:

    image-20230316171208266

    示例:

    1
    2
    3
    4
    $ file test.bin 
    test.bin: data
    $ file test_firmware
    test_firmware: Squashfs filesystem, little endian, version 1024.0, compressed, -3519191473859854336 bytes, 805896192 inodes, blocksize: 512 bytes, created: Thu Jun 4 12:04:42 2020
  4. binwalk是一款快速、易用,用于分析,逆向工程和提取固件映像的工具。简单易用,完全自动化脚本,并通过自定义签名,提取规则和插件模块,很重要的一点就是可以轻松地拓展。

    常用参数:

    1
    2
    3
    -e, --extract                Automatically extract known file types
    -M, --matryoshka Recursively scan extracted files
    -E, --entropy Calculate file entropy
  5. fdisk是一个创建和维护分区表的程序,它兼容DOS类型的分区表、BSD或者SUN类型的磁盘列表。

    fdisk -lfdisk -lu(- u 选项指定以segment段标记分区大小,而不是默认的”cylinders(柱面)”)

    image-20230317101454236

    image-20230317101435568

  6. dd命令用于读取、转换并输出数据。dd可以从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。

    示例:

    1
    2
    3
    4
    $ dd skip=1376404 if=test.bin bs=1 of=test_firmware
    记录了5386240+0 的读入
    记录了5386240+0 的写出
    5386240字节(5.4 MB,5.1 MiB)已复制,5.94871 s,905 kB/s
  7. GUI hex

    image-20230317101530509

手动方式提取固件文件系统

首先我们使用hexdump命令,对获取到的固件进行文件系统签名的检索:

1
2
$ hexdump -C test.bin |grep "sqsh\|hsqs\|sqlz\|qshs\|tqsh\|hsqt\|shsq"
00150090 00 00 00 00 68 73 71 73 30 09 00 00 5e d8 e3 5a |....hsqs0...^..Z|

在地址00150090(16进制)处发现SquashFS文件系统的签名(即hsqs)。由此可以确定这个固件的文件系统是小端的SquashFS。

接下来使用dd命令将从 00150090 地址开始的内容提取出来,需要注意的是我们要将其转化成十进制的表示形式(1376400),并且由于hsqs前面有4字节的填充,所以真正提取是,要在 00150090 的基础上加 4 (即1376404)

计算好地址后,可以使用dd命令提取,其命令格式为:

1
dd if=输入文件名 bs=读入/输出大小 skip=从文件头跳过块数 of=输出文件名
1
2
3
4
$ dd skip=1376404 if=test.bin bs=1 of=test_firmware
记录了5386240+0 的读入
记录了5386240+0 的写出
5386240字节(5.4 MB,5.1 MiB)已复制,5.94871 s,905 kB/s

接下来执行file命令,查看提取出的文件系统时候正确

1
2
$ file test_firmware 
test_firmware: Squashfs filesystem, little endian, version 1024.0, compressed, -3519191473859854336 bytes, 805896192 inodes, blocksize: 512 bytes, created: Thu Jun 4 12:04:42 2020

可以看到这个固件文件系统为小段的Squash FS文件系统

接下来执行 unsquashfs 命令来提出整个文件系统

1
2
3
4
5
6
7
8
9
10
11
$ unsquashfs test_firmware 
Parallel unsquashfs: Using 8 processors
2246 inodes (2292 blocks) to write

[===========================================================| ] 2225/2292 97%

created 1987 files
created 106 directories
created 192 symlinks
created 0 devices
created 0 fifos

至此,我们已经成功地提取到了Squash FS格式的固件,其中提取的文件夹名称为squash-root

接下来执行 ls 命令,预览该文件夹下的各个文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ls -ll squashfs-root/
总用量 48
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 bin
drwxrwxr-x 9 guoxb guoxb 4096 Apr 28 2018 dev
drwxrwxr-x 13 guoxb guoxb 4096 Apr 28 2018 etc
lrwxrwxrwx 1 guoxb guoxb 9 Apr 28 2018 home -> /var/home
drwxrwxr-x 10 guoxb guoxb 4096 Apr 28 2018 htdocs
drwxr-xr-x 3 guoxb guoxb 4096 Apr 28 2018 lib
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 mnt
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 proc
drwxr-xr-x 2 guoxb guoxb 4096 Apr 28 2018 sbin
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 sys
lrwxrwxrwx 1 guoxb guoxb 8 Apr 28 2018 tmp -> /var/tmp
drwxrwxr-x 5 guoxb guoxb 4096 Apr 28 2018 usr
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 var
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 www

使用工具提取

采用 binwalk 工具自动提取文件系统,命令如下:

1
binwalk -Me test.bin

image-20230317161003457

使用 binwalk 工具提取出的文件系统以 “_固件名.extracted”命名。打开 _test.bin.extracted 文件夹,可以看到 squashfs-root 文件夹,里面存放的就是获取的文件系统。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ls -ll _test.bin.extracted/squashfs-root
总用量 48
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 bin
drwxrwxr-x 9 guoxb guoxb 4096 Apr 28 2018 dev
drwxrwxr-x 13 guoxb guoxb 4096 Apr 28 2018 etc
lrwxrwxrwx 1 guoxb guoxb 9 Apr 28 2018 home -> /var/home
drwxrwxr-x 10 guoxb guoxb 4096 Apr 28 2018 htdocs
drwxr-xr-x 3 guoxb guoxb 4096 Apr 28 2018 lib
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 mnt
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 proc
drwxr-xr-x 2 guoxb guoxb 4096 Apr 28 2018 sbin
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 sys
lrwxrwxrwx 1 guoxb guoxb 8 Apr 28 2018 tmp -> /var/tmp
drwxrwxr-x 5 guoxb guoxb 4096 Apr 28 2018 usr
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 var
drwxrwxr-x 2 guoxb guoxb 4096 Apr 28 2018 www

0x05 实际漏洞分析

见另外的专栏 《IoT设备漏洞复现》