You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于PLT与GOT跳转的技术问询:`jmp DWORD PTR [ebx+0xc]`如何将控制权转移至GOT?

32位ELF动态链接中PLT跳转GOT时EBX为0的问题分析

看起来你在调试32位ELF程序的动态链接流程时卡在了关键节点:进入puts@plt后执行jmp DWORD PTR [ebx+0xc]时,EBX的值居然是0,导致跳转地址完全不符合预期。我们来一步步拆解这个问题,找到疏漏点:

核心原理:EBX在32位动态链接中的作用

在32位x86的ELF动态链接机制里,EBX寄存器是专门用来存储GOT(全局偏移表)基地址的。所有PLT中的跳转指令都依赖EBX+偏移量来定位GOT条目,这是位置无关代码(PIC)实现动态符号寻址的核心逻辑。

为什么你的EBX是0?—— 看main函数里的GOT基址初始化流程

从你提供的main函数反汇编代码来看,GOT基址是在main函数执行过程中主动设置的,关键步骤如下:

11ac:	call   11d9 <__x86.get_pc_thunk.ax>  ; 将当前PC值存入EAX寄存器
11b1:	add    eax,0x2e4f                   ; 通过偏移量计算出GOT的基地址
11c0:	mov    ebx,eax                      ; 把GOT基地址存入EBX,这一步是关键!
11c2:	call   1030 <puts@plt>              ; 调用puts@plt,此时EBX已经正确初始化

正常情况下,当执行到call puts@plt时,EBX应该已经被设置为GOT的起始地址(你的程序中GOT起始于0x4000),所以[ebx+0xc]就是0x400c——也就是GOT中对应puts的条目。

你调试时EBX为0,大概率是以下原因之一:

  • 断点设置时机错误:你可能在main函数还没执行到mov ebx,eax时,就提前进入了PLT(比如误将断点打在了程序启动的初始化阶段)。
  • 调试操作失误:调试过程中不小心修改了EBX的值,或者跳过了设置EBX的关键指令。
  • 第一次调用PLT的特殊流程:第一次调用puts@plt时,GOT中的0x400c条目其实指向的是puts@plt内部的push 0x0指令(地址1036),这是动态链接器的解析流程:
    1. 执行jmp DWORD PTR [ebx+0xc]跳转到1036
    2. 执行push 0x0(这个0是puts在重定位表中的索引)
    3. 跳转到PLT的通用解析入口1020,触发动态链接器解析puts的真实地址
    4. 解析完成后,动态链接器会把puts的真实地址写入GOT的0x400c条目,下次调用就直接跳转到真实地址

验证方法

你可以在调试时做以下操作来确认问题:

  • 在main函数的mov ebx,eax指令(地址11c0)处设置断点,执行完这条指令后查看EBX的值,应该等于0x4000(你的GOT起始地址)。
  • 接着单步执行到call puts@plt,进入PLT后再查看EBX,此时应该还是0x4000,[ebx+0xc]就是0x400c,对应GOT中的条目。

总结

你的流程疏漏点在于没有确认EBX是否已经被正确初始化——正常调用puts@plt时,EBX必须已经被main函数设置为GOT基址。如果调试时EBX为0,说明你在执行到call puts@plt之前,GOT基址的初始化步骤没有被正确执行。

内容的提问来源于stack exchange,提问作者user3488903

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 19:12:32