出于测试目的,我修改了由llvm链接器lld生成的PLT存根。
之前的存根是:
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index>
0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0]
将程序与此(原始)存根链接并使用objdump
进行检查会产生如下结果:
00000000002012d0 <printf@plt>:
2012d0: ff 25 62 0d 00 00 jmpq *0xd62(%rip) # 202038 <__TMC_END__+0x28>
2012d6: 68 02 00 00 00 pushq $0x2
2012db: e9 c0 ff ff ff jmpq 2012a0 <_fini+0x10>
我通过简单地在末尾添加NOP来修改PLT存根:
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index>
0xe9, 0x00, 0x00, 0x00, 0x00, // jmpq plt[0]
0x0f, 0x1f, 0x40, 0x00 // nop
我确保修改PltEntrySize
变量,以便它反映大小的变化。使用此修改链接和运行程序似乎工作正常。
但是,当我尝试用objdump
检查链接程序的反汇编时,我看到一些奇怪的东西:
00000000002012d0 <printf@plt>:
2012d0: cc int3
2012d1: ff (bad)
2012d2: ff (bad)
2012d3: ff 0f decl (%rdi)
2012d5: 1f (bad)
2012d6: 40 00 ff add %dil,%dil
2012d9: 25 5a 0d 00 00 and $0xd5a,%eax
2012de: 68 02 00 00 00 pushq $0x2
2012e3: e9 b8 ff ff ff jmpq 2012a0 <_fini+0x10>
2012e8: 0f 1f 40 00 nopl 0x0(%rax)
objdump
将PLT存根的地址解释为0x2012d0
,但真正的printf@plt
地址位于0x2012d8
!这由readelf -s
确认:
Symbol table '.dynsym' contains 7 entries:
Num: Value Size Type Bind Vis Ndx Name
...
6: 00000000002012d8 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
objdump
从哪里获取信息?很可能是我忘记修改链接器中的内容。
答案 0 :(得分:0)
出于测试目的,我修改了由llvm链接器lld生成的PLT存根。
plt
条目的大小和布局由ABI设置(见第79页),并且无法更改。
使用此修改链接和运行程序似乎工作正常。
我怀疑任何非平凡程序都会在您的修改中正确运行 - 动态加载程序采用ABI plt
布局,并且在给定伪造plt
时应该崩溃并刻录。