注:本文出自复眼小组的magpie
一、前言
最近入坑iot,涉及很多芯片固件的逆向。但是这些固件很多时候都不是标准二进制格式,也就是说丢进ida,识别不出架构和指令集。架构和指令集可以查芯片的文档,但是加载基址还没法确定,这个靠自己去定位,再配置ida。人工做这个工作太累,而我又是懒狗,所以自动化这一过程不香吗?
这里推荐一篇很优秀的论文,北京理工大学朱瑞瑾博士学位论文《ARM设备固件装载基址定位的研究》,在第三章提到了一个基于函数入口表的基址定位方法。具体原理原文写的非常清楚,建议直接阅读原文,我就不再赘述。本文要聊的就是把文中提到的这个方法给具体实现出来,做成工具。
文末我会附上GitHub地址,我完成这个工具的开发后,测试的固件样本毕竟不多,肯定会遗留一些问题,希望师傅们能试一下帮我发现问题,能帮到师傅们最好了。
二、工具的开发、改进和优化
工具的原理直接去看论文原文就可以,源码我都公开在GitHub了,这里就不贴了。下面就主要聊一下对原文的算法做的改进和优化。
1、扫描模式的优化
原文中扫描寻找入口表时,找到一个入口表后就会停止gap值的遍历,且直接跳过入口表覆盖的偏移。跳过这些gap和偏移其实并不是很合理,会不够精确。
起初我是改成了不跳过,但是扫描时间变长了,于是我设置了一个开关参数,可以选择精确模式和粗糙模式。
2、函数紧凑间隔值的优化
匹配规则一中的间隔值,原文建议为0x10000,本人实测建议为0x1000.
3、简洁模式
实际情况中,加载基址第三位hex一般为000,原文中不考虑这一点,全部输出,其实不够准确。因此增加了简洁模式开关参数,可以开启后只输出第三位hex为000的地址。
4、boot模式
笔者新增的一个模式,也叫上电模式。Arm Cortex-M/R核心的固件的4偏移为pc寄存器上电值,代表第一条指令地址,因此能确定时加载基址不会大于此值。这时可以将boot参数设为此值来提高扫描效率。否则boot参数设为0.
三、其他说明
iAudio固件测试图:
sony固件测试图:
项目GitHub地址:
https://github.com/MagpieRYL/arm32_base_loc
关于工具的用法,下载后详见项目内的文档。Exmaple目录下有几个测试用例固件,其中sony和iAudio固件为原论文中用到的,可以去对照加载基址。Sony固件满足boot模式。