想象一下:

您有一块ARM固件的二进制文件。您将近100%是ARM,并且它在裸机上运行。您从制造商更新页面获得了此固件。

但是,您不确定二进制文件打算用于的确切芯片型号。您找不到该芯片的开发人员指南或规格表。

二进制文件没有已知的标头,研究表明,该二进制文件未经压缩或加密。二进制文件底部的很大一部分字符串表明它是一个单一的二进制文件,并且没有几个压缩在一起的记录。没有文件系统的迹象。

您应该能够合理地反汇编代码,但是缺少一些因素来阻止您检索控制流并造成明显的反汇编。

1)您不知道初始入口点在哪里。
2)您不知道是否有一个ram节,以及它的起始地址和结束地址。
3)您不知道是否有rom节,以及它的起始地址和结束地址。

鉴于这些或类似情况,逆向工程师如何推断出ROM之类的区域的初始入口点和位置/大小?

我想通过有效地反汇编来检测某种类型的内存映射芯片中的读和写,只需突出显示经常引用的公共内存区域并将它们分类即可。我希望有人想出一种自动化的方法来进行这种分析。 “

E.G

“经常引用范围0x7-0x9。它可能是ROM。最高地址是0x7998,该区域似乎占据了8 Mb。

到目前为止,确定入口点的另一个区域使我很困惑。没有芯片的文档,是否可以推断代码的初始入口点?这对于引导加载程序似乎与主固件分开存储在ROM中的芯片尤其令人沮丧。

如果没有开发人员文档,是否可以暗示这种固件映像的结构?

#1 楼

我通常要做的事情:


将二进制文件加载到不太小的基地址,例如0x10000000
标识尽可能多的函数和字符串。 />
您可能会很幸运,仅从字符串开始,这通常工作量较小。位二进制值)。
现在对函数和字符串地址列表进行排序,并计算每个连续地址之间的差。
对常量值列表进行相同操作。

现在,您有两个地址差异列表,如果在两个列表中都找到一系列连续的差异,则您已经找到了基址。这两个列表可能不完整的问题。例如,地址列表将没有每个函数的绝对指针,或者您可能错误地反汇编了一些函数。也许您会更好地专注于字符串地址。

我通常在vim中使用正则表达式搜索手动完成此列表匹配。在某些情况下,我写了一些小脚本来帮助寻找比赛。 ...但是我现在找不到这些,如果再次找到它们,我将更新我的帖子。


聊天摘要


正在讨论的固件文件:dvdo的DVDO Matrix6固件01.01。

我查看了同一站点的其他二进制文件,并找到了基于ARM芯片LPC1758的引用。 >
独立IDA不能立即识别该二进制文件。原因是此二进制文件只有Thumb指令。 IDA期望手臂二进制文件以ARM32代码开头。
通过存在70 47(BX LR),00 bf(NOP),*0 b5(PUSH {...}

因此使用T将段类型1更改为Alt-G后,我可以反汇编该文件。

查找偏移量:

这两个命令将生成文件中出现的dword列表和文件中出现的字符串列表:

od -Ax -t x4 Matrix6_Version_01/M6FW0101.BIN | perl -pe 's/^\w+\s+//' | tr " " "\n" | sort|uniq  > dwordlist.txt
strings -10 -o -t x "Matrix6_Version_01/M6FW0101.BIN" > stringlist.txt


现在来看第字符串列表中的真实文本:

28eaa pGSAC Initiation task finished
28eca SAC Audio Format Discovery task finished
28ef4 SAC volume has changed
28f0c Audio System Logical Address not assigned
28f37 CBUS MUTE received
28f4b CBUS UN-MUTE received
28f62 CBUS VOL UP received
28f78 CBUS VOL DOWN received


您可能会注意到第一个字符串的前2个字符pG实际上是70 47BX LR指令。

现在我将在Vim中加载两个文件,并在两个文件中都运行以下vim-perl脚本: :

:perldo s/^\w+/($x,$p)=(hex($&),$x); sprintf("%s(%8x)", $&, $x-$p)/e


现在,由于错误的pG开始,跳过前两个,我在dwordlist.txt中搜索分别使用2a,18和2b的连续行正则表达式搜索:

28eaa(    25dd) pGSAC Initiation task finished
28eca(      20) SAC Audio Format Discovery task finished
28ef4(      2a) SAC volume has changed
28f0c(      18) Audio System Logical Address not assigned
28f37(      2b) CBUS MUTE received
28f4b(      14) CBUS UN-MUTE received
28f62(      17) CBUS VOL UP received
28f78(      16) CBUS VOL DOWN received


这使我在两个文件中都找到了以下匹配的行: 0x2eeac的0x28eaa将我引向0x6000的偏移量。

评论


我假设您正在针对像objdump这样的线性反汇编程序进行初始反汇编?我担心的是,从某种程度上已经腐烂的东西中辨别出合法的拆卸。

–baordog
17-10-24在21:49

我将使用IDA进行初始和最终拆卸。因为那样可以自动执行很多功能查找。也许可以借助一些idapython脚本来强制IDA探索更多未实现的代码。

–威廉·亨格维尔德(Willem Hengeveld)
17-10-25在6:33

嗯,是的,但是在许多情况下,IDA并不是首先找到这些功能。因此,所有担心都无法找到适合导入的地址。在这样的典型二进制文件中(对我而言),IDA将找到2-5个函数,它们将是错误的。

–baordog
17-10-25在8:55

也许您正在查看加密的固件映像?你可以发表样品吗?

–威廉·亨格维尔德(Willem Hengeveld)
17-10-25在10:22

我认为该方法适用于任何以二进制形式存储字符串绝对偏移量的CPU。

–威廉·亨格维尔德(Willem Hengeveld)
17-10-31在15:41

#2 楼

我将在Recon 2010演示文稿(从第48页开​​始)中介绍其中的一些内容。

总结方法:预期位置
初始化代码,其中包含对预期运行时地址的引用
具有绝对地址的跳转表
与二进制文件中的实际字符串匹配的字符串表(地址表)。
符号桌子(如果幸运的话)


评论


我不认为这方面有自动化吗?听起来好像不是。

–baordog
17-10-24在7:49

我每天不会反转数百个二进制文件,因此到目前为止,我一直主要是手动执行此操作。

–伊戈尔·斯科钦斯基♦
17-10-24在9:26

maddie stone的IDAPython Embedded Toolkit对此类任务有用吗?

– julian♦
17-10-24在12:25

@SYS_VL我认为她的脚本主要处理已经正确加载的代码,但是也许她也对此有所帮助,我不确定... FWIW字符串表(或函数表)搜索当然可以自动化

–伊戈尔·斯科钦斯基♦
17-10-24在13:49

谢谢,很高兴知道。听起来真的不像是“改变生活的魔法”,但是我还没有尝试使用它

– julian♦
17-10-24在16:57