非英特尔固件中对象的手动分割

逆向工程 艾达 拆卸 固件 分割
2021-06-18 04:33:30

我目前正在为旧的 TMS320C5 16 位微处理器反转固件文件。我正在使用 IDA pro 来执行此操作,我需要为文件中包含的每个对象手动创建段。我要求一个循序渐进的程序来做到这一点。以下是有关原因/内容的更多信息。

与许多其他处理器一样,TMS320C5 访问内部缓存,称为“快速内存”,它是单个 64K 页面。它从外部更大和更慢的内存中加载此内存。

固件文件包含一个内存映像,该映像直接写入设备的慢速内存中。它使用多任务实时操作系统运行。每个任务/进程都存储在二进制文件中的不同位置,并且似乎没有任何特定的顺序。根据我的理解,文件中的每个任务前面都有 4 个字,其中一个表示当前任务将在快速内存中加载的基地址。在某些情况下,可以在快速内存中的相同基址加载 2 或 3 个任务。

任务中的每个分支/调用指令似乎都使用当前页面中的直接地址(见图 3)。所以它们与 PC(程序计数器)或其他寄存器的内容无关。

当然,我现在希望分支和调用指令与其段内的适当功能和部分保持一致。虽然我对 IDA 中的分段没有很好的掌握,但我阅读了一些其他线程,例如如何处理在不同执行中更改其地址的代码IDA 分段问题IDA 中的分段如何克服 NONAME 问题,但没有一个能提供我需要的完整解决方案,因为我不相信 CS/DS 和其他英特尔细分市场适用于此。我在 IDA PRO 书中也找不到任何真正有用的东西。

到目前为止,通过执行以下操作,我似乎已经完成了所需的 50%:

  1. 使用 Selector 子视图创建一个新的选择器:View > Open Subviews > Selectors
  2. 在子视图中右键单击,选择Add Selector
  3. 按照下面的图 1 创建了一些示例。
  4. 使用命令行和SetSegmentAttr函数,我更改了其中一个段的选择器:SetSegmentAttr(ScreenEA(), SEGATTR_SEL, 1)

例如,固件中有一个从线性地址0xCAEFD开始的任务此任务在快速内存中的0x2C00处加载因此,我想创建一个包含此任务的段,其基地址为 0x2C00。当我使用上述过程更改块的段时,偏移量从0x9EF02开始(见图 2)。我希望它从0x0开始

图1: 图 1:创建一个新的选择器

图2: 图 2:段的结果地址

我怀疑我有点需要以某种方式更改偏移量。我知道Move Segment选项,但它似乎“物理地”将段更改为地址,这是我不想要的,因为某些任务在快速内存中共享相同的基地址(或者彼此接近并会覆盖另一个任务)。我需要完成哪些步骤才能将每个任务隔离到自己的段中,以便分支和调用对齐?例如,在图 3 中,我希望 IDA 链接BCND 2C1Dh, geq段内相应的0x2C1D位置,而不是相应的线性地址。

图 3: 任务中的分支指令示例

谢谢你的帮助

1个回答

不是答案,真的,但评论太长了;另外,我很了解 x86 架构,但对 TMS320C5 一无所知,所以请持保留态度。

恐怕您尝试做的与 IDA 分段的工作方式不太匹配,这基本上源于 80x86 的做事方式。这意味着段寄存器包含 20 位地址的高 16 位,偏移量包含低 16 位;并计算物理地址,你会做segment<<4 | offset

这意味着像这样的地址1234:0020相当于1236:0000- 都映射到 的物理地址12360现在,如果您的二进制文件在段加载1234- 物理地址12340- 没有“内在”方式来告诉偏移量12360什么它可能是0020在内部1234段,或00001236段。IDA 分段只会告诉反汇编器新的段从12360物理地址开始,因此如果ds寄存器设置为该段,则ds:0访问该s defined at that12360` 地址的变量

这与您的处理器不同,因为代码永远不会换入或换出,代码区域永远不会在物理内存中重叠,并且段内的偏移量始终从 开始0000即使在病态的情况下,元信息 .EXE 文件声明要加载一个段到 offset 0200,加载器也会生成一个新段,用 填充前 0x200 个字节00,然后从 .EXE 文件中加载这个零后的内容堵塞。

IDA什么不能做-因为据我所知-大概是“做0000-CAEFD一个区隔,然后在开始另一段C82FD中的地址CAEFD有偏移2C00,因为这将使之间的文件部分的含义C82FDCAEFDambigous,你不知道它属于哪个段。

在你的例子中,当你说基地址应该是 时2C00,你告诉 IDA2C00文件中的地址应该等于0000段中的地址这就是它显示 offset 的原因9EF02如果2C00(文件位置)对应于0000(段开始),那么CAEFD-2C00=9EF02(文件位置)对应于9EF02(段内的位置)。尝试使用9EF02作为段开始;字节 atCAEFD2C00该段中的字节,因此它的偏移量为2C00.

如果这对您不起作用,我会执行以下操作:

  • 如果我的原始固件的大小不是 64K 的倍数,请附加\0字节直到它是。
  • 当我确定一个任务和它应该执行的偏移量时,附加尽可能多的0字节以到达该任务的起始地址,复制任务本身,并附加更多\0字节以再次达到 64K 的倍数。

这样做,您将获得一个文件,其中包含一个包含原始固件的大块和多个 64 KB 块,每个块只包含一个任务和一堆零。

现在,当您加载该文件时,为第一个大块定义一个段,并为每个附加的 64 KB 块定义一个段。这样,每个任务可以有一个段;段很容易定义,因为它们中的每一个都以 的倍数开始,10000除了第一个之外的所有10000字节的大小都是字节,并且您在file byte之间有 1:1 的关系memory byte这应该让 IDA 满意。