0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

技术让梦想更伟大 来源:技术让梦想更伟大 2023-11-30 10:30 次阅读

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

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

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

wKgaomVn9TuACAuwAAAQISh9Rf4210.png

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

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

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

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

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

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

wKgaomVn9TqAS66SAABsZUG96zU804.png

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

wKgaomVn9TuAcsO5AAKzuKC6O_A269.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的大小并不需要调整。它们现在已经正确地自动填充好了。

wKgaomVn9TuADb8rAAA8_LCw2hI762.png

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

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

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

wKgaomVn9TuAf6wbAACSYjkg5G0430.png

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

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

wKgZomVn9TuABCT7AAMoC0T1-QA117.png

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

wKgaomVn9TuAfPaKAAB2E3mYq2w884.png

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

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

wKgZomVn9TuAf5jMAAAc8p4rBvA873.png

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

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

0xF9 = 11111001b (with Thumb indicator)

0xF8 = 11111000b (without)

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

wKgZomVn9TqABPyIAAAWqTFaDgU504.png

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

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

wKgZomVn9TqABC0uAAAVwLd4rm4605.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部分应该开始变得更有趣了。

wKgZomVn9TuAIWLoAAAC6lENaAg511.png

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

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

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

wKgZomVn9TuAMFoyAABau0RWYtw939.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)来完成这个过程。

wKgZomVn9TuAeKUGAAEqeV2b0sA150.png

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

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

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

小结我认为,到目前为止,您应该已经具备了自己研究这一主题所需的一切。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ARM
    ARM
    +关注

    关注

    134

    文章

    8651

    浏览量

    361780
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10442

    浏览量

    206559
  • 二进制
    +关注

    关注

    2

    文章

    705

    浏览量

    41250
  • IDA
    IDA
    +关注

    关注

    0

    文章

    7

    浏览量

    7904

原文标题:如何利用IDA Pro逆向分析ARM 二进制映像

文章出处:【微信号:技术让梦想更伟大,微信公众号:技术让梦想更伟大】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    二进制码详解

    本帖最后由 gk320830 于 2015-3-9 06:39 编辑 二进制码  数字系统中的信息可分为两类,一类是数值,另一类是文字符号(包括控制符)。  代码:采用一定位数的二进制数码来
    发表于 04-06 23:55

    二进制格雷码与自然二进制码的互换

    。而绝对式编码器是直接输出数字量的传感器,它是利用自然二进制或循环二进制(格雷码)方式进行光电转换的,编码的设计一般是采用自然二进制码、循环二进制
    发表于 03-08 14:16

    arm二进制文件和UE的二进制取值问题讨论

    本帖最后由 kernel288 于 2013-7-11 15:02 编辑 请教下。为什么littlearm 出来的汇编指令和ue 的二进制取值相反。举例如下:arm littlearm 的本来指令是这样的e3a00207…… 经编译后成这样的。07 02 a0 e3
    发表于 07-11 15:01

    基于FPGS二进制LDPC

    一个8位二进制数经过二进制LDPC编码器编码后等到一个几位二进制的数,怎么计算的?
    发表于 03-14 13:07

    Labview图像二进制转换问题

    `各位大神,我想把一张图片通过变成二进制通过TCP传输,现在我把图片转换成二进制文件,但文件只有1KB大小。我想读取但是不知道二进制的图片数据类型。能否帮我画一个简易的读取二进制图片的
    发表于 12-29 09:26

    如何进行Linux二进制分析

    器和逆向工具并且依赖我们的黑客直觉来掌控我们正在逆向的目标程序。我们必须理解二进制格式、内存布局和给定处理器指令集的复杂性。我们因此成为微处理器上的程序的主人。一个逆向工程师对
    发表于 07-18 06:25

    如何理解二进制运算规则 二进制是如何运算的

    二进制运算规则二进制的运算算术运算二进制的加法:0+0=0,0+1=1 ,1+0=1, 1+1=10(向高位进位);二进制的减法:0-0=0,10-1=1(向高位借位) 1-0=1,1
    发表于 12-11 17:49

    进制46.25对应的二进制表达式为什么

    的计算是最简单的,整数部分除以2得到的余数按照逆向顺序排列后就是整数部分转化为二进制后的结果,详细过程如下所示:46转化为二进制的结果就是101110小数部分的计算可能很多人记不清楚了,小数部分每次乘以2后得出的结果取其整数部分
    发表于 07-27 08:25

    如何丢弃函数的二进制代码填入SRAM的二进制代码?

    应用程序 : 示例代码演示了如何丢弃函数的二进制代码, 然后填入 SRAM 的二进制代码, 然后调用它 。 BSP版本:M451系列BSP V3.01.001 硬件: 任何 M451 系列板块
    发表于 08-23 06:34

    二进制

    二进制   二进制与十进制的区别在于数码的个数和进位规律有很大的区别,顾名思义,二进制的计数规律为逢二进一,是以2为基数的计数体制。10这
    发表于 04-06 23:48 7668次阅读
    <b class='flag-5'>二进制</b>

    二进制编码和二进制数据

    二进制编码和二进制数据   二进制编码是计算机内使用最多的码制,它只使用两个基本符号"0"和"1",并且通过由这两个符号组成的
    发表于 10-13 16:22 4516次阅读

    二进制电平,什么是二进制电平

    二进制电平,什么是二进制电平 在二进制数字通信系统中,每个码元或每个符号只能是“1”和“0”两个状态之一。若将每个码元可能取的状态增
    发表于 03-17 16:51 2271次阅读

    二进制移频键控原理图分析

    二进制移频键控原理图分析 1.2FSK信号的产生原理框图
    发表于 03-19 16:48 2143次阅读

    格雷码与二进制的转换

    格雷码,又叫循环二进制码或反射二进制码,格雷码是我们在工程中常会遇到的一种编码方式,它的基本的特点就是任意两个相邻的代码只有一位二进制数不同,这点在下面会详细讲解到。格雷码的基本特点就是任意两个相邻的代码只有一位
    的头像 发表于 03-02 15:48 1.7w次阅读
    格雷码与<b class='flag-5'>二进制</b>的转换

    二进制SCA指纹提取黑科技: go语言逆向技术

    二进制SCA指纹提取黑科技: go语言逆向技术 华为云DevCloud软件开发平台在2022华为伙伴暨开发者大会重磅推出了4大新能力,其中的二进制成分分析安全检测能力,能够实现对开源软件漏洞的全面
    的头像 发表于 10-13 22:20 459次阅读
    <b class='flag-5'>二进制</b>SCA指纹提取黑科技: go语言<b class='flag-5'>逆向</b>技术