2020年5月时,段老师曾对我说过:“目前智能设备这个版块,最紧迫要做的事,就是有一套入门的指引。”
当时我答应了段老师会认真整理一个指引,然后不断丰满此指引中的内容,用各个案例来进一步说明每个细节,最终形成一个相对比较完善和全面的体系框架。
所以,就有了此文。很感谢段老师和gjden大佬等人的帮助,对文章内容进行了多次审阅。接下来就言归正传,开始正题。
目录:
1. 引言 2. 攻击面 3. 有固件逆向分析 3.1 固件的获取 A. 通过设备的云端获取 B. 通过电路板接口获取 C. 通过其他方法直接获取
3.2 固件的内容分析 3.3 固件的程序分析 A. 无操作系统 B. 操作系统与应用程序分开 C. 操作系统与应用程序混合 3.4 固件的调试 A. 使用硬件调试器调试 B. 使用gdbserver调试 C. 使用qemu仿真调试 3.5 固件的重打包 4. 无固件通信分析 4.1 有线/无线网卡通信 4.2 通过4G/2G通信 4.3 通过Bluetooth通信 4.4 通过Zigbee通信 4.5 其他的通信情况 5. 智能设备漏洞分析 5.1 逻辑漏洞 A. 固件后门 B. 认证绕过 C. 加密不当 D. …… 5.2 代码漏洞 A. 栈溢出漏洞 B. 整数溢出漏洞 C. 命令注入漏洞 D. …… 6. 小结
既然我们要研究智能设备,那么“智能设备”究竟是什么?可能我们暂时无法给“智能设备”一个准确而严谨的定义,但我们日常见到的那些能够联网通信的,与传统设备相比,功能更丰富的电子设备,都可以被当作一个“智能设备”而成为我们的研究目标。或许叫“IoT设备”更贴切一些。
一个常见的智能设备系统通常包含三部分:手机端,云端和设备端。采用这种架构的智能设备系统,例如我们经常使用的共享单车,设备端是自行车本身,手机端就是Android/ iOS手机中的app,云端就是共享单车的服务器。此外,有些系统的设备端除了设备本身之外,还包含一个网关,例如智能门锁中的门锁设备和配套网关。常见情况下,智能设备系统三端的关系图如下:
图1-1 智能设备系统
我们要研究智能设备的安全问题,具体讲就是研究手机端,云端和设备端,这三端中出现的安全问题。在《智能设备》板块中,我们的重心肯定不是研究手机端和云端,关于Web、Android、iOS的问题还是交给专门的同事去研究比较好。但我们有必要掌握一些关于云端和手机端的基本知识,如果一丁点Android/iOS的app逆向都不懂,那分析智能设备也会挺费劲的。
在上一章中,我们已经明确要研究的是“智能设备”中“设备端”的问题,那么接下来我们就看一下智能设备中可行的攻击面。智能设备是为我们服务的,我们在使用智能设备中或多或少的都会与智能设备产生通信,其通信方式就是智能设备暴露在外的通信接口。常见的通信接口可以归纳如下表:
表2-1 智能设备的常见通信接口
上表中列出的项目,仅仅是一些常见的应用层通信协议。一方面,我们整理得并不是全面,仅仅是把常见的列出来;另一方面,我们暂时不关心通信协议本身的安全问题,例如,我们目前不考虑智能设备tcp协议的实现代码是否存在安全问题。
事实上不仅仅正常使用智能设备时,需要通过表2-1归纳的各种通信接口,在攻击者进行漏洞攻击时,同样是通过上述的接口完成。比如说,常见路由器的各种RCE漏洞都是通过攻击监听http接口的程序、或者攻击监听udp接口的某个程序。
因此,不管是为了挖掘漏洞,还是为了分析漏洞,我们都有必要研究一下监听这些接口的程序,确定这些程序是如何处理收到的数据。所有这些我们打算研究和分析的程序,都在智能设备的固件中。所以,我们在展开研究之前,先要拿到固件内容。当然,我们不排除有些漏洞是不需要研究固件,直接分析通信内容就可以复现的,但多数情况还是离不开固件。在接下来的第三章和第四章中,将专门讨论固件分析和通信分析。
上一章中我们提到了固件,那么固件又是什么?其实简单说,固件就是运行在设备端的程序和数据,一方面固件和底层MCU等硬件直接打交道;另一方面固件还要完成智能设备的各种逻辑功能。
固件一般会保存在2个位置,其一是外置的Flash存储器中,其二是MCU内置的Flash存储器中。存储在不同位置的固件,可以使用不同的提取方法,我们在这里列出一些常见的方法供各位读者参考。
有些设备的固件是可以直接在官网下载到的,如TP-Link、D-Link路由器等。关于这两个路由器,我们不但可以下载到固件,还可以下载到一部分代码,因为他们采用了OpenWRT嵌入式Linux操作系统,需要遵循GPL开源协议。关于在云端直接下载固件的案例,笔者正在整理,估计要 8月或者9月才能整理出来。
有些设备的固件是不会让你直接下载的,这时可以尝试监听通信获取下载地址。但这招并不是每次都有效,毕竟通信内容可能是加密的,或者下载到的固件是增量更新,那我们只能再想别的办法。关于监听通信获取固件下载的案例,可以参考果加智能门锁分析的那篇帖子,链接如下:https://bbs.pediy.com/thread-259530.htm 。
每个MCU都有其对应的调试方法,通过专用的硬件调试器和调试接口即可调试MCU中的程序,比较常用的调试器有J-Link、ST-Link等,通过这些调试器也可以进行固件提取,例如J-Link调试器支持两种调试接口JTAG接口和SWD接口,接通J-Link调试器后,可以使用savebin等指令就读取并保存Flash中的内容。但这招也并不是每次都有效,因为很多设备的发行版本都会设置Readout Protection(RDP),导致无法提取。关于通过调试接口提取固件的案例,笔者打算整理,但估计要9月以后才真正开始。
UART通信接口是一种被广泛使用的通信接口,绝大部分MCU都是支持的。但不同设备通过UART接口提取固件的方法也各有不同,例如,有些设备可以通过UART引导启动处于其他Flash中的固件,进而完成主Flash中的固件提取。关于通过UART接口提取固件的案例,笔者打算整理,但不知道啥时候能发出来。
当设备端使用外置Flash存储器时,可以将Flash芯片从电路板上取下来,使用热风枪或者电烙铁均可,然后通过支持读写该Flash的编程器来读取Flash中的固件内容。此外,有些BGA封装的Flash芯片可能需要更专业的设备和技术才能拆下来。关于通过Flash编程器提取固件的案例,可以参考海康萤石智能网关分析的那篇帖子,连接如下:https://bbs.pediy.com/thread-261679.htm 。
针对于内置Flash存储器,也有一些其他方法,例如利用芯片的漏洞或固有问题等。比如说,STM32F0系列MCU处于RDP level 1时,可以利用CVE-2017-18347以完成内置Flash中的固件提取。此外,芯片就是封装完备的电子元件,用芯片级的方法打磨腐蚀芯片封装,然后用显微镜和探针读写Flash的内容,这样也可以帮助提取固件,但需要专业设备。关于这些其他方法的案例,笔者打算整理,但不知道啥时候能发出来。
当我们顺利拿到固件之后,往往获得是一个二进制的文件,但是对于此文件道理包含什么内容还尚不明确。此外,我们获取此固件文件的方式不同,也会对该文件有所影响。例如,我们通过网页下载固件文件,那么文件中可能会包含一些烧录配置信息,此信息会被烧录程序读取并以此配置烧录固件;若是通过直接读取外置Flash内容而获取的固件文件,那么这个文件就是此Flash中保存的所有内容,除了固件之外,可能还包含一些设备端在运行时生成的需要保存在Flash中的其他数据。
在分析固件内容时,有一个很常用的工具:binwalk,其官方的github地址是:https://github.com/ReFirmLabs/binwalk 。通过binwalk工具,可以快速发现并提取固件文件中包含的各种内容,如lzma压缩数据、squashfs文件系统等。binwalk的工作方式就是在固件文件中查找标志字节(magic number),也称为特征码,如PE文件的前两个字节是’MZ’等,通过这些标志字节就可以辨认出固件中内容,如lzma压缩数据等。识别完成之后,就可以将这部分数据单独取出并解压缩。
当binwalk工具什么都没有分析出来时,那么常见情况下有以下几种情况:A. 固件文件就是个可执行文件,不存在其他压缩数据,所以什么都没识别出;B. 固件文件被加密了或者固件本身是增量更新的数据,导致binwalk什么都没有识别出来;C. 固件中的magic number被抹掉了,这同样会导致binwalk分析失败。具体怎么解决这三情况,就要具体问题具体分析了。
binwalk工具在提取文件时要依赖很多第三方工具,如提取jffs2文件系统时需要依赖https://github.com/sviehb/jefferson 工具,有些工具很久不更新了,只能在python2环境下运行,所以目前安装binwalk工具还是建议使用python2环境,以后有更好的适配时再切换成python3不迟。关于binwalk工具的安装可以参考其官方的步骤;关于使用binwalk工具的案例,基本出现在所有分析文章中,就不再单独整理了。
完成固件内容的提取之后,就可以开始逆向分析固件中的程序了,常用的分析工具有IDA、Ghidra等。与Windows逆向、Android逆向不同的是,智能设备的MCU是多种多样的,这就意味着我们在进行逆向工作时会见到各种各样的指令集,在家用设备中最常见的有x86、ARM和MIPS等。我们没有必要为了逆向固件而专门去学习指令集的所有细节,这有些舍本逐末。一般情况下,我们能够理解反汇编得到的代码段的大致含义就好,只有我们在较真一些加密、解密算法或者某些关键代码段时,才有必要一行不漏地看每个汇编助记符。
接下来要根据智能设备中是否有操作系统,以及操作系统的不同而进行分类讨论了。但不管怎么分类,归根结底还是要看汇编代码,所以多看多分析才能不断提高。
无操作系统(NoOS, No Operating System),NoOS这个词是笔者从TI官方提供的STM32 SDK中摘抄过来的,并没有严格考证过其出处。操作系统往往起到一个承上启下的作用,应用程序运行在操作系统之上,操作系统提供了内存管理、线程调度等核心功能,应用程序只要熟悉操作系统提供的各种API,即可完成开发工作。
如果智能设备中没有运行操作系统,那么开发者就需要直接操作底层硬件设备,这就导致我们在逆向过程中经常会看到直接操作物理内存,以及操作被映射到内存地址的各种外设,如GPIO等。此时,我们在进行逆向分析时,需要不断地参考MCU的芯片手册以帮助理解程序。关于NoOS的智能设备分析案例,可以参考:https://bbs.pediy.com/thread-259530.htm 。
操作系统与应用程序分开就是指,操作系统与应用程序被编译成不同文件。这个分类中最常见的就是嵌入式Linux操作系统,有很多优秀的操作系统都是基于嵌入式Linux实现的,比如OpenWRT、RTLinux等。当作系统与应用程序分开时,那么逆向工作就会相对简单,只需要单独逆向我们关注的某一个程序即可。
此外,操作系统和应用程序分开之后,在很多其他方面也提供了便利,比如说我们可以上传其他的可执行文件至操作系统中,使用这些程序用以帮助分析和调试。关于操作系统与应用程序分开的案例,可以参考海康萤石智能网关分析的那篇帖子,连接如下:https://bbs.pediy.com/thread-261679.htm 。
操作系统与应用程序混合就是指,操作系统和应用程序被编译成了同一个可执行文件。这个分支下同样有很多优秀的操作系统,例如FreeRTOS、ThreadX等。笔者在撰写本章节时,原计划是每个操作系统都整理一个案例用于说明情况,但一方面工作量确实很大,另一方面他们都是大同小异的关系,所以就将这几个操作系统暂时归位了同一个类别,3.3章节总共3个小节的分类方式。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2020-9-21 17:50
被胡一米编辑
,原因: