STM32F10x的启动文件跳转攻击方案设计
2018-06-15,,,
,,,
(1.陆军装甲兵学院 信息通信系,北京 100071; 2.73630部队)
引 言
一般嵌入式产品应用环境不会对硬件采取特殊的保护措施,而嵌入式系统的硬件又直接影响着系统工作的安全性,这为嵌入式系统带来了许多安全隐患,同时近年来嵌入式设备信息安全事故频发,系统的信息安全问题引起社会的广泛关注[1-4],越来越多的学者投入嵌入式系统漏洞的挖掘和研究工作。
林郭安、黄强等人[5]根据STM32芯片的启动特点,设计了一种由后至前遍历获取程序入口地址,通过修改程序入口地址实现源码复制窃取的目的,但该方法的遍历阶段具有盲目性的特点,攻击效率低。Frank Altschuler和Bruno Zoppis等人[6-7]提出通过向RAM缓存区传送大量数据,造成缓存区溢出,从而覆盖原程序跳转地址以达到攻击的目的,但这种方法并不适用于运行时直接从Flash区间读取代码的芯片。
本文针对STM32F10x系列控制芯片,根据其启动原理,借助仿真器和下载接口,将恶意软件载入目标芯片Flash空余扇区,在调试模式运行恶意软件,并从中篡改原启动文件的程序跳转指针,从而改变原程序启动时的运行顺序,使得植入的恶意软件得到执行,实现攻击目的,实验证明该方法具有针对性强、攻击效率高、方法简单易于实施的特点。
STM32F10x系列芯片采用32位的ARM Cortex-M3内核,主频高达72 MHz,型号众多、片上资源丰富,具有功耗低、性能强、性价比高的特点[8],可以很好地满足各类中低端嵌入式产品市场需求,在ARM系列微控制器市场占有率高[9],对STM32F10x系列芯片的攻击研究具有重要的市场价值和借鉴意义。
1 原理分析
加载启动文件是STM32微控制器在启动时执行的第一段程序,由汇编语言编写,它的作用包括配置中断向量、堆栈初始化、系统时钟初始化以及跳转至main函数等[10]。启动文件根据STM32具体型号而定,STM32F10x系列芯片共有小型容量、中型容量、大型容量等8种启动文件,这些启动文件在ST官方网站即可获取,芯片只有匹配了正确的启动文件才能正常运行。在实施嵌入式系统攻击时往往无法得知目标芯片的代码信息,但是获取其型号信息并不困难,只要在植入恶意代码中匹配相应的启动文件,就可以正确配置芯片,使得恶意代码在芯片上正常启动并运行。
Cortex-M3内核规定[11],映射存储空间的起始地址存放堆栈指针,第二个地址存放复位中断向量指针,在芯片启动时,硬件首先会根据复位中断向量指针跳转到复位中断函数,进行内核堆栈初始化和中断向量初始化工作,然后执行System_Init进行系统时钟初始化,最后通过__main函数跳转到主函数执行用户代码。本实验根据Cortex-M3内核启动顺序,重定位复位中断向量指针,从而在复位时跳转至恶意软件执行,然后跳转回原启动文件执行原程序,保证了原代码的完整性和嵌入式攻击的隐蔽性。
对目标实施攻击后的代码执行流程如图1所示。
图1 攻击目标代码执行流程
一般情况下,映射存储空间为MCU内部Flash,出于产品优化升级考虑,嵌入式产品都会在Flash内部预留出多余扇区[5,13],这为恶意代码的植入提供了可用空间,Flash的读写保护仅对外界读写操作有效,不能阻止原有程序对Flash的操作,这为恶意代码提供了执行条件。恶意代码一经执行,就会篡改原程序复位中断向量指针,在下次芯片烧录之前,攻击一直有效。
2 方案设计
汽车实验采用搭载STM32F103VET6芯片的指南者开发板,该芯片Flash容量为512 KB,应用CMSIS-DAP标准的仿真器,上位机系统环境为Windows7,使用ST公司提供的编译开发环境MDK,以及串口调试助手。
首先利用MDK将恶意代码下载至芯片Flash的最后扇区,然后通过仿真器的Debug模式从恶意代码区启动,并在恶意代码中修改原启动文件的复位中断向量指针,最后在恶意程序中跳转回原启动文件,重新初始化系统运行原代码,之后系统每次复位都会优先执行攻击代码后再跳转回原代码执行。
在指南者开发板上进行简单的流水灯作业,注入恶意代码的功能为蜂鸣器响起并延时1 s,并向串口输出“攻击成功”的打印信息,同时可以在Debug模式下观察PC指针的值以判定攻击是否成功。
方案实现框图如图2所示。
图2 启动文件攻击实现流程
3 实验验证
3.1 实验过程
(1)恶意软件下载
为了最大限度确保注入恶意代码的完整性并且不覆盖芯片原有代码,实验首先分析恶意攻击软件的容量,在编译好的文件中,通过map文件可以查看恶意软件的大小为3.75 KB,STM32F103VET6芯片内Flash容量为512 KB(0x08 0000),每页扇区大小为2 KB,本实验将恶意代码烧录到最后两片扇区中,即0x0807 F000~0x0808 0000区间。通过修改MDK中Options->Target的设置可以实现定位下载地址。
图3为map文件中恶意代码大小信息以及Target Memory部分设置界面。
图3 map文件代码信息及Target Memory设置页面
(2)仿真器启动
为了在启动时优先运行恶意软件,实验借助DAP仿真器在Debug模式下复位运行,需要添加初始化文件Debug_RAM.ini,在该文件中设置堆栈指针和PC指针,这样在Debug模式下启动时,程序就会被强制跳转到此位置运行,程序如下所示:
FUNC void Setup(void){
SP=_RDWORD(0x0807F000);
PC=_RDWORD(0x0807F004);
_WDWORD(0xE000ED08,0x20000000);
}
LOAD %L INCREMENTAL
Setup();
(3)跳转地址重定位
由于Cortex-M3内核在启动时会根据映射存储空间第二个偏移地址(复位中断向量指针)跳转到复位中断函数执行,用户无法改变这一内核启动的顺序,但是可以通过Flash自身程序修改复位中断向量指针的值,从而改变默认跳转地址。通过实验发现,STM32F10x系列芯片的复位中断指针相对Flash的起始空间固定偏移0x145个字节,当Flash起始地址为0x0807 F000时,复位中断指针应修改为0x0807 F145,该过程由恶意软件实现。
由于Flash在写操作之前必须按页擦除,故在代码实现时需要先将Flash起始地址的第一页内容复制到至少2 KB容量的数组,将数组中第二个字的内容修改成恶意代码的复位中断向量指针0x0807 F145,然后再将这一页内容重新写入Flash,完成复位中断向量指针的替换。当开发板重启时,系统就会先跳转至恶意代码区启动文件进行系统初始化启动,在执行完恶意代码内容后跳转回原启动文件的复位中断函数,重新初始化系统,运行原代码。
3.2 实验结果
对正在进行流水灯作业的指南者开发板进行攻击后,每复位一次开发板,蜂鸣器鸣笛1 s,并在串口收到“攻击成功”的调试信息,在单步调试模式下,对比攻击前后映射存储空间起始地址(0x0800 0000)的第二个字内容,如图4所示,可以清楚看出复位中断向量地址已被篡改。
图4 Debug_RAM.ini文件内容
结 语
[1] 蔡舒祺.嵌入式系统安全性分析概述[J].电子技术与软件工程,2017(3):210-212.
[2] 李冰冰,陈静.物联网时代的嵌入式系统安全性问题探讨[J].数字技术与应用,2016(12):217,219.
[3] 第88届中国电子展.嵌入式应用面临新机遇,信息安全更加被重视[J].中国电子商情:基础电子,2016(12):53-54.
[4] 赵国冬.安全嵌入式系统体系结构研究与设计[D].哈尔滨:哈尔滨工程大学,2006.
[5] 林郭安,黄强,许文焕.STM32F103RB的Bootloader软件安全设计方案[J].单片机与嵌入式系统应用,2009(9):73-75.
[6] Frank Altschuler,Bruno Zoppis.嵌入式系统安全性(上) -对攻击状况和防卫策略的概述和分析[J].电子产品世界,2008(5):109-113.
[7] 王柳滨,魏国珩,李政.嵌入式系统缓冲区溢出攻击防范技术[J].计算机应用,2012,32(12):3449-3452.
[8] STMicroelectronics.STM32F103xE Data sheet,2008.
[9] 单祥茹.STM32教父新愿景:产品成嵌入式工程师的首选[J].中国电子商情:基础电子,2017(7):10-11.
[10] 刘火良,杨森.STM32库开实战指南[M].北京:机械工业出版社,2017.
[11] Joseph Yiu.ARM Cortex-M3与Cortex-M4权威指南[M].北京:清华大学出版社,2015.
[12] 张宏财,赵曾贻.基于ARM核的Bootloader代码分析与设计[J].微计算机信息,2006,22(5-2):137-139.
[13] STMicroelectronics.STM32F10xxx Flash programming manual,2008.