
pwndbg got 命令实战全面解析 ELF GOT 全局偏移表状态与 RELRO 防护【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbggot是 pwndbg 提供的 LINUX 类别调试命令用于展示目标进程中全局偏移表Global Offset TableGOT的真实状态包括每个 GOT 条目对应的符号名、运行时地址与当前指向的目标以及目标文件的 RELRORelocation Read-Only防护等级。本文基于 got 命令文档 并结合命令实现源码完整讲解其全部参数、典型用法、输出解读与底层 ELF 重定位解析原理帮助你在漏洞利用与逆向分析中快速定位 GOT 劫持点与可写条目。GOT 是什么理解本命令的核心对象GOT 是 ELF 动态链接机制中的一张运行时数据表用于存放全局符号与外部函数在进程地址空间中的真实地址。当程序调用puts、printf等 libc 函数时会先经过过程链接表PLT桩代码PLT 桩通过 GOT 中的跳转槽jump slot间接跳转到目标函数。在延迟绑定lazy binding机制下GOT 条目最初指向 PLT 内部的解析桩代码首次调用后由动态链接器将其改写为真实函数地址。从 pwndbg/lib/got.py 中定义的RelocationType枚举可以看到pwndbg 关注的 GOT 相关重定位类型主要有三种重定位类型枚举值典型 x86-64 形式说明JUMP_SLOT1R_X86_64_JUMP_SLOT函数调用跳转槽PLT 桩依赖它完成间接跳转GLOB_DAT2R_X86_64_GLOB_DAT全局数据符号引用如__libc_start_main、全局变量地址IRELATIVE3R_X86_64_IRELATIVE间接函数解析用于 IFUNC 机制下按 CPU 特性选择函数实现在利用视角下GOT 是经典的攻击面如果能改写某个 GOT 条目就可以把puts劫持为system或 one_gadget从而控制程序执行流。而 RELRO 防护决定 GOT 是否可写——这正是got命令输出中“GOT protection”一栏要回答的问题。got命令的职责就是把目标进程中所有 GOT 条目的状态符号名、地址、当前值一次性展示出来并明确标注当前防护等级。got 命令速览完整用法与参数说明命令完整用法如下与文档一致并可在 pwndbg/commands/got.py 的 argparse 定义中验证usage: got [-h] [-p PATH_FILTER | -a] [-r] [symbol_filter]位置参数参数说明symbol_filter按符号名过滤结果支持子串匹配。默认即不过滤可选参数短选项长选项说明-h--help显示帮助信息并退出-p--path按库/目标文件路径过滤例如-p libc。默认-a--all处理所有已加载的库与目标文件包括主可执行文件本身-r--show-readonly同时显示只读条目默认会过滤掉只读条目需要注意两个关键的默认行为与约束-p与-a互斥在源码中二者被加入同一个add_mutually_exclusive_grouppwndbg/commands/got.py同时指定会直接报错默认只显示可写条目GOT 中已被 RELRO 保护只读的条目默认不展示需要使用-r才能看到默认只处理主程序不带任何选项时got只展示主可执行文件的 GOT需要同时查看 libc 等共享库时应配合-p或-apwndbg/commands/got.py。实战示例四种典型用法详解以下示例全部来自命令文档并在实现中注册为examplespwndbg/commands/got.py1.got查看主程序所有可写 GOT 条目got Print all writable GOT entries in the executable.这是最常用的形式返回主可执行文件中可写的 GOT 条目。在 Partial RELRO 下.got.plt中的跳转槽仍然可写这正是传统 ret2dlresolve 与 GOT 覆写利用的落点。运行时会先打印当前生效的过滤条件例如Filtering out read-only entries (display them with -r or --show-readonly)2.got -r puts按符号名过滤并包含只读条目got -r puts Print all GOT entries that contain the string puts.-r让只读条目也参与展示puts作为符号名子串过滤器。若目标文件是 Full RELROGOT 条目全部只读此时不加-r可能什么都看不到-r是查看完整 GOT 状态的关键。3.got -p libc查看指定共享库的可写 GOT 条目got -p libc Print all writable GOT entries used by libc. (And any other loaded object files that contain the string libc in their path).-p按库文件路径做子串匹配因此-p libc会命中所有路径中包含libc的已加载目标文件如libc.so.6、libm.so.6等。如果过滤条件没有命中任何已加载库pwndbg 会给出错误提示并列出当前可用的共享库列表供参考pwndbg/commands/got.py。4.got -ra查看整个地址空间中所有 GOT 条目got -ra Print all GOT entries in the address space.-r与-a组合使用-a让 pwndbg 遍历所有已加载的共享库和主程序-r关闭只读过滤。这是最全面的“全景”输出适合在逆向分析时建立完整的符号解析图谱。输出解读GOT 防护等级、地址、符号与目标值got命令的输出由 pwndbg/commands/got.py 生成格式如下State of the GOT of /path/to/binary: GOT protection: Full RELRO | Found 12 GOT entries passing the filter [0x7ffff7fd2a60] putsGLIBC_2.2.5 - 0x7ffff7e55e30 puts [0x7ffff7fd2a68] printfGLIBC_2.2.5 - 0x7ffff7e4f810 printf每一部分的含义第一行当前处理的目标文件路径主程序或过滤命中的库文件第二行RELRO 防护等级 通过过滤的 GOT 条目数量。RELRO 等级通过 pwndbg 对 pwntools 的封装获取pwndbg/wrappers/checksec.py取值有三种Full RELROGOT 在重定位完成后整体只读条目不可被 GOT 覆写攻击利用Partial RELRO.got只读但.got.plt可写跳转槽仍是攻击面No RELROGOT 完全可写防护最弱。输出中防护等级带有颜色标注Full RELRO 显示为成功色message.onPartial RELRO 显示为警告色message.warn无 RELRO 时无特殊着色pwndbg/commands/got.py后续每一行[GOT 条目地址] 符号名 - GOT 条目当前值。箭头右侧的当前值经由 pwndbg/chain.py 的指针链格式化函数输出会尝试解引用并增强显示为可读符号例如0x7ffff7e55e30 puts一眼即可确认该 GOT 槽当前绑定到了哪个函数条目按地址升序排列便于对照 ELF 布局阅读pwndbg/commands/got.py。值得注意的细节是当过滤了只读条目或指定了路径/符号过滤时pwndbg 会先打印一行提示信息再输出结果pwndbg/commands/got.py这有助于避免误解“条目为何变少”。源码级原理got 命令的处理流程got命令的实现位于 pwndbg/commands/got.py其_got()函数处理单个目标文件的流程如下获取本地文件调用pwndbg.aglib.file.get_file(path, try_local_pathTrue)获取目标文件。try_local_pathTrue意味着在本地调试时直接使用本机路径而在远程调试场景下则会尝试从远端下载该文件保证后续 ELF 解析始终有可读的磁盘文件读取防护信息通过pwndbg.wrappers.checksec.relro_status()与pie_status()得到 RELRO 与 PIE 状态解析 GOT 条目调用pwndbg.lib.got.get_got_entry(local_path)从 ELF 重定位节中提取全部 GOT 条目详见下一节计算装载基址对主程序若pie_status包含PIE enabled基址取pwndbg.aglib.proc.binary_base_addr()否则基址为 0pwndbg/commands/got.py对共享库基址取自 vmmap 中对应目标文件映射页的起始地址page.startpwndbg/commands/got.py最终每个 GOT 条目的运行时地址为offset bin_base_offset即“文件内偏移 装载基址”应用过滤默认过滤只读条目通过pwndbg.aglib.vmmap.find(address).write判断该地址所在页是否可写不可写则跳过pwndbg/commands/got.py按符号名子串过滤if symbol_filter not in name: continuepwndbg/commands/got.py对无符号名的IRELATIVE条目沿用历史行为生成*ABS*i386或*ABS*0x值形式的占位名pwndbg/commands/got.py排序输出按地址升序排序后逐行打印。此外iter_objfiles()pwndbg/commands/got.py负责枚举需要处理的共享库它遍历 vmmap 中的内存映射页跳过主 ELF、跳过[vdso]等虚拟目标文件、按 objfile 去重并通过读取页起始 4 字节是否为\x7fELF魔数来判断是否为磁盘背书的 ELF 映射。这一逻辑保证了-a模式遍历的是真实加载的 ELF 库而不是内存中的伪映射。底层解析get_got_entry 如何提取重定位信息GOT 条目的数据来源是 pwndbg/lib/got.py 中的get_got_entry()它基于 pyelftools 直接解析 ELF 文件主要步骤包括遍历重定位节迭代 ELF 的所有节section仅处理RelocationSection类型的节.rela.plt、.rela.dyn等符号表查名通过节头中的sh_link找到关联符号表用rel[r_info_sym]索引取出符号得到符号名解析符号版本利用.gnu.versionGNUVerSymSection与.gnu.version_rGNUVerNeedSection两张节还原出符号版本。版本索引 0/1 是特殊值local/global大于 1 时通过vna_other与版本索引的对应关系查得版本名拼装成putsGLIBC_2.2.5这样的完整符号名pwndbg/lib/got.py。若解析失败则静默降级为纯符号名分类重定位类型用 pyelftools 的describe_reloc_type()把整数类型的r_info_type翻译成R_X86_64_JUMP_SLOT这类可读字符串再按RelocationType枚举名做子串匹配归类到JUMP_SLOT/GLOB_DAT/IRELATIVE三个桶中返回结构化数据每个条目包含offset重定位目标在文件中的偏移、info、type、value符号在符号表中的值、name、addend六个字段。单元测试如何验证这一实现仓库在 tests/unit_tests/test_got.py 中为 GOT 解析提供了自动化测试基于tests/binaries/host/reference-binary.native.out构建产物校验get_got_entry返回结构与字段类型offset/value为整数、name为字符串且offset 0断言结果中必须包含puts与__libc_start_main符号验证 GOT 条目标识的正确性断言结果中存在带GLIBC版本后缀的符号验证符号版本解析路径确实生效。这意味着文档中got -r puts示例所依赖的符号提取与版本解析能力是有一整套可回归测试背书的。与 GOT 相关的其他 pwndbg 能力checksec 命令用于查看二进制整体安全属性NX、Canary、PIE、RELRO是got输出中 RELRO 状态的同源信息来源gotplt 命令从另一个角度展示 GOT 与 PLT 的映射关系可与got配合阅读track-got 命令 与 GOT 调用追踪子系统got是“静态查看状态”而 GOT 追踪实现在 pwndbg/gdblib/got.py 与 pwndbg/commands/got_tracking.py是“动态监控访问”——它通过给 GOT 条目安装写监视点watchpoint并配合陷俘地址trap address重定向记录每一次经由 GOT 的跨库调用及其调用栈。二者分别回答“GOT 现在长什么样”与“GOT 正在被谁调用”这两个问题。小结got命令虽小却是理解程序动态链接状态、评估 RELRO 防护、定位 GOT 覆写攻击面的高效入口默认视角聚焦主程序可写条目-r打开只读视角补全全景-p/-a把视野扩展到 libc 等全部共享库。配合本仓库中 pwndbg/commands/got.py 与 pwndbg/lib/got.py 的实现你可以清楚知道每个输出字段的来源与过滤语义从而在实战调试中准确解读 GOT 的每一个字节。【免费下载链接】pwndbgExploit Development and Reverse Engineering with GDB LLDB Made Easy项目地址: https://gitcode.com/GitHub_Trending/pw/pwndbg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考