本文编写于367 天前,最后修改于367 天前,其中某些信息可能已经过时。

只有bin, 我们怎么办?

拿到一个stm32的固件,只有bin文件了,如何研究、修改里面的代码呢?
通常很多人认为这是不可能的……对呀,没有了源程序怎么办嘛!
没关系,现在我们来研究一下如何使用ida来逆掉stm32的bin固件~
接下来以stm32f103c8t6为例,其他stm32系单片机也基本大同小异啦……无非是内存大小不一样罢了,没有什么太大的区别。

提示: 如果你拿到的文件不是bin而是hex,那么能节省掉好多的配置步骤。当然实际上没有太大的区别,不管是hex还是bin都不影响我们的分析。


载入ida

首先常规操作,把bin文件拖入ida。
但是因为这是一个二进制bin文件,ida并不知道这是一个什么东西……于是我们要设置CPU参数等等信息。
因为stm32是一个arm cortex m系列的cpu内核,因此我们需要把cpu设置为arm:

当然,仅仅把cpu设置为arm是不够的,因为arm下面还有好多个子类。接下来点击processor options,设置cpu的相关属性信息:

好了,这时候我们可以直接点击确定加载这个固件了……不过这还没完呢。


设置rom起始地址和ram起始地址

emmmmmm……不出意外的话,现在ida一定会询问我们固件的起始地址和内存起始地址。
这是因为bin文件仅仅是一串二进制的数据,ida并不知道这个固件要被加载到什么位置上去……
于是我们要手动配置固件的起始地址。

如果你加载的固件是hex,那么通常情况下hex已经标注了固件的起始地址。这样一来往往这一步会被自动配置,无需人工干预了。

那么我们就手工输入ram起始地址和rom起始地址,如图:

其实这样设置的原因也很简单:

  1. RAM start address,ram起始地址,在我印象里我用过的所有stm32都是清一色的0x20000000,似乎就不会有什么变化。直接填上就可以了。
  2. RAM size,ram长度,stm32f103c8t6是一个64kb内存的单片机,换算为16进制刚好是0x10000。如果是其他型号的单片机,内存容量不一样的话,改一下就好了。
  3. ROM start address,rom起始地址,一般来说都是0x08000000。这是默认的stm32程序被映射到的内存地址,如果存在bootloader,这里的地址可能会有变化。如果不能确定,可以先用0x08000000进行载入,稍后分析入口点的时候若发现不对,观察一下入口点的地址大概在哪个范围内,重新载入一次并修改过来即可。
  4. ROM size,rom长度,无需修改,当前文件的长度就好了。
  5. Loading address,rom装载地址,一般来说和rom起始地址保持一致即可。

设置好之后,点击OK,就可以将这个文件装入了呢。


分析入口点

到现在这个位置,我们已经成功的将固件载入到了ida,但是因为这是一个没有任何信息的二进制文件,ida依旧不知道应该在什么位置分析这个文件。
那么我们需要手工将一部分信息分析出来,找到文件的入口点函数,然后ida才能对文件进行更深层次的反汇编分析。
现在的ida大概是这个样子的:

我们来观察这开头的几个字节,其实这几个字节标注了stm32运行所需要的一些关键信息,如入口点向量、中断向量等等。在这里面就有我们要找的入口点向量,也就是入口点函数的地址。

我们知道stm32是32位机,那么毫无疑问,这些数据也应该是32位,也就是4字节dword。
那么我们在这个位置狂按d,把数据都转换为4字节整数,然后就变成了这个样子……

之所以这样操作,原理是这样的:这其实是stm32固件的一个固定格式,文件开头固定是几个dword。我们可以理解为,这些数值代表着stm32运行所必须需要的向量表信息。其中这里面第二项就是我们要找的入口点函数的地址。这招在各种stm32单片机上都屡试不爽。

观察这些数据,从第二个开始,无一例外的都落到了0x08000000的数据范围内,这也说明了我们手工输入的rom起始地址是正确的。

提示: 如果不正确(比如变成了0x080121E5,明显在文件长度之外),那么我们可以观察一下大概落在了一个什么范围里面(如0x8010000),然后关闭ida,重新开始,纠正我们的rom起始地址,并再试一次。

那么入口点函数在哪呢? 如图,第二项就是。我们右键,跟过去看一看。


开始反汇编!

不出意外,我们跳到了一个完全未知的区域,此时的ida依旧是一片空白,什么代码都没有分析出来。
看上去好像什么都没有,难道我们做错了哪一步么?

别担心,我们并没有做错什么,只是因为ida并没有对这个文件进行任何的分析,因此没有主动反汇编这个文件啦……
我们对着这个地址的数据按C键,强制转换为代码~
当然,因为arm的特性,要在这个地址-1的位置按C键进行反汇编,否则是反不出东西的哦……如下图的位置,按C键进行反汇编:

伴随着ida的一阵自动分析,然后这一段代码就变成了这个样子:

看到什么了么,arm汇编出现啦~ 这就是入口函数的汇编代码了呢。
我们现在已经可以人工阅读汇编来逆向分析这个固件了,不过代码还是很庞大的,汇编的可读性还是很差。
为何不借助ida的hexrays插件,直接按F5将这段汇编代码反编译为C语言呢? 我们只需要将这个位置标记为函数,即可让ida识别到函数体,进而使用F5工具了呢。
于是在CODE32的位置按下P键,将这一段入口点汇编代码创建为函数:

好啦,至此大功告成! 大部分的函数也已经被ida自动分析出来了,现在和往常一样使用F5去逆向stm32固件吧~