Introduction to objdump
This hands-on lab introduces the Linux objdump
command, a vital tool for system administrators and developers needing to dissect object file internals. You'll begin with the core purpose of objdump
, then delve into its command syntax and options, culminating in a detailed analysis of objdump
output from a basic C program. This tutorial hones fundamental skills applicable to scripting, programming, software debugging, and reverse engineering tasks performed by systemadmin and development teams.
Understanding the Role of the objdump Command
This section illuminates the function of the objdump
command within the Linux environment. objdump
serves as a robust utility for scrutinizing the makeup of object files – binary files containing compiled machine code and associated data.
A primary application of objdump
is disassembling machine code, transforming binary instructions into a more easily interpreted, human-readable representation. This capability proves invaluable for deciphering program logic, pinpointing software bugs, and even conducting reverse engineering operations on software components.
To illustrate, we'll construct a straightforward C program and leverage objdump
to dissect its contents.
Begin by generating a file named hello.c
within the ~/project
directory, populated with the subsequent code:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
Subsequently, compile the C code utilizing the gcc
compiler:
cd ~/project
gcc -o hello hello.c
Now, invoke the objdump
command to scrutinize the hello
executable:
objdump -d hello
Sample output:
hello: file format elf64-x86-64
Disassembly of section .init:
0000000000001000 <_init>:
1000: f3 0f 1e fa endbr64
1004: 48 83 ec 08 sub $0x8,%rsp
1008: 48 8b 05 d9 2f 00 00 mov 0x2fd9(%rip),%rax ## 3fe8 <__gmon_start__>
100f: 48 85 c0 test %rax,%rax
1012: 74 02 je 1016 <_init+0x16>
1014: ff d0 callq *%rax
1016: 48 83 c4 08 add $0x8,%rsp
101a: c3 retq
As evidenced, objdump
has disassembled the hello
executable, displaying the underlying machine instructions the processor will execute. This level of detail facilitates understanding program behavior and diagnosing potential issues.
Next, we'll examine the command syntax and available options within objdump
.
Dissecting objdump Syntax and Options
This segment explores the syntax and customizable options of the objdump
command. Numerous options exist to fine-tune output and isolate specific information within the object file.
First, consider the fundamental structure of the objdump
command:
objdump [options] file
Key objdump
options include:
-d
or--disassemble
: Disassembles the executable code into assembly language.-S
or--source
: Integrates source code alongside the disassembly for easier comprehension.-t
or--syms
: Reveals the symbol table's contents, mapping names to addresses.-x
or--all-headers
: Outputs all header information, offering a comprehensive file overview.-h
or--section-headers
: Presents section headers, detailing file segmentation.
Apply these options to the hello
executable created earlier:
## Display the disassembly with source code
objdump -dS hello
## Display the symbol table
objdump -t hello
## Display all available header information
objdump -x hello
Illustrative output:
hello: file format elf64-x86-64
Disassembly of section .text:
0000000000001000 <_init>:
1000: f3 0f 1e fa endbr64
1004: 48 83 ec 08 sub $0x8,%rsp
1008: 48 8b 05 d9 2f 00 00 mov 0x2fd9(%rip),%rax ## 3fe8 <__gmon_start__>
100f: 48 85 c0 test %rax,%rax
1012: 74 02 je 1016 <_init+0x16>
1014: ff d0 callq *%rax
1016: 48 83 c4 08 add $0x8,%rsp
101a: c3 retq
0000000000001020 <__libc_csu_init>:
1020: f3 0f 1e fa endbr64
1024: 41 57 push %r15
1026: 4c 8d 3d 93 2c 00 00 lea 0x2c93(%rip),%r15 ## 3cc0 <__frame_dummy_init_array_entry>
102d: 41 56 push %r14
102f: 49 89 e6 mov %rsp,%r14
1032: 41 55 push %r13
1034: 41 54 push %r12
1036: 4c 8d 25 83 2c 00 00 lea 0x2c83(%rip),%r12 ## 3cc0 <__frame_dummy_init_array_entry>
103d: 55 push %rbp
103e: 48 8d 2d 83 2c 00 00 lea 0x2c83(%rip),%rbp ## 3cc8 <__do_global_dtors_aux_fini_array_entry>
1045: 53 push %rbx
1046: 4c 29 e5 sub %r12,%rbp
1049: 48 83 ec 08 sub $0x8,%rsp
104d: e8 ae fe ff ff callq f00 <_init>
1052: 48 c1 fd 03 sar $0x3,%rbp
1056: 74 1f je 1077 <__libc_csu_init+0x57>
1058: 31 db xor %ebx,%ebx
105a: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
105f: 4c 89 f2 mov %r14,%rdx
1062: 4c 89 ee mov %r13,%rsi
1065: 44 89 e7 mov %r12d,%edi
1068: 41 ff 14 df callq *(%r15,%rbx,8)
106c: 48 83 c3 01 add $0x1,%rbx
1070: 48 39 dd cmp %rbx,%rbp
1073: 75 ea jne 105f <__libc_csu_init+0x3f>
1075: 48 83 c4 08 add $0x8,%rsp
1079: 5b pop %rbx
107a: 5d pop %rbp
107b: 41 5c pop %r12
107d: 41 5d pop %r13
107f: 41 5e pop %r14
1081: 41 5f pop %r15
1083: c3 retq
0000000000001084 <__libc_csu_fini>:
1084: f3 0f 1e fa endbr64
1088: c3 retq
0000000000001089 <main>:
1089: f3 0f 1e fa endbr64
108d: 55 push %rbp
108e: 48 89 e5 mov %rsp,%rbp
1091: bf 00 00 00 00 mov $0x0,%edi
1096: e8 85 fe ff ff callq f20 <puts@plt>
109b: b8 00 00 00 00 mov $0x0,%eax
10a0: 5d pop %rbp
10a1: c3 retq
10a2: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%rax,%rax,1)
10ac: 0f 1f 40 00 nopl 0x0(%rax)
Disassembly of section .fini:
00000000000010b0 <_fini>:
10b0: f3 0f 1e fa endbr64
10b4: 48 83 ec 08 sub $0x8,%rsp
10b8: 48 83 c4 08 add $0x8,%rsp
10bc: c3 retq
This output exemplifies the disassembled code, accompanied by source lines. A powerful aid for detailed code analysis.
The next section provides an in-depth analysis of the objdump
output when applied to our hello
program.
Deep Dive: Analyzing objdump Output from a Simple C Program
In this concluding step, we perform an extensive analysis of objdump
output specifically concerning the hello
program.
Let's re-examine the disassembly output:
objdump -d hello
Representative output:
hello: file format elf64-x86-64
Disassembly of section .text:
0000000000001089 <main>:
1089: f3 0f 1e fa endbr64
108d: 55 push %rbp
108e: 48 89 e5 mov %rsp,%rbp
1091: bf 00 00 00 00 mov $0x0,%edi
1096: e8 85 fe ff ff callq f20 <puts@plt>
109b: b8 00 00 00 00 mov $0x0,%eax
10a0: 5d pop %rbp
10a1: c3 retq
This output represents the disassembled main
function. A breakdown of the instructions follows:
f3 0f 1e fa
: Theendbr64
instruction, a security precaution against certain attacks.55
:push %rbp
, storing the base pointer on the stack.48 89 e5
:mov %rsp,%rbp
, setting the base pointer to the stack pointer.bf 00 00 00 00
:mov $0x0,%edi
, setting the first argument for theputs
function.e8 85 fe ff ff
:callq f20 <puts@plt>
, calling theputs
function to display "Hello, World!".b8 00 00 00 00
:mov $0x0,%eax
, setting themain
function's return value to 0.5d
:pop %rbp
, restoring the base pointer from the stack.c3
:retq
, returning from themain
function.
By interpreting the disassembly output, you gain insights into the low-level workings of the hello
program. This understanding is beneficial for debugging or reverse engineering.
Summary
This lab provided an introduction to the objdump
command within Linux, highlighting its utility in analyzing object files. You constructed a simple C program, compiled it, and utilized objdump
to disassemble its executable code, granting a peek into its low-level operations. Furthermore, the lab explored the syntax and options within objdump
, facilitating the extraction of symbol tables and other file details. Ultimately, this lab equipped you with a fundamental understanding of employing objdump
for executable file analysis on Linux, a valuable skill for any systemadmin working within the Linux ecosystem or developers debugging their applications.