Skip to content

objdump

核心前置概念:BFD 库与 objdump 的底层逻辑

要深入理解 objdump,必须先明确它与 readelf 的核心差异:BFD (Binary File Descriptor) 库依赖。

  • readelf: 专为 ELF 格式设计,直接解析 ELF 文件头。即使 ELF 头部被恶意篡改(如去除了 Section Header 导致文件损坏,常见于逆向题目的反分析混淆),它往往也能强行解析 Program Headers。

  • objdump: 基于 BFD 库运行。这意味着它是一个通用型工具,不仅能处理 ELF,还能处理 Windows PE、Mac Mach-O 等各种架构和格式的二进制文件。但代价是,如果二进制文件的文件头被恶意破坏,BFD 库可能会解析失败,导致 objdump 拒绝工作。

常用参数速查表

短参数 长参数 核心作用
-d --disassemble 反汇编所有包含指令的节(如 .text)
-D --disassemble-all 反汇编所有的节(无论是否为代码)
-M --disassembler-options 指定反汇编选项(如切换 Intel 语法)
-S --source 将源代码与反汇编代码交织显示(需带 -g 编译)
-h --section-headers 显示目标文件各个节的头部摘要信息
-s --full-contents 以十六进制和 ASCII 形式转储所有非空节的内容
-t --syms 显示静态符号表
-T --dynamic-syms 显示动态符号表(常用于分析 .so 库)

核心参数深度解析与实战场景

1. 反汇编双雄:-d vs -D

这是 objdump 最常用的功能:将机器码(Machine Code)翻译成人类可读的汇编代码(Assembly)。

  • -d (Disassemble):

    • 行为: 仅对标记为可执行(Executable)的节进行反汇编。通常只有 .text 节。

    • 应用: 常规的控制流分析、函数逻辑逆向。

  • -D (Disassemble All):

    • 行为: 强制将文件中的所有节(包括 .data、.bss 甚至 .rodata)当作机器指令进行反汇编。

    • 应用: 当恶意代码或 Shellcode 被隐藏在数据段(非正常可执行段)中时,或者二进制文件被加壳(Packed)导致节属性混乱时,-D 是强制提取指令的唯一方式。对于数据段,它会翻译出大量无意义的垃圾指令,需要人工甄别。

2. 汇编风味切换:-M (Disassembler Options)

默认情况下,objdump 在 x86/amd64 架构下输出的是 AT&T 语法(寄存器带 %,立即数带 $,源操作数在前)。

  • 切换为 Intel 语法: objdump -d -M intel <binary>

  • 应用: 绝大多数反汇编引擎(如 IDA Pro, Ghidra)和底层开发都偏好 Intel 语法。强制使用 -M intel 能大幅降低阅读汇编代码时的认知负担。

3. 源码与汇编映射:-S (Source)

将高级语言(如 C 语言)的源代码与底层的汇编指令混合显示。

  • 前提条件: 二进制文件在编译时必须包含调试信息(例如使用了 gcc -g)。

  • 应用: 非常适合在学习《汇编语言设计》或底层系统编程时,验证特定的 C 语言控制流(如 switch-case、for 循环)或数据结构到底被编译器翻译成了什么样的机器码序列。

4. 节头部信息:-h (Section Headers)

虽然 readelf -S 也能看,但 objdump -h 提供了一种更紧凑的 BFD 视角的摘要。

  • 核心关注 VMA 与 LMA:

    • VMA (Virtual Memory Address): 运行时的虚拟地址。

    • LMA (Load Memory Address): 加载时的物理地址(主要在嵌入式开发、裸机编程和编写 Bootloader 时极其重要;在普通的 Linux 用户态程序中,VMA 和 LMA 通常是一致的)。

5. 十六进制全量转储:-s (Full Contents)

转储文件的原始字节内容。

  • 应用: objdump -s -j .rodata <binary> (-j 指定特定的节)。当你不只需要字符串(用 strings)或简单的查看,而是需要精确提取某个偏移量处的硬编码密钥、魔法字节(Magic Bytes)或跳转表数据时,这是一个非常直观的命令。

6. 符号表解析:-t 与 -T

解析程序内部的符号引用。

  • 应用:

    • 找目标: 在编写 Exploit 时,如果二进制文件没有被 strip,可以通过 objdump -t 快速找到隐藏的后门函数(如 get_shell)的虚拟地址。

    • 查库引用: objdump -T 专门看动态符号表,能迅速确认程序导入了哪些 libc 函数(如是否有 system、execve 供利用)。