如何确定从二进制调用哪个glibc函数?

时间:2015-09-23 20:56:55

标签: binaryfiles elf

我们有什么方法可以说从ARM elf二进制文件调用哪个glibc函数?例如,请考虑以下反汇编:

8300 <printf@plt-0x40>:
   ....
8320:   e28fc600    add ip, pc, #0, 12
8324:   e28cca08    add ip, ip, #8, 20  ; 0x8000
8328:   e5bcf344    ldr pc, [ip, #836]! ; 0x344

   ....
83fc <main>:
   ...
8424:ebffffbd   bl  8320 <_init+0x2c>

在这里,我们怎么说bl 8320是对printf的调用?这些信息是否存储在ELF二进制文件中?

2 个答案:

答案 0 :(得分:1)

  

我们有什么方法可以说从ARM elf二进制文件调用哪个glibc函数?

不是。

您可以简单地询问“二进制文件调用外部函数”,如下所示:

nm -D a.out | grep ' U '

定义了未定义函数的库记录的,实际上可以更改。例如,您可以使用LD_PRELOAD=libfoo.so注入printf中定义的其他libfoo.so,并抢占glibc printf的定义。

答案 1 :(得分:1)

TLDR:您必须计算GOT条目的地址(存储在IP但PLT中)并找到与此GOT条目对应的重定位条目。此重定位条目引用符号名称(通过动态符号表和动态字符串表)。

你的例子

此PLT条目计算IP寄存器中PLTGOT条目的地址:

8320:   e28fc600    add ip, pc, #0, 12
8324:   e28cca08    add ip, ip, #8, 20  ; 0x8000
8328:   e5bcf344    ldr pc, [ip, #836]! ; 0x344

这计算地址的GOT条目:0x8320 + 0x8 + 0x8000 + 0x344 = 0x1066c。重定位表中有一个重定位条目,它将此GOT条目绑定到给定的符号。

另一个例子

让我们从我的libc中获取这个PLT条目:

00015b98 :
   15b98:       e28fc601        add     ip, pc, #1048576        ; 0x100000
   15b9c:       e28cca2f        add     ip, ip, #192512 ; 0x2f000
   15ba0:       e5bcf46c        ldr     pc, [ip, #1132]!        ; 0x46c

GOT条目的地址是:0x15b98 + 0x8 + 0x100000 + 0x2f000 + 0x46c = 0x14500c。

如果你想知道为什么“+ 0x8”,这是because

  

在ARM状态下,PC的值是当前的地址   指令加上8个字节。

让我们看一下重定位条目:

 Offset     Info    Type            Sym.Value  Sym. Name
0014500c  0001e416 R_ARM_JUMP_SLOT   00077c28   realloc

所以这个PLT条目是realloc的PLT,这是我们期望得到的! \ O /

查找符号名称

您可能想知道如何找到符号名称。在我的示例中,info字段为0x0001e416:此重定位使用动态符号表(.dynsym)中的符号条目0x1e4 = 484

   Num:    Value  Size Type    Bind   Vis      Ndx Name
   484: 00077c28   760 FUNC    GLOBAL DEFAULT   11 realloc@@GLIBC_2.4

实际上,直接在符号表中找不到realloc字符串,但在字符串表(.dynstr)中找不到。符号表存储字符串表中字符串的偏移量。