将汇编指令BL和B转换为二进制

时间:2015-10-09 16:48:31

标签: python regex assembly arm

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

例如,这里是基于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。)

2 个答案:

答案 0 :(得分:1)

  

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

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

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

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

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

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

唯一不变的部分是&#39; 101 &#39;。你的python reg-ex看起来像十六进制。前导半字节是一个条件,如果该指令将为真,则该条件;否则它就像 no op 。非常旧的ARM CPU文档中存在 never (前导十六进制&#39; F&#39;)条件;不推荐使用它来扩展指令集。因此可以忽略前导半字节(四位),然后查找“1010b”和“#10; 1010b”。或0xa(对于b牧场)和&#39; 1011b&#39;或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;但是还有许多其他丰富的构造,例如添加移位和使用带有指针表的ldr等等.Afaik,当我在ARM glibc上运行时,ROPGadget正在检测这些。

答案 1 :(得分:0)

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

  

分支指令包含带符号的2的补码24位偏移。   这会向左移两位,符号扩展为32位,并添加到   电脑。因此该指令可以指定+/-的分支   32M字节。分支偏移量必须考虑预取   操作,使PC在2字(8字节)之前   现行指示。超过+/- 32Mbytes的分支必须使用偏移量   或先前已加载到的绝对目的地   寄存器。在这种情况下,如果a,PC应手动保存在R14中   需要具有链接类型操作的分支。

那么让我们来看看你的分支示例

ntdll.dll

处理器逻辑采用24位偏移8464: ebffffb3 bl 8338 <printf@plt> 并将其乘以4(由于4字节对齐而有效编码)。然后它将此偏移量添加到当前指令的程序计数器+8。这给出了总和:

ffffb3