物联网

记一次RTEMS系统的固件解密

时间:2010-12-5 17:23:32  作者:网络安全   来源:网络安全  查看:  评论:0
内容摘要:1、前言近期翻阅之前的工作,发现在考勤机系列的安全研究里,有一篇很早就整理好但是没发出来的文章,考虑到相关设备的漏洞已经提交了快两年了,想必该修复的也修复了,设备可能都已经不再生产了。这篇文章我们主要

1、记次解密前言

近期翻阅之前的固件工作 ,发现在考勤机系列的记次解密安全研究里 ,有一篇很早就整理好但是固件没发出来的文章 ,考虑到相关设备的记次解密漏洞已经提交了快两年了,想必该修复的固件也修复了 ,设备可能都已经不再生产了。记次解密这篇文章我们主要聊一下这个设备的固件分析过程,着重描述一下这个设备的记次解密固件解密 。服务器租用

2、固件IoT设备启动概述

IoT设备的记次解密安全分析中,分析人员的固件主要工作是分析设备的逻辑功能及其代码实现 ,从而挖掘设备中的记次解密漏洞 。大多数分析工作是固件从解析固件开始的,如果这一步就不顺利的记次解密话 ,后续可能会更加麻烦。不巧的香港云服务器是,这次的设备在起步阶段就很曲折:固件被加密了 ,并不能直接开始分析。

在此我们再简单总结一下那些常见IoT设备的启动流程 ,如下图所示:

图2-1 IoT设备大致的启动流程

上图大致可以分为4个阶段  :

(1)首先,芯片上电后首先运行的是boot rom ,执行完毕后会跳转到bootloader ,如果设备启用了固件签名 ,那么此处会对固件进行校验;

(2)然后 ,bootloader的免费模板作用类似于PC启动过程的引导,主要功能就是为操作系统的运行做准备工作  ,在复杂的设备中,bootloader会进一步分成多个阶段;

(3)此时 ,操作系统就开始接管对MCU的控制,上图中把操作系统和app分成了两个部分,是为了对标PC方便大家理解,实际上在有些设备里跑的操作系统和app是混合在一起的建站模板 ,甚至可能没有操作系统;

(4)最后,各个app被加载运行 ,开始执行设备的逻辑功能,此处往往是我们想要着重分析的地方 。

上图中 ,bootloader、kernel和app这三个阶段的代码通常是由开发者编写并烧录到Flash中的 ,我们所说的固件指的源码库就是这部分内容。请将此图放在脑海中  ,后续所有工作都将以此图为模板展开分析和叙述 。

PS :本次分享讨论的是固件可以提取但是无法分析的情况,一些由于读保护机制导致固件不被提取的情况,暂不在本篇的讨论范畴中。

3 、情况简介

通过热风枪可以取下Flash芯片,然后通过编程器可以拿到Flash中的云计算固件 ,这些基本功各位一定已经非常熟悉了,这里就不再赘述  。固件文件包含一个FAT12格式的文件系统,可以通过7z工具直接提取出文件系统中的所有内容 ,提取内容截图如下:

图3-1 固件文件系统内容

显而易见,上图中的App文件夹中肯定包含了这款门禁考勤机的主程序 。不过 ,事情肯定没有那么顺利,该文件夹内只有一个文件是可以解析的ELF格式 ,其他文件均不可解析,仅存在可解析文件叫main.bin ,用IDA加载之后  ,内容看起来也有些过于简单,截图如下:

图3-2 main.bin程序内容

上图中 ,虽然函数符号都还在,可以大概推断出函数的作用 ,但是函数看起来很古怪,比如RT_CreateProcess函数内容是下图中的样子 :

图3-3 RT_CreateProcess函数内容

上图中的gFuncEntryKern看起来有点像虚表指针,指向一个函数地址表 ,而这个指针在程序启动时被赋值 。

程序main.bin很短 ,很快就逆完了 ,看起来最后创建了一个新的进程,但除了main.bin程序之外 ,其他程序全都无法解析。即便是main.bin自身,看起来也不太正常,很多函数只有跳转stub ,缺少实质内容,看起来像是PC中加了保护导入表的壳。那么,接下来还是从头开始啃一下这个设备固件吧。

4、kernel分析与解密

按照图2-1所示 ,我们决定先看看bootloader,在解压获得的完整文件系统中,可以看到Product.ini文件 ,从里面能够找到设备的分区表 ,如下图所示  :

图4-1固件分区表

我们此前解压缩得到的FAT12文件系统即为0x20000偏移处,顺便吐槽一下binwalk,为啥binwalk识别不出FAT12文件系统,因为太古老了吗  ?

结合设备上电后串口的输出字符串 ,可以推断出0x20000之前的固件内容即为程序的bootloader ,接下来用IDA载入bootloader部分代码进行分析 ,并结合串口的输出日志 ,可以定位到关键位置,如下图 :

图4-2 bootloader加载kernel文件的过程

上图中,我们根据串口打印出来的字符串来定位程序的关键位置  ,找到了kernel文件其实就是rootfs中的Rtbio_3760_R4502文件 ,且串口打印出来的信息包含了kernel的加载基址和入口地址 ,根据这些信息 ,可以分析kernel文件了 。

使用IDA加载kernel文件之后,IDA导航条如下图所示:

图4-3 直接解析Rtbio文件时的IDA导航条

可以看到此时kernel只被解析出了一小部分,绝大多数内容都是unexplored状态,实际上这部分内容还是处于加密或压缩状态。由于执行流程已经离开bootloader而进入kernel阶段,那么kernel代码肯定是自解密或自解压的  ,这很正常 ,一般情况下linux kernel都是自解压的,但我们没办法直接解压就很奇怪  。通过逆向分析 ,可以在入口点附近看到多处异或解密代码 ,如下图所示 :

图4-4 异或解密代码

上图中 ,0x79E1即为异或解密使用的密钥,类似上图中的异或解密代码在多个位置都有出现 ,原来再自解压之前还有一步自解密过程 ,所以没法直接解压。

耐心分析这些已经解析的代码 ,可以将kernel的启动流程整理为下图所示内容  :

图4-5 kernel文件的解密过程分析

可以看到 ,kernel既包含自解密部分 ,也包含自解压部分。将我们在PC端脱壳的经验用到此处 ,待程序完成自解密和自解压之后 ,dump完整的内存 ,就可以获得可以逆向阅读的kernel二进制文件。

然而我们并没有找到设备调试接口 ,写脱机解密脚本又太繁琐 ,最终选择用QEMU加载kernel,运行其自解密和自解压代码 ,待所有工作完毕之后dump内存 。最后 ,用ida加载dump下来的内核文件 ,就可以看到很多代码和明文的字符串,如下图 :

图4-6 载入并分析dump kernel

在众多字符串中 ,我们还注意到了一个版权信息 ,如下图:

图4-7 版权信息字符串

上图中的版权信息表明此固件可能使用了RTEMS系统 。该系统一款开源的RTOS系统,在github上就可以找到源码 ,代码参考链接 :https://github.com/RTEMS/rtems  。

与我们此前分析云丁鹿客智能门锁那篇很类似,当确定了固件使用的操作系统,那么逆向工作就变得相对简单 ,毕竟有源码可以参考 。通过对比源码,我们可以分辨出大量函数,如open、close、read等。查找这些函数的交叉引用,我们发现了一张很大的函数表,如下图右侧所示 :

图4-8 导出函数表

上图左侧中,我们展示了第3章main.bin的几个函数调用 ,并与右侧kernel中的函数表相互对应。还记得gFuncEntryKern指针吗?看起来这个指针所指向的函数表就是上图右侧中的函数表 。到此 ,依靠这张函数表 ,我们就可以正常分析main.bin程序中的所有函数了 。

到此,bootloader和kernel部分可以告一段落了 ,在开始分析APP之前 ,还有一点需要提一下 ,与传统PC操作系统不同的是 ,该设备并不存在用户态和内核态,kernel和app处于相同的特权级别,所以两者之间可以直接相互调用,不需要上下文的切换 。

5 、app分析与解密

在这个设备固件中  ,除了kernel需要解密解压之外 ,大部分app也是需要解密解压的 。除main.bin之外的程序 ,我们都无法用IDA直接分析  ,就是因为这些程序尚未解密解压 ,而解密解压的关键就在RT_UnzipFile函数中,将该函数的关键位置截图如下 :

图5-1 RT_UnzipFile函数的代码片段

上图中可以看到read 、xor、write等几个关键点,进一步分析可以判定RT_UnzipFile函数同样包含解密和解压这两个过程,异或密钥也没有变化,同样是0x79E1。

根据以上结论我们可以写一个用于解密和解压每个bin文件的脚本,将这些文件恢复成可以分析的ELF格式 。通过脚本,我们将Root_00.bin解密解压 ,root_00.bin就是main.bin在执行最后创建的新进程,用IDA载入解密解压后的ELF文件 ,截图如下 :

图5-2 通过IDA载入解密后的Root_00.bin文件

可以看到,Root_00.bin已经可以分析了。至此 ,我们已经完全理解了这个设备和固件 ,可以随意分析其中的文件了。

6 、固件程序的编写

门禁考勤机作为一个企业的门户 ,往往承担了保卫企业的任务 ,如果门禁考勤机自身变成了打入企业内网的潜伏者 ,想必是件很搞笑的事情。当我们发现了门禁考勤机的漏洞 ,想植入后门时,就可以来阅读一下这第6章的内容 。

虽然与开发传统的Linux程序比较类似,但由于我们没有与之匹配的SDK  ,而只能选择公版ARM编译器  ,所以在开发过程中 ,需要额外注意两点:

(1)系统调用 。通过逆向分析被解密解压的多个固件程序,我们可以确定程序是没有导入表的 ,系统调用是通过gFuncEntryKern和gFuncEntryLibc等几个指针实现。由于我们没有官方SDK,这就导致没办法像常规正向开发一样进行各种系统调用,但是按照shellcode开发思路,直接写汇编肯定是没问题的,最终结果如下图所示:

图6-1 模拟系统调用

上图中  ,我们参考IDA的逆向代码用汇编实现socket、bind等系统调用,具体的逻辑功能代码还是可以照常用C来编写 。

(2)生成文件格式。通过查看其他已经解密解压的多个固件程序,我们可以确定ELF文件是relocatable格式,而不是executable格式的 ,如下图所示:

图6-2 查看main.bin文件格式

因此 ,使用gcc编译程序时,需要指定-c参数,用于生成仅编译和汇编的文件;同时,使用ld链接程序时,指定-r参数 ,用于生成relocatable文件。

完成以上工作后  ,将编译的程序 ,按照第三章的分析做好压缩、加密处理后,并通过某些方式植入设备中 ,设备上电后即可看到程序开始执行 ,tcp回连nc监听的42240端口 ,如下图 :

图6-3 反弹socket通信的进程

上图中  ,我们以发送hello world字符串来说明问题。

当然,我们也可以修改固件中已有的文件 ,例如开机界面的图片,更多内容我们这里不再展示 。

图6-4 修改考勤机开机界面

7、总结

本篇我们着重讨论了一款固件加密的门禁考勤机设备,并借鉴PC端app脱壳的技巧,解密解压了固件中的kernel以及app。其实,本篇分享的固件加密只是各种加密方式的一小类,更常见的情况应该是固件文件完整加密,如果以后有机会我们也会分享那些完整加密的情况 ,感兴趣的可以等我们后续的分享。

copyright © 2025 powered by 创站工坊  滇ICP备2023000592号-21sitemap