【问题标题】:Converting assembly instructions BL and B to binary将汇编指令 BL 和 B 转换为二进制
【发布时间】:2015-10-09 16:48:31
【问题描述】:

我试图了解包含二进制代码的二进制文件如何转换为汇编指令。

例如,这里是基于 ARM 的应用程序的 objdump 的示例输出:

00008420 <main>:
8420:   e92d4800    push    {fp, lr}
8424:   e28db004    add fp, sp, #4
8428:   e24dd008    sub sp, sp, #8
842c:   e59f2054    ldr r2, [pc, #84]   ; 8488 <main+0x68>
8430:   e24b300c    sub r3, fp, #12
8434:   e1a00002    mov r0, r2
8438:   e1a01003    mov r1, r3
843c:   ebffffc6    bl  835c <__isoc99_scanf@plt>
8440:   e3a03000    mov r3, #0
8444:   e50b3008    str r3, [fp, #-8]
8448:   ea000006    b   8468 <main+0x48>
844c:   e51b3008    ldr r3, [fp, #-8]
8450:   e2833001    add r3, r3, #1
8454:   e50b3008    str r3, [fp, #-8]
8458:   e59f302c    ldr r3, [pc, #44]   ; 848c <main+0x6c>
845c:   e1a00003    mov r0, r3
8460:   e51b1008    ldr r1, [fp, #-8]
8464:   ebffffb3    bl  8338 <printf@plt>
8468:   e51b300c    ldr r3, [fp, #-12]
846c:   e51b2008    ldr r2, [fp, #-8]
8470:   e1520003    cmp r2, r3
8474:   bafffff4    blt 844c <main+0x2c>
8478:   e3a03000    mov r3, #0
847c:   e1a00003    mov r0, r3
8480:   e24bd004    sub sp, fp, #4
8484:   e8bd8800    pop {fp, pc}
8488:   00008500    .word   0x00008500
848c:   00008504    .word   0x00008504

正如您在偏移量 8464 中看到的,二进制代码 ebffffb3 被转换为 bl 8338。我想了解它。

这样做的明确原因是因为我想为以下 python 代码中存在的指令添加额外的正则表达式:

[b"[\x00\x08\x10\x18\x20\x28\x30\x38\x40\x48\x70]{1}\x47", 2, 2], # bx   reg
[b"[\x80\x88\x90\x98\xa0\xa8\xb0\xb8\xc0\xc8\xf0]{1}\x47", 2, 2], # blx  reg
[b"[\x00-\xff]{1}\xbd", 2, 2]                                     # pop {,pc}

正如您所见,二进制中 bx 指令的正则表达式是 "\x00\x08\x10\x18\x20\x28\x30\x38\x40\x48\x70]{1}\x47" 和 blx它是“\x80\x88\x90\x98\xa0\xa8\xb0\xb8\xc0\xc8\xf0”。现在我想再添加两条指令 B 和 BL(这些是 ARM 指令),但我不知道如何将指令转换为类似的二进制代码。 (源代码来自github中的ROPGadget。)

【问题讨论】:

  • 如果你想处理那个 objdump 输出,为什么不把正则表达式应用到反汇编的助记符上呢?也就是说,指令格式当然在指令集参考中有所描述。
  • 如果您打算按照 ROPGadget 的原始目的使用它,您可以添加标签“安全”和/或“利用”。

标签: python regex assembly arm


【解决方案1】:

我试图了解包含二进制代码的二进制文件是如何转换为汇编指令的。

除此之外:所有传统 CPU 硬件都使用二进制逻辑,使用一些标准晶体管配置来实现 NOTNORNAND 等。从这些很少的逻辑门,您可以使用逻辑元素的组合来实现许多更复杂的设备和逻辑。

因此,所有 CPU 都会提取位域(几个位位置,但不一定相邻)并确定它是哪种类型的指令。其他位域将为特定的操作码提供参数。

在“C”中,这会转换为一些掩码和比较操作,您可以在其中提取要检查的位,然后查看位模式是否相等。 GNU 工具(binutils)的具体实现是arm-dis.c

sourceforge project 是一种信息来源,尽管还有其他信息来源(包括 arm-dis.c 文件)。

  |31..28|27..25| 24|23   ..  0|
  +------+------+---+----------+
  |cond  |  101 | L | offset   |
  +------+------+---+----------+

唯一不变的部分是“101”。你的 python reg-ex 看起来像十六进制。前半字节是一个条件,如果为真,指令将采用该条件;否则它就像一个no op。在非常古老的 ARM CPU 文档中存在 never(前导十六进制“F”)条件;它已被弃用以扩展指令集。因此可以忽略前半字节(四位),然后查找“1010b”或 0xa(用于branch)和“1011b”或 0xb(用于bl 或分支和链接)。

例如,arm-dis.c 有,

  {ARM_FEATURE_CORE_LOW (ARM_EXT_V1),
     0x0a000000, 0x0e000000, "b%24'l%c\t%b"},

也就是说,bbl 指令对 ROP 没有那么有用,因为它们没有 register 参数,因此您无法更改控制流。通常,您只需安排将控制流直接放在您的 ROP 小工具中,而不是尝试通过跳转来获取它们。

b Rn的ARM版本是mov pc, rN;但是还有许多其他丰富的构造,例如 add with shift 和使用 ldr 和指针表等。Afaik,当我在 ARM glibc 上运行 ROPGadget 时,它正在检测这些。

【讨论】:

    【解决方案2】:

    引用https://www.ic.unicamp.br/~ranido/mc404/arm/arm-instructionset.pdf

    分支指令包含有符号 2 的补码 24 位偏移。 这被左移两位,符号扩展为 32 位,并添加到 电脑。因此,该指令可以指定 +/- 的分支 32 兆字节。分支偏移量必须考虑预取 操作,这会导致 PC 提前 2 个字(8 个字节) 当前指令。超出 +/- 32Mbytes 的分支必须使用偏移量 或之前已加载到 登记。在这种情况下,PC 应手动保存在 R14 中,如果 需要使用 Link 类型操作的分支。

    让我们看看你的分支示例

    8464:   ebffffb3    bl  8338 <printf@plt>
    

    处理器逻辑采用 24 位偏移量 ffffb3 并将其乘以 4(由于 4 字节对齐,因此编码效率很高)。然后它将这个偏移量添加到当前指令的程序计数器 + 8。这给出了总和:

    ffffffb3 * 4
    --------
    fffffecc +
        8464 +
           8 +
    --------
        8338        QED
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-24
      • 2014-07-20
      • 2016-10-16
      相关资源
      最近更新 更多