我有一个x86-64
可执行文件,我正在尝试使用静态方法对其进行分析。从_start
开始,我看到跳转到0x400648
——PLT
中的一个地址——它包含指令jmp *0x20065a(%rip)
。这个跳跃导致*0x600ca8
,实际上是0x40064e
。这使我们回到PLT
并执行pushq $0x2
。
这就是我的困境:我知道pushq $0x2
指令的存在是为了告诉动态链接器解析.dynsym
表中的第三个条目。问题是该条目中的st_value
字段是0x0
。这个值实际上应该是main
相对于_start
的偏移量,对吧?如果是,如何初始化st_value
字段?
这个值实际上应该是main从_start的偏移量,对吧?
错了。您不能只是从_start
跳到main
——后者需要argc
和argv[]
参数,但还没有人设置它们。libc
初始化代码的任务是:
- 初始化libc本身,创建标准的
FILE
句柄(stdout
等),设置环境等 - 使用正确的参数调用
main
,以及 - 如果/当
main
返回时,用正确的退出代码将程序安排到exit(2)
您看到的实际上是PLT
对__libc_start_main
的调用,它将执行上述所有操作,然后调用main
。你可以在objdump -dr a.out
中看到这一点,它看起来类似于:
00000000004003d0 <_start>:
4003d0: 31 ed xor %ebp,%ebp
4003d2: 49 89 d1 mov %rdx,%r9
4003d5: 5e pop %rsi
4003d6: 48 89 e2 mov %rsp,%rdx
4003d9: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
4003dd: 50 push %rax
4003de: 54 push %rsp
4003df: 49 c7 c0 50 05 40 00 mov $0x400550,%r8
4003e6: 48 c7 c1 c0 04 40 00 mov $0x4004c0,%rcx
4003ed: 48 c7 c7 b4 04 40 00 mov $0x4004b4,%rdi
4003f4: e8 c7 ff ff ff callq 4003c0 <__libc_start_main@plt>
4003f9: f4 hlt
4003fa: 90 nop
4003fb: 90 nop
stvalue字段是如何初始化的?
您可以在这里阅读动态符号解析如何工作的实际细节(搜索"过程链接表";请注意:很少有人真正了解它是如何详细工作的)。