如何在 IDA Pro 中正确更改字符串?

逆向工程 补丁反转
2021-06-21 09:48:36

我正在尝试修补使用 Objective-C 开发的 cydia 调整。我想修改一段代码以满足我的需要。

我正在使用 IDA Pro V6.8 进行检查。检查后,我认识到每个十六进制字节将代表装配线代码的一部分。

Bellow 是我需要更改的代码的屏幕截图。 在此处输入图片说明

看上面的截图,我们需要8个字节(4A F2 A6 50 C0 F2 01 00)来表示一条“MOV”指令。让我来谈谈这 8 个字节:

  1. 据我所知,前四个字节(4A F2 A6 50)代表您在屏幕截图中看到的“#(cfstr_UnknownCallbac - 0x9F56)”。
  2. 后面的两个字节(C0 F2)代表一条 MOV 指令。
  3. 最后两个字节(01 00)会告诉系统将值从字符串移动到寄存器中,在这种情况下,寄存器是 R0。

我对 MOV 指令和前四个 HEX 字节 (4A F2 A6 50) 有一些担忧

  1. 指令中的“0x9F56”是什么意思?

  2. 系统如何知道前四个字节正确反映到“#(cfstr_UnknownCallbac - 0x9F56)”而不是任何其他字符串变量?

  3. 我需要创建一个新字符串,然后我将使用它来替换现有的 "#(cfstr_UnknownCallbac - 0x9F56)"我相信我只需要替换前四个十六进制字节,以便它指向新字符串,但我不知道这里应该有什么十六进制代码。

任何帮助表示赞赏,非常感谢。

1个回答

要了解发生了什么,您需要了解位置无关代码(PIC)。

简而言之,编译器希望可执行代码正确无误,而与它在内存中的加载位置无关。在共享库的情况下,操作系统可能每次都在不同的地方加载它;即使静态链接,PIC 也会使链接器的工作更轻松。

通常在 ARM 处理器上用于生成 PIC 的“技巧”是使用 PC(程序计数器)相对地址。编译器不会生成显示“字符串在地址 0x123456 处”的代码,而是生成“字符串在此指令后面的 0x1234 字节”。因此,当程序在内存中移动时,“0x1234”保持不变。

这就是为什么您的第二条指令将程序计数器添加到 R0 中的相对地址。

现在,要了解ADD R0, PC真正的功能,您需要了解处理器的工作原理。处理器处于 Thumb(2 字节指令)模式,从9F52之间的 2 字节差异可以看出9F54,当处理器执行ADD R0, PC指令时,预取单元已经读取了 的前两个字节BLX _MSlog所以添加的 PC 实际上是9F56. 这应该回答您的第一个问题:在操作码含义的显示中,IDA 减去它知道要在下一条指令中添加的值。

第二个问题:我不知道 IDA 的内部结构,但我 99% 肯定它会查找ADD Rx, PC指令,并在加载的前面的指令中产生一个像你一样的字符串引用Rx,只是因为它知道这是实现的标准方法ARM 上的 PIC。

第三个问题:手动反汇编 Thumb 很难——真的很难——你可以通过检查Thumb 指令集看到不,4a f2 a6 50不仅仅是数据偏移;它加载值的低 16 位,并C0 F2 01 00加载的高 16 位。在线反汇编翻译这两套4个字节指令

movw r0, #42406 ; 0xa5a6          
movt r0, #1

您可以在此处阅读有关movwmovt说明的信息。IDA 足够友好,可以将所有这些显示为一条 8 字节指令,但在幕后,还有更多的事情发生。

因此,如果您真的想像这样更改偏移量,请熟悉我上面链接的拇指手册,学习每一点,然后手动组装新指令。或者,只是(ab)按照我在这个问题的回答中概述的方式使用 gnu 汇编程序只需编写一个最少的汇编程序片段,并as为您处理血腥的细节。

但是,正如@joxeankoret 所说:如果您只想更改一个字符串,并且不需要其他地方的原始字符串,并且新字符串不比旧字符串长,那么用新字符串覆盖字符串会很多比为新弦找到一个位置并调整偏移更容易。您可以通过双击 IDA 中的标签跳转到该位置,或者直接滚动到地址2FF4C( 1A5A6+9F56)。