我们有什么方法可以说从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二进制文件中?
答案 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
)中找不到。符号表存储字符串表中字符串的偏移量。