如何利用IDA Pro逆向分析ARM 二进制映像 - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

如何利用IDA Pro逆向分析ARM 二进制映像

fanyeee 技术 2022-01-15 11:50:00
272933
收藏

导语:本文将为读者详细介绍如何利用IDA Pro逆向分析ARM 二进制映像。

 在本文中,我们将以ANYTONE 878UVII对讲机中的固件为例,为大家演示如何对ARM固件映像进行逆向分析。不过,本文中的大部分内容,对于ARM架构来说都是通用的。

本文假设读者已经熟悉IDA Pro,并且至少分析过一些普通的二进制文件。如果您还不熟悉IDA,只需在网上搜索一下,就能找到许多非常优秀的入门教程,大家可以先通过它们来掌握相关的基础知识。

固件映像

就本文来说,我们只需IDA Pro和ANYTONE 878UVII对讲机的固件映像就能搞定我们的实验。并且,所需的映像还可以从分销商网站下载。实际上,下载哪个版本并不重要,但本文是将以2.04版本为例进行介绍。

1.png

在下载的更新包中,我们可以找到FW文件夹,其中包含三个文件:CDI、SPI和CDD文件。其中,CDD是最大的文件,它实际上就是我们要分析的固件映像。

这次我们的运气不错,因为这个固件映像并没有加密,否则,事情就会麻烦一些。它只是内部闪存中的映像,甚至连文件头都没有。并且,该文件的元数据被拆分为单独的文件。所以,我们可以直接在IDA Pro中加载CDD文件。

技术背景

ANYTONE 878系列对讲机使用的是GigaDevice GD32 ARM Cortex-M4微控制器:通过拆开对讲机,我们就能看到这些芯片的型号。

除了拆对讲机外,实际上还有另一种更方便的方法:查询FCC。如果您的设备符合FCC的要求,网上应该有关于它的公开信息。这时,我们可以直接在FCC或独立的数据库中搜索制造商的信息。大多数情况下,我们会找到一份带有“内部照片”的文件。这个文件通常能够提供我们感兴趣的信息,比如芯片型号等,这样,我们就不用拆机了。

1.png

重要的是,我们建议大家下载CPU的数据表,并保存起来供后面使用:后面步骤中需要设置的参数,都可以从中找到。

关于CPU的相关设置

首先要做的是,把CDD拖到打开的IDA Pro窗口中,或者通过文件菜单打开它。IDA会检测出这是一个二进制文件。然后,将“Processor type”指定为 “ARM little-endian”,具体如下图所示。

1.png

现在,先别按“Ok”按钮,因为还要对处理器选项进行一些设置。我们知道,这种设备使用的处理器是基于ARMv7E-M架构的。因此,我们必须对处理器选项做相应的修改。最佳设置如下图所示;为此,需要按下“Processor options”菜单中的“Edit ARM architecture Options”按钮,这样就可以找到中间的窗格了。

1.png

由于这个项目与Thumb指令集高度相关,所以也建议在“ARM specific options”中勾选“No automatic ARM THUMB switching”选项。虽然这一点并没有显示在上面的截图中,但对本项目来说的确是一个非常有用的设置。

加载映像

现在,我们已经完成了基本的CPU设置。接下来,我们需要将加载的固件映像重新定位到正确的偏移量处。这个固件映像将被加载到IDA数据库的ROM部分。由于CPU不会从文件中的0x00处开始加载映像,所以,我们必须重新定位。如果跳过这一步,交叉引用将被破坏,反汇编文件将无法正常工作。我们的目标设备中使用的ARM CPU将要求映像从偏移量0x8004000处开始。这里其实就是映射到物理ROM的内存位置,所以,我们需要将文件映射到这个地址。

在单击“Load new file”对话框中的Ok按钮之后,将会出现如下所示的对话框。通常情况下,RAM的大小和ROM的大小并不需要调整。它们现在已经正确地自动填充好了。

1.png

接下来要做的事情,就是创建一个RAM分区。为此,可以勾选“Create RAM section”,分配的RAM将从0x20000000位置开始,长度为0x17FFF。

如何找到正确的内存偏移量

如果读者是第一次接触这方面的内容,通常会有这样的疑问:这些值是如何确定的?答案很简单,我们可以从之前下载的数据手册中找到它们。

从第17页的内存映射部分,我们可以找到主闪存(固件文件)的加载地址。而在第16页中,我们可以找到SRAM偏移量和这段内存的长度。

1.png

很简单吧?上面所做的只是将文件/映像重新定位到从我们的数据表中获取的正确位置。关于主闪存有一个小技巧,第一个0x4000似乎是由引导程序获取的,所以,我们的二进制文件必须位于0x8004000处。

二进制文件的结构

对于第一次使用IDA的读者来说,感觉可能非常奇怪:它并没有像其他软件一样进行自动分析,也没有展示程序代码,相反,它只是给出了大量的十六进制字符。难道是我们哪里做错了吗?很可能不是。如果您正在使用IDA Pro分析固件映像,这是非常正常的现象。这里的难点在于,我们必须自己从头开始进行分析。

1.png

但这也没有想象的那么难。首先,让我们考察文件的开头位置。这是ARM CPU开始执行代码的地方。在这个偏移量处,一个被称为向量表的结构被定位,它在ARM Cortex通用用户指南中有很好的详细描述。

1.png

正如我们在用户指南的图形中所看到的,偏移量0x0000(0x08004000)处包含初始堆栈指针。CPU将在这个地址加载接下来的四个字节,并将其用作指向未来堆栈的指针。

复位处理程序

接下来的字节是各种处理程序,最重要的是复位处理程序(reset handler)。它正是CPU要启动或重新启动时将会跳转到的地方。


1.png

它又是一个4字节的地址,对于我们的映像来说,这个地址很容易解析。正如链接的ARM用户指南文章所告诉我们的,如果地址的最低有效位为1,则处理程序为Thumb。

在我们的例子中,该地址的最后一个字节是0xF9,二进制形式为11111001B。我们可以看到,这里的最低有效位确实是1。因此,我们需要将复位处理程序的入口点改为Thumb。实际上,复位处理程序的实际偏移量也由于该位的值而移动了一个字节。

0xF9 = 11111001b (with Thumb indicator)

0xF8 = 11111000b (without)

单击这个偏移量,就会跳转到复位处理程序的地址减1个字节的地方。现在,请按“Alt+G”,这时会打开一个对话框,我们需要将下面的部分定义为Thumb(CODE16)。

1.png

这个项目主要涉及Thumb指令集,因此,您也可以从ROM段的第一个字节开始使用Thumb代码。请记住,这一点并非适用于所有的ARM项目。但对于这个项目来说,这是没问题的。

将当前偏移量改为CODE16后,只需按“C”,就能在该偏移量处创建代码了。现在,我们就应该可以看到复位处理程序的代码了。

1.png

查找其他代码和字符串

上面介绍的方法虽然能用,但是通过手动方式来创建所有的代码是相对繁琐的。别担心,我们可以借助于脚本来完成这些任务。实际上,Maddie Stone已经为IDA Pro创建了许多非常方便的脚本,能够给我们带来极大的便利。

由于她的脚本不能用于较新的IDA版本(在写这篇文章时,最新的版本为7.7),所以,我们专门把适用于IDA 7.x版本的脚本上传到了Github上,读者可以从https://github.com/alexander-pick/IDAPythonEmbeddedToolkit下载。为了支持基于ARM的项目,我已经对这些代码做了相应的处理。

首先,我们可以使用脚本define_code_functions.py,在0x08004000到0x080963DC大致范围内创建代码。如果脚本询问是否要撤销现有的代码,请选择No。

IDA Pro应该可以正常工作了,此时的ROM部分应该开始变得更有趣了。

1.png

接下来,我们可以使用make_strings.py脚本,在ROM的其余部分创建字符串。这时,你会在其中发现许多我们感兴趣的字符串。

关于字符串引用

分析这个固件时,我们会发现一个奇怪的现象。由于ANYTONE的开发人员为多国语言创建了固件,所以,他们使用了引用表。因此,这可能导致我们会遗漏某些字符串的引用。之所以会发生这种情况,是因为这些字符串是根据选择的语言来动态加载的。遗憾的是,基于IDA的静态分析是无法解决这个问题的。

不过,引导过程中的一些字符串是直接嵌入的,所以它们解析起来问题不大。因此,我们可以从这些字符串开始下手。

1.png

为了做进一步的分析,我们需要能够识别一些基本的OS函数,即操作嵌入字符串的函数,比如“print”或“read”函数等。当然,类似“memcpy”这样的函数在各种操作系统中都是非常常见的。

非常值得注意的是“print_string”函数(一旦识别出来,我就把它重命名为这个名字)。它接受一些坐标和一个字符串作为参数,并将字符串显示在屏幕上给定的位置处。这个函数在启动菜单中被大量使用。

从固件镜像中的字符串可以识别出设备使用的RTOS(实时操作系统)是μC/OS-II。μC/OS-II是一个用ANSI C编写的免费实时操作系统。关于该系统的进一步介绍,以及相关文档,读者可以在这里找到;而相关代码则可以从这里下载。感兴趣的读者可以参考这些资料,它们应该对您有很大的帮助。

I/O和外围设备

像这样基于ARM的CPU通常使用特殊的内存区域来处理地址总线、GPIO、I/O或简单的定时器和时钟,具体请参阅数据表。实际上,在第14页中,大家可以找到我们用来指定加载偏移量的内存映射。该映射还包含要添加到数据库中的特殊内存区域。

打开IDA中的内存区域视图(segments view)并将它们添加到数据库中,结果应该与下图类似。如果你想偷懒,则可以使用这个IDC(https://github.com/alexander-pick/useful-script-and-code/blob/master/GD32F303xx_segments.idc)来完成这个过程。

1.png

现在,请重新运行自动分析(Options -> General -> Reanalyse program)以创建交叉引用。

一旦你完成了上面的步骤,就可以查看感兴趣的内存区域,看看是否有对它们的交叉引用。这些可以帮助您找到使用特定总线、GPIO或I/O的函数。

如果您查找操作UART的函数,只需检查UART区域,就会找到对它的引用。这在没有或只有很少字符串作为引用的情况下是特别有用的。

小结

我认为,到目前为止,您应该已经具备了自己研究这一主题所需的一切。请随时给我留言。如果您还有什么问题,尽管问。我总是很高兴看到人们分享有趣的发现。

阅读愉快!

本文翻译自:https://do1alx.de/2022/reverse-engineering-radios-arm-binary-images-in-ida-pro/如若转载,请注明原文地址
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2022 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务