上期讲到了物联网终端关于硬件方面的一些基础知识,接下来我们再来聊聊固件。
一、固件概述
固件因存储在硬件电子器件中,并且在以前一般不会对其进行更改,所以有固化在硬件中的软件的含义。随着技术的不断发展,修改固件以适应不断更新的硬件环境成了用户们的迫切要求,所以,可重复写入的可编程可擦除只读存储器EPROM、EEPROM和Flash出现了。这些芯片是可以重复刷写的,让固件得以修改和升级。
固件在物联网终端设备中有举足轻重的作用,可以说是终端设备的灵魂,终端设备没有固件就如同没有了操作系统的电脑一样无法正常运行。
作为设备中非常重要的数据,固件会被写入像EEPROM和Flash等非易失性存储器件中,以确保其不会被意外删除,而固件作为一种存储在硬件中的软件,当设备通电时,固件是第一个运行的部分,它无需通过API、操作系统或设备驱动程序即可运行,从而为设备提供所需的指令和指示,以便与其他设备进行通信或按预期执行基本任务和功能。
二、固件、驱动和应用软件的对比
有很多同学对固件、驱动以及普通应用程序之间有什么异同不太清楚,这里来进行说明一下:
相似处
- 三者都是广义上的软件
差异性
- 固件和应用软件
- 固件提供帮助硬件启动、与其他设备通信以及执行基本输入/输出任务的指令;应用软件安装在设备上用于人机交互,例如浏览互联网、文字处理、听音乐和视频会议
- 固件和驱动程序
- 固件直接存储在硬件设备上;驱动程序安装在设备的操作系统中
- 固件可以自行启动;驱动程序得依赖于操作系统运行
- 固件是指引硬件设备如何运行;驱动程序则是充当操作系统和硬件之间的信使的软件,来帮助用户更好的去操作硬件
三、物联网终端设备固件结构
3.1 总体构成
其实固件在我们生活和工作中处处可见。我们知道固件是在设备上电时第一个运行的软件,这里对Windows有所了解的同学可能会想到BIOS(简单概述:BIOS 位于计算机主板的芯片上,在设备通电时,发出指令使设备的操作系统能够加载)。BIOS的确是一种固件,较新的UEFI也是固件。除此之外,像照相机、遥控器、智能门锁、智能穿戴设备、路由器、摄像头等等设备中都存有固件。
对于物联网终端设备,把上电后来引导设备正常启动的程序称为bootloader,但由于物联网终端一般体积较小,为了节省成本,各家厂商并不会只将bootloader这一个程序单独打包为一个固件存入一个电子器件中,常见的是会把系统内核程序、文件系统等一并打包到固件中。所以现在所说的固件会有很多形式,有的可能只是简单的硬件配置程序,文件很小,有的固件则可能包含了操作系统等数据。
嵌入式Linux、嵌入式Windows内核以及各种实时操作系统(RTOS)的区别,以及厂商在集成、封装工艺等方面的区别,导致物联网终端设备的固件在格式上产生了很大的差异。
如常见的基于嵌入式Linux内核的设备,是将bootloader、内核和文件系统(可能会存在多种文件系统,如基于嵌入式Linux内核的OpenWRT系统的设备)以特定格式打包组合在一起成为一个固件,进行解包后,会是几块独立的文件数据;而像RTOS类型的设备,它的固件则是在编译环节就将上述内容融合在了一起成为一个整体的文件,后续所有数据的使用都需要通过偏移来寻找。
内核 | 操作系统 | 固件区别 |
嵌入式Linux | Linux | 常见的是将bootloader、内核和文件系统以特定格式打包组合在一起成为一个固件 |
嵌入式Linux | OpenWRT | 和上述一样,但常见的是存在多文件系统 |
rtos | VxWorks | 在编译环节将上述数据编译成一个整体 |
3.2 Bootloader
bootloader是设备上电或复位后运行的一段小程序。这段程序将系统的软硬件环境带到一个合适的状态,为最终调用应用程序准备好正确的环境,具体作用主要包括完成处理器和周边电路正常运行所需要的初始化工作、RAM初始化、内核镜像调用、内核解密、文件系统解密等。
对于嵌入式系统,bootloader是基于特定硬件平台来实现的。因此,几乎不可能为所有的嵌入式系统建立一个通用的bootloader,不同的处理器架构都有不同的bootloader。bootloader不但依赖于CPU的体系结构,而且依赖于嵌入式系统板级设备的配置。对于2块不同的嵌入式板而言,即使它们使用同一种处理器,要想让运行在一块板子上的bootloader程序也能运行在另一块板子上,一般也都需要修改bootloader的源程序进行适配。
但大部分bootloader仍然具有很多共性,某些bootloader也能够支持多种体系结构的嵌入式系统。例如,U-Boot就同时支持PowerPC、ARM、MIPS和X86等体系结构,支持的板子有上百种。下图展示了常见的bootloader的基本信息和对不同架构体系的支持情况。
在物联网终端设备中,常见的bootloader包括Redboot、u-boot、barebox等,但由于现在多数bootloader都是开源项目,所以存在安全问题的可能性不大,不过我们可以通过对bootloader的分析,获取一些系统信息,为后续的设备研究做好铺垫。
3.3内核
内核,是操作系统的核心。是基于硬件的第一层软件扩充,提供操作系统的最基本的功能,是操作系统工作的基础,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。
常见的Linux内核映像文件有两种:一种是非压缩版本,叫Image;另一种是它的压缩版本,叫zImage。zImage是Image经过压缩形成的,所以它的大小比Image小。为了能使用zImage这个压缩版本,必须在它的开头或者定制的bootloader中加上解压缩的代码,将zImage 解压缩之后才能执行,因此它的执行速度比Image要慢。但考虑到嵌入式系统的存储容量一般都比较小,内核要常驻内存,采用zImage可以占用较少的存储空间,因此牺牲一点性能上的代价也是值得的,所以一般嵌入式系统均采用压缩的内核映像文件,即zImage。
内核由bootloader进行加载,当bootloader完成硬件环境初始化后,便会进入内核映像加载阶段。常见的是先将内核映像文件复制SDRAM环境中,然后跳转到它的入口点即可调用内核,但在此之前,bootloader需要给内核设置启动参数,因为内核并不是对于所有的开发板都能完美适配,此时对于硬件的环境并不清楚,所以,要想顺利启动内核,bootloader必须要给内核传递一些必要的信息来告诉内核当前的环境,这些信息主要包括CPU ID、内存的起始地址、内存大小、内核启动后挂载文件系统的方式等。
3.4文件系统
当bootloader完成内核的加载后,系统内核便会加载文件系统,完成设备的完整启动。
文件系统是操作系统用于明确存储设备或分区上的文件的方法和数据结构,像Windows操作系统常用的文件系统有FAT、NTFS、HPFS等,Linux操作系统常用的文件系统有ext3、ext4等。对于物联网终端设备,其硬件资源在存储能力以及内存等方面有诸多限制,所以常见的一般都是压缩文件系统,如基于Linux内核操作系统的文件系统有SquashFS、JFFS2、YAFFS2等,基于rtos的实时操作系统常见的文件系统有SPIFFS和LittleFS。
设备类型 | 常见文件系统 |
Windows主机 | FAT、NTFS、HPFS等 |
Linux主机 | ext3、ext4等 |
物联网终端设备(Linux内核) | SquashFS、JFFS2、YAFFS2等 |
物联网终端设备(RTOS内核) | SPIFFS、LittleFS等 |
以基于Linux内核的物联网终端设备为例,较为常见的文件系统是SquashFS和JFFS2。SquashFS文件系统是一种只读压缩文件系统,可以使用unsquashfs等开源工具从中提取数据,而JFFS2是一种可写的日志结构文件系统。
根据文件系统的特性,不同操作系统可灵活搭配这些文件系统达到不同的效果,如有些设备不允许用户对其进行灵活配置,所以往往采用单SquashFS文件系统;而有些开源的操作系统为了给到用户自己做更灵活的深层次配置,往往会采用多文件系统来实现这个效果,像OpenWRT常使用SquashFS等只读文件系统来存储busybox、iptables等基础文件。由于自定义配置这些文件的意义不大,并且误删或损毁后设备可能无法正常运行,所以不允许用户自己随意定制。而在应用软件层面上给到了用户极大程度的可定制化功能,往往是通过使用可写文件系统来实现这些定制化功能,如安装其他软件包等。
本章结语
本期《物联网终端安全入门与实践》之了解物联网终端部分已完全结束,固件对于物联网终端设备的安全研究极为重要,特别是文件系统这一块数据。由于固件中的程序包含了部分厂商自研程序,暴露出了一定的攻击面,存在潜在的安全风险。因此我们后续针对设备的安全研究很大一部分时间和精力会聚焦在固件及其文件系统(比如固件的仿真、固件文件系统的提取、固件文件系统的脆弱性分析等)。