ELF 文件数据分析: 全局变量

本文详细介绍了如何使用C语言编写简单程序并进行编译,随后通过objdump命令分析输出的ELF文件,解读.text、.rodata、.data和.bss段的含义,并展示了如何定位全局变量和静态变量的内存地址。
部署运行你感兴趣的模型镜像

先编译一个简单的 C 程序。

#include <stdio.h>

char* s = "Hello, World!";
char* x;
int i = 0x1234;

int main(int argc, char* argv[])
{
 x = "Ubuntu";

 printf("%s/n", s);
 return 0;
}


编译后,使用 objdump 输出 ELF Section 信息。我们通常关心只有 .text, .rodata, .data, .bss 这几个段。

yuhen@yuhen-desktop:~/Learn.c$ objdump -h hello

hello: file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
 12 .text 0000018c 08048310 08048310 00000310 2**4
 CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .rodata 0000001d 080484b8 080484b8 000004b8 2**2
 CONTENTS, ALLOC, LOAD, READONLY, DATA
 22 .data 00000010 0804a00c 0804a00c 0000100c 2**2
 CONTENTS, ALLOC, LOAD, DATA
 23 .bss 0000000c 0804a01c 0804a01c 0000101c 2**2
 ALLOC


Section 说明:

  • .text: 程序执行代码。
  • .rodata: 代码中的字符串常量等。
  • .data: 初始化的全局变量。
  • .bss: 未初始化的全局变量。

我们反汇编看看 main 函数中的相关代码。

yuhen@yuhen-desktop:~/Learn.c$ objdump -d -M intel hello > hello.asm 

yuhen@yuhen-desktop:~/Learn.c$ cat hello.asm | less # 我们只关心 main,其他代码省略

080483c4 <main>:
 80483c4: 8d 4c 24 04 lea ecx,[esp+0x4]
 80483c8: 83 e4 f0 and esp,0xfffffff0
 80483cb: ff 71 fc push DWORD PTR [ecx-0x4]
 80483ce: 55 push ebp
 80483cf: 89 e5 mov ebp,esp
 80483d1: 51 push ecx
 80483d2: 83 ec 04 sub esp,0x4

 80483d5: c7 05 24 a0 04 08 ce mov DWORD PTR ds:0x804a024,0x80484ce ; 注释: x = "Ubuntu"
 80483dc: 84 04 08
 80483df: a1 14 a0 04 08 mov eax,ds:0x804a014 ; 注释: s 地址
 80483e4: 89 04 24 mov DWORD PTR [esp],eax
 80483e7: e8 08 ff ff ff call 80482f4 <puts@plt>
 
 80483ec: b8 00 00 00 00 mov eax,0x0
 80483f1: 83 c4 04 add esp,0x4
 80483f4: 59 pop ecx
 80483f5: 5d pop ebp
 80483f6: 8d 61 fc lea esp,[ecx-0x4]
 80483f9: c3 ret
 80483fa: 90 nop
 80483fb: 90 nop
 80483fc: 90 nop
 80483fd: 90 nop
 80483fe: 90 nop
 80483ff: 90 nop


我们先关注全局变量 s,其地址是:

0x804a014 - 0x0804a00c (.data 基地址) + 0x0000100c (.data Offset) = 0x1014

我们看看二进制文件中对应位置的信息。

yuhen@yuhen-desktop:~/Learn.c$ xxd -g 1 -s 0x1014 -l 100 hello

0001014: c0 84 04 08 34 12 00 00 00 47 43 43 3a 20 28 55 ....4....GCC: (U
0001024: 62 75 6e 74 75 20 34 2e 33 2e 33 2d 35 75 62 75 buntu 4.3.3-5ubu
0001034: 6e 74 75 34 29 20 34 2e 33 2e 33 00 00 47 43 43 ntu4) 4.3.3..GCC


指向 0x080484c0,我们计算一下该字符串的 offset。

0x080484c0 - 0x080484b8 (.rodata 基地址) + 0x000004b8 (.rodata Offset) = 0x04c0

看看数据。

yuhen@yuhen-desktop:~/Learn.c$ xxd -g 1 -s 0x04c0 -l 100 hello

00004c0: 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 00 55 62 Hello, World!.Ub
00004d0: 75 6e 74 75 00 00 00 00 00 00 00 00 00 00 00 00 untu............


接下来看看未出化全局变量 x 的情况。

mov DWORD PTR ds:0x804a024,0x80484ce ; 注释: x = "Ubuntu"


很显然,该变量地址 (0x804a024) 在 .bss 段 (0x0804a01c ~ 0x0804a028)。字符串 "Ubuntu" 地址是 0x80484ce,我们可以计算其 Offset。

0x80484ce - 0x080484b8 (.rodata 基地址) + 0x000004b8 (.rodata Offset) = 0x04ce

yuhen@yuhen-desktop:~/Learn.c$ xxd -g 1 -s 0x04ce -l 100 hello

00004ce: 55 62 75 6e 74 75 00 00 00 00 00 00 00 00 00 00 Ubuntu..........
00004de: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................


全局变量和静态变量的地址在编译时就决定了的。我们还可以用 readelf 命令获取更详细的 ELF 文件信息。

yuhen@yuhen-desktop:~/Learn.c$ readelf -e hello

ELF Header:
 Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
 Class: ELF32
 Data: 2's complement, little endian
 Version: 1 (current)
 OS/ABI: UNIX - System V
 ABI Version: 0
 Type: EXEC (Executable file)
 Machine: Intel 80386
 Version: 0x1
 Entry point address: 0x8048310
 Start of program headers: 52 (bytes into file)
 Start of section headers: 6004 (bytes into file)
 Flags: 0x0
 Size of this header: 52 (bytes)
 Size of program headers: 32 (bytes)
 Number of program headers: 8
 Size of section headers: 40 (bytes)
 Number of section headers: 36
 Section header string table index: 33

Section Headers:
 [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
 [ 0] NULL 00000000 000000 000000 00 0 0 0
 [ 1] .interp PROGBITS 08048134 000134 000013 00 A 0 0 1
 [ 2] .note.ABI-tag NOTE 08048148 000148 000020 00 A 0 0 4
 [ 3] .hash HASH 08048168 000168 000028 04 A 5 0 4
 [ 4] .gnu.hash GNU_HASH 08048190 000190 000020 04 A 5 0 4
 [ 5] .dynsym DYNSYM 080481b0 0001b0 000050 10 A 6 1 4
 [ 6] .dynstr STRTAB 08048200 000200 00004a 00 A 0 0 1
 [ 7] .gnu.version VERSYM 0804824a 00024a 00000a 02 A 5 0 2
 [ 8] .gnu.version_r VERNEED 08048254 000254 000020 00 A 6 1 4
 [ 9] .rel.dyn REL 08048274 000274 000008 08 A 5 0 4
 [10] .rel.plt REL 0804827c 00027c 000018 08 A 5 12 4
 [11] .init PROGBITS 08048294 000294 000030 00 AX 0 0 4
 [12] .plt PROGBITS 080482c4 0002c4 000040 04 AX 0 0 4
 [13] .text PROGBITS 08048310 000310 00018c 00 AX 0 0 16
 [14] .fini PROGBITS 0804849c 00049c 00001c 00 AX 0 0 4
 [15] .rodata PROGBITS 080484b8 0004b8 00001d 00 A 0 0 4
 [16] .eh_frame PROGBITS 080484d8 0004d8 000004 00 A 0 0 4
 [17] .ctors PROGBITS 08049f0c 000f0c 000008 00 WA 0 0 4
 [18] .dtors PROGBITS 08049f14 000f14 000008 00 WA 0 0 4
 [19] .jcr PROGBITS 08049f1c 000f1c 000004 00 WA 0 0 4
 [20] .dynamic DYNAMIC 08049f20 000f20 0000d0 08 WA 6 0 4
 [21] .got PROGBITS 08049ff0 000ff0 000004 04 WA 0 0 4
 [22] .got.plt PROGBITS 08049ff4 000ff4 000018 04 WA 0 0 4
 [23] .data PROGBITS 0804a00c 00100c 000010 00 WA 0 0 4
 [24] .bss NOBITS 0804a01c 00101c 00000c 00 WA 0 0 4
 [25] .comment PROGBITS 00000000 00101c 0000fc 00 0 0 1
 [26] .debug_aranges PROGBITS 00000000 001118 000070 00 0 0 8
 [27] .debug_pubnames PROGBITS 00000000 001188 000025 00 0 0 1
 [28] .debug_info PROGBITS 00000000 0011ad 0001b5 00 0 0 1
 [29] .debug_abbrev PROGBITS 00000000 001362 000083 00 0 0 1
 [30] .debug_line PROGBITS 00000000 0013e5 000180 00 0 0 1
 [31] .debug_str PROGBITS 00000000 001565 00008e 01 MS 0 0 1
 [32] .debug_ranges PROGBITS 00000000 0015f8 000040 00 0 0 8
 [33] .shstrtab STRTAB 00000000 001638 000139 00 0 0 1
 [34] .symtab SYMTAB 00000000 001d14 0004d0 10 35 54 4
 [35] .strtab STRTAB 00000000 0021e4 000213 00 0 0 1
Key to Flags:
 W (write), A (alloc), X (execute), M (merge), S (strings)
 I (info), L (link order), G (group), x (unknown)
 O (extra OS processing required) o (OS specific), p (processor specific)

Program Headers:
 Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
 PHDR 0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
 INTERP 0x000134 0x08048134 0x08048134 0x00013 0x00013 R 0x1
 [Requesting program interpreter: /lib/ld-linux.so.2]
 LOAD 0x000000 0x08048000 0x08048000 0x004dc 0x004dc R E 0x1000
 LOAD 0x000f0c 0x08049f0c 0x08049f0c 0x00110 0x0011c RW 0x1000
 DYNAMIC 0x000f20 0x08049f20 0x08049f20 0x000d0 0x000d0 RW 0x4
 NOTE 0x000148 0x08048148 0x08048148 0x00020 0x00020 R 0x4
 GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
 GNU_RELRO 0x000f0c 0x08049f0c 0x08049f0c 0x000f4 0x000f4 R 0x1

 Section to Segment mapping:
 Segment Sections...
 00
 01 .interp
 02 .interp .note.ABI-tag .hash ... .text .fini .rodata .eh_frame
 03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
 04 .dynamic
 05 .note.ABI-tag
 06
 07 .ctors .dtors .jcr .dynamic .got

您可能感兴趣的与本文相关的镜像

Kotaemon

Kotaemon

AI应用

Kotaemon 是由Cinnamon 开发的开源项目,是一个RAG UI页面,主要面向DocQA的终端用户和构建自己RAG pipeline

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值