APP下载

基于ARM7TDMI架构的嵌入式软件逆向工程分析方法

2022-07-03高洪涛杨栋翔李明程程春

航空维修与工程 2022年6期
关键词:嵌入式软件逆向工程二进制

高洪涛 杨栋翔 李明程 程春

摘要:软件逆向工程对于国外先进技术引进、恶意代码检测等有重要意义。随着嵌入式技术的高速發展,以ARM架构微处理器为核心的嵌入式系统在国防、通信、自动控制等关键领域得到了普遍应用。本文以某型航空发动机数据采集单元(DCU)的二进制程序逆向为例,阐述了一种基于ARM7TDMI架构的嵌入式软件逆向分析流程和方法。结果显示,本方法可以对DCU软件的全部子函数和全局变量功能进行有效逆向分析,可以作为功能分析及维护保障的重要依据。

关键词:ARM7TDMI;逆向工程;嵌入式软件;二进制

Keywords:ARM7TDMI;reverse engineering;embedded software;binary

0 引言

随着嵌入式系统的飞速发展,在嵌入式领域占据主导地位的ARM架构微处理器在国防电子、电力系统、工业自动化、汽车电子、医疗设备、无线通信等国家关键领域都有十分广泛的应用。 ARM微处理器采用RISC(精简指令集)架构,具有体积小、成本低、能效比高等特点。如图1所示,2003年以前,ARM架构主要包括ARM7TDMI、ARM9E、ARM11等系列。2003年之后,ARM架构主要分为A系列、R系列和 M系列,A系列主要用于顶级主控,如手机、平板电脑的应用处理器;R系列主要用于实时高性能场景,如车辆控制等;M系列主要用于低端应用领域,如消费电子等。

鉴于ARM架构在各个领域的广泛应用,针对ARM架构进行逆向分析具有重要的价值和意义。在民用领域,逆向分析可以帮助检测恶意代码,找出隐藏的后门软件以避免系统被攻击;在军事领域,逆向分析有助于快速学习并引进国外的军事工业技术,发展我国的国产化装备。软件逆向工程按照工程实践,可以分为两类:一类是从已知的软件系统的源码出发,生成对应的系统结构及设计原理、算法思想的文档;另一类软件逆向的研究对象是二进制,即没有源代码的逆向分析。二进制逆向工程按照程序的结构特点,又可以分为结构化二进制逆向和非结构化二进制逆向。前者的研究对象是具有规范的文件格式、包含了程序动态执行与静态分析相关的程序信息,如PE、ELF文件等;后者的研究对象是仅包含数据和指令的固件代码,如bin、hex格式的芯片内置程序等[1]。二进制逆向工程是目前研究的重点。

公开资料显示,目前国内ARM逆向工程的研究重点主要在工具层面,如赵亚新等基于芯片的JTAG接口分析固件的运行机制[2]。解放军信息工程大学蒋烈辉团队在开发ARM的反汇编自动化工具方面做了大量工作,将ARM指令集转为高级语言[3,5];井靖等提出了嵌入式软件的动静态分析机制,以帮助逆向分析软件的调用关系和完整性等[4]。此外,为了方便脱离硬件环境对固件代码进行分析和调试,鲍庆国引入了QEMU技术进行仿真模拟[5]。然而,这些工作只能将二进制文件转为代号或地址表达的高级语言,无法真正解析函数或变量的具体含义。

本文使用目前最流行的逆向分析软件IDA Pro,将二进制文件转换为ARM指令集的汇编语言,在此基础上,以某型发动机数据采集单元(DCU)为研究对象,阐述一种ARM架构嵌入式软件的逆向分析方法,从ARM框架代码入手,结合DCU的已知功能情况,依次逆向分析各个子函数和全局变量的实际含义。

1 ARM7TDMI架构

ARM7系列包括ARM7TDMI、ARM7TDMI-S、ARM720T和扩充了Jazelle的ARM7EJ-S等内核。ARM7TDMI内核支持32位寻址范围,其命名规则为:

● T:支持高密度16位的Thumb指令集;

● D:支持片上调试;

● M:支持64位乘法;

● I:支持EmbededICE观察硬件;

● S:ARM7TDMI的软核版本,编程模型与ARM7TDMI一致。

ARM处理器使用流水线增加处理器指令流的速度,可以同时进行几个操作。ARM7TDMI的流水线分3级,分别是取值、译码和执行。ARM7TDMI处理器使用了冯诺依曼结构进行存储器访问,指令和数据共用一条32位总线,只有装载、存储和交换指令可以对存储器中的数据进行访问。

ARM7TDMI支持7种处理器模式,分别为用户模式、FIQ模式、IRQ模式、管理模式、中止模式、未定义模式和系统模式。各模式的定义和关系如表1所示。

ARM7TDMI具有37个寄存器,包括31个通用的32位寄存器和6个状态寄存器。ARM各模式下可以访问的寄存器如表2所示。

根据各寄存器的作用范围和特点,从ARM7TDMI的汇编代码可以直接进行如下逆向分析工作。

1)栈空间操作分析:寄存器R13通常作为栈指针(SP),当使用R13时,通常是在操作栈空间的内容。

2)子函数调用分析:寄存器R14称为链接寄存器(LR),当要调用子函数时,其用于保存当前函数的下一条指令地址,子函数执行完毕后,将LR寄存器的内容放入R15(PC),返回原函数。因此,汇编语句中有BX LR的地方,一般情况下可以视作子函数的结尾标志。

3)函数传入参数分析:R0~R7可以作为子函数的传入参数,当一个函数中直接使用R0~R7寄存器的内容时,该函数可以视为有传入参数的函数。若R0在函数中第一次使用时是被赋值,则该函数的传入参数肯定是void类型。

4)分支跳转分析:对于BL分支指令,返回指令应为MOV PC,R14或实现类似功能的语句,通过判断该语句可以找到分支结束的标志。

5)中断响应函数分析:针对中止、FIQ、IRQ等异常模式,当退出异常模式时,应有SUBS PC,R14或实现类似功能的语句,通过查找这个语句,可以找到整个代码的中断响应函数。

2 DCU逆向流程

针对DCU的逆向分析流程如图2所示。

硬件电路逆向,主要包括DCU正常工作时的各关键测试点的信号、电平、开关量的测试,以及电路测绘和验证,最终获得DCU的电路原理图及关键测试点的工作状态表,如图3所示。

上位机协议逆向,通过抓取上位机软件与DCU进行通信的数据包,通过改变数据内容查看其影响范围,获取上位机协议相关信息。本阶段获得上位机通信协议。

二进制文件提取,是通过JTAG(DCU的MCU芯片支持JTAG)接口,使用J-Flash软件,直接读取ARM7TDMI芯片的全部Flash内容。二进制文件提取后,将该文件再烧录到空白芯片中,验证空白芯片是否能正常工作。若能正常工作,则说明所有的程序内容都有效的被提取完成。本阶段获得二进制代码文件。

反汇编阶段,使用IDA Pro软件,将二进制代码文件转换为ARM指令集的汇编语言。转换完成后,查看汇编代码的结束位置是否为二进制文件的结束位置。若不是,则说明有無法反汇编的二进制数据。这些数据通常是静态存储的数组或配置文件,应单独保存。本阶段获得DCU的汇编代码。

在软件框架分析阶段,根据上述对ARM7TDMI架构的分析,可以直接从汇编语句中分析出每个子函数的汇编代码起止位置、调用关系、输入参数、返回值,还可以找到DCU的中断响应函数、主函数。本阶段获得DCU的软件总体框架。

类C代码转换,是指将汇编代码逐行转换为类C代码的操作。由于汇编代码中的全局变量和外设寄存器全部用物理地址表示,而局部变量则用通用寄存器表示,在没有分析具体功能之前,只能在类C代码中沿用地址和通用寄存器,类C代码将以C语言的形式表示每个子函数的代码结构。本阶段获得类C代码文件。

子函数与变量逆向,是根据类C代码分别逆向解析各个函数和变量的功能及含义。本阶段获得全局变量与函数功能表。

通信协议分析,是基于函数和变量分析结果从总体上分析DCU的通信协议,以在功能验证阶段通过模拟各种操作指令验证DCU的逆向解析结果是否符合预期。

3 函数及变量逆向分析方法

针对不同的情况,采用函数及变量逆向分析方法,如图4所示。

3.1 中断响应函数上下文分析法

在软件框架分析阶段,可以在汇编代码中找到中断响应函数,再对该函数进行上下文分析,解析出相关的函数和变量。

以定时器中断函数为例,图5为反汇编阶段得到的汇编源码。查看最后一行,结合上述分析,可以确认sub_158函数是一个中断响应函数。由于中断响应函数必然有其相关联的配置,因此在汇编代码中搜索所有sub_158的调用位置,在sub_5320函数中找到了相关的配置代码,汇编源码及类C代码如图6所示。

可以看到,VICVectAddr4寄存器赋值为sub_158函数的地址,结合该部分代码上下文所使用的寄存器,如T1MR0和T1MCR,可以得到:sub_5320为Timer1的初始化配置函数,sub_158为Timer1的中断响应函数,且Timer1的定时时间为2ms。得到定时时间后,进一步分析sub_158内的调用函数,可以逆向解析出更多信息。

3.2 电路功能反向分析方法

通过对电路功能的理解,可以反向解析出软件的含义。

如图7所示,温度传感器芯片为LM20BIM7,输出模拟信号,输出引脚直接连接到MCU的P0.29。因此可以判断P0.29必然配置为ADC采用的AIN2功能。在类C代码中查找ADCR寄存器的配置,发现在sub_4D88中,ADCR寄存器配置为0x210307。因此,sub_4D88必然为ADC的配置函数,且可以看到DCU共配置了AIN0/1/2三个ADC输入。

由于在ARM7TDMI中读取ADC的值,必然会使用ADDR寄存器,因此在类C代码中查找读取ADDR0/1/2寄存器的函数,可以看到是在sub_5E88函数中读取了ADDR寄存器(见图8)。

由此得到sub_5E88函数为ADC读取函数,且地址0x40000014、0x40000016、0x40000018分别为保存ADC结果的全局变量。

3.3 寄存器分析法

通过类C代码中对外设寄存器的读取和配置,可以分析出部分初始化函数和变量信息。以串口配置为例,在类C代码中,有对寄存器的直接读写操作,分析函数或变量与寄存器的关系,可以分析出其含义。

以图9中串口配置为例,按上述电路功能反向分析方法可知sub_501C为串口配置函数。在sub_501C中有switch语句,根据0x4000003F的值,配置U0THR和U1THR寄存器为不同的值。UxTHR寄存器是波特率配置寄存器,则变量0x4000003F中保存的必然是波特率配置参数。同时,由于DCU采用switch语句,可知DCU只支持switch语句中4种case的波特率,即9600bps、19200bps、38400bps、115200bps,且DCU的默认配置为9600bps(default语句)。

3.4 变量赋值与使用分析法

部分全局变量没有与寄存器直接关联,也无法通过电路反向解析获得,但变量只要有赋值和使用,就可以根据变量赋值和使用的上下文信息解析其功能。

以串口数据包超时参数(0x40000D94)为例,0x40000D94只在两个函数中赋值或使用。其中,在串口接收处理函数sub_A48中,有如图10所示的清零操作。

函数sub_A48的输入参数为Uart0/1接收数据结构体,根据采用其他方法解析的结果,地址a+0xA表示Uart0/1已接收到的一帧数据包的长度。通过类C代码可以看到,当已接收到的长度>0时,0x40000D94变量清零,0x40000D90变量置为1。结合其他分析方法,可知0x40000D90变量的含义为串口新数据到达标志。

另一处使用0x40000D94变量的函数为定时2ms处理函数sub_6FD8(见图11)。

在sub_6FD8中,0x40000D98变量在初始化时被赋值为0x28,之后没有其他操作。分析sub_6FD8中的逻辑,当0x40000D90为1时,说明串口收到新的数据,此时0x40000D94开始每隔2ms自加1,直到0x40000D94的值到达0x40000D98,则收到的数据包全部清除。此时,若串口又收到了新数据,则会调用sub_A48,0x40000D94变量清零。通过以上线索可以理解,0x40000D94为数据包超时检测变量,当串口收到一次新数据后,在定时处理中开始计时,超过80ms后认为数据包超时,则之前收到的数据包无效。

3.5 正向代码对比分析法

尽管不同的编译器对同样的C代码编译结果可能稍有差异,但ARM7TDMI芯片的启动代码通常为一段汇编程序,大多数的IDE工具都提供了芯片的模板启动代码。本文使用keil uVision软件提供的startup.s文件与二进制反汇编代码进行对比分析,可以得到DCU项目的各地址空间分配配置。

反汇编代码的起始阶段代码如图12所示,可以看到,在ROM地址0x00000000处,即上电后第一条指令是跳转到loc_58位置。而图13所示为正向代码的第一条指令,对比可知,loc_58为Reset_Addr,loc_40为Undef_ Addr,loc_44为SWI_Addr,loc_48为PAbt_Addr,loc_4C为DAbt_Addr。

进一步对比loc_58的配置(见图14),正向代码与反汇编代码非常接近,但具体配置参数不同,直接对比分析,可以得到:DCU的Stack_Top为0x40003608,用户模式堆栈空间大小为0x400,管理模式堆栈空间大小为0x200,IRQ模式堆栈空间大小为0x400,FIQ模式堆栈空间大小为0x8,中止模式堆栈空间大小为0x8,未定义模式堆栈空间大小为0x8。

此外,对比最后的代码,可以发现,sub_5BB4即为main函数。

4 分析结果

1)全局变量解析结果

DCU代码中,部分使用的全局变量解析结果如表3所示。

2)函数解析结果

DCU中部分函数的解析结果如表4所示。

3)通信协议解析结果

数据帧格式如表5所示;地面模式协议如表6所示;飞行模式通信协议如表7所示。

5 结论

本文阐述了一种基于ARM7TDMI架构的嵌入式软件二进制逆向流程和方法,根据ARM7TDMI架构与ARM指令集的特点以及数据采集器软硬件的功能特性,全面解析软件的全部子函数功能和全局变量含义,这对于充分吸收、学习数据采集器和发动机控制相关技术有重要参考价值。

受限于DCU嵌入式软件中提供的线索,部分变量只有赋值信息,没有被使用,因此采用本文的方法不能逆向分析这些变量的含义。此外,Flash中存储的内容只有有限的几帧数据可以采用本文的方法解析出,这也是本文方法的不足之处。盡管如此,这些没有解析出来的变量或数据并不会从根本上影响DCU的功能分析,从逆向解析结果可以看到,本文的方法可以解析出全部的子函数和全局变量的含义。下一步的工作将基于上述分析结果,对软件进行正向还原,为后续数据采集器国产化正向开发提供参考。

参考文献

[1] 蒋烈辉. 固件代码逆向分析关键技术研究[D]. 郑州:解放军信息工程大学,2007.

[2] 赵亚新,郭玉东,舒辉. 基于JTAG的嵌入式设备固件分析技术[J].计算机工程与设计,2014,35(10).

[3] 周丽娜. ARM反编译中的类型分析技术研究[D]. 郑州:解放军信息工程大学,2010.

[4] 井靖,何红旗,司彬彬,等.嵌入式软件逆向分析中的动静态分析交互机制[J].信息工程大学学报,2015,16(5).

[5] 鲍庆国. 嵌入式设备固件分析的关键技术研究[D]. 北京:北京工业大学,2016.

猜你喜欢

嵌入式软件逆向工程二进制
一种嵌入式软件并行处理框架设计
有用的二进制
用Scratch把十进制转为二进制
有趣的进度
浅析嵌入式软件技术的现状与发展动向
基于模型检查的嵌入式软件构件化分析与验证
一种改进的点云数据组合精简算法
基于Hibernate逆向工程对企业组织建模研究
逆向工程技术在高职模具专业创新能力培养中的应用
嵌入式软件在计算机软件开发过程中的运用