RVOS练习3-2

编译程序

编写程序hello.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdio.h>

int global_init = 0x11111111;
const int global_const = 0x22222222;

void main()
{
static int static_var = 0x33333333;
static int static_var_uninit;

int auto_ver = 0x44444444;

printf("hello world\n");
return;
}

使用如下指令编译程序,获得hello.o文件:

1
gcc -g -c hello.c

查看变量位置

已初始化全局变量和静态变量

global_init为已初始化全局变量,static_var为已初始化静态变量,已初始化的全局变量和静态变量位于.data section,使用指令

1
objdump -s -j .data hello.o

进行查看,.data section如下:

1
2
Contents of section .data:
0000 11111111 33333333 ....3333

其中11111111对应变量global_init33333333对应变量static_var.

只读数据

常变量global_const以及字符串hello world\n\0为只读数据,只读数据位于位于.rodata section,使用指令

1
objdump -s -j .rodata hello.o

进行查看,.rodata section如下:

1
2
Contents of section .rodata:
0000 22222222 68656c6c 6f20776f 726c6400 """"hello world.

其中22222222对应常变量global_const68656c6c 6f20776f 726c6400对应字符串hello world\n\0的ascii码值.

未初始化全局变量和静态变量

static_var_uninit为未初始化全局变量和静态变量,未初始化全局变量和静态变量位于位于.bss section,此节区不占用 ELF 文件空间,但占用程序的内存映像中的空间。当程序开始执行时,系统将把这些数据初始化为 0。bss 其实是 block started by symbol 的简写.

使用指令

1
objdump -t hello.o

查看符号表,输出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0000000000000000 l    df *ABS*  0000000000000000 hello.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l d .rodata 0000000000000000 .rodata
0000000000000000 l O .bss 0000000000000004 static_var_uninit.1
0000000000000004 l O .data 0000000000000004 static_var.0
0000000000000000 l d .debug_info 0000000000000000 .debug_info
0000000000000000 l d .debug_abbrev 0000000000000000 .debug_abbrev
0000000000000000 l d .debug_line 0000000000000000 .debug_line
0000000000000000 l d .debug_str 0000000000000000 .debug_str
0000000000000000 l d .debug_line_str 0000000000000000 .debug_line_str
0000000000000000 g O .data 0000000000000004 global_init
0000000000000000 g O .rodata 0000000000000004 global_const
0000000000000000 g F .text 0000000000000025 main
0000000000000000 *UND* 0000000000000000 puts

可以看到未初始化静态变量static_var_uninit位于.bss段.

局部变量

局部变量不在elf中占有相关的节,局部在程序执行过程被存储在栈区,我们可以在通过反汇编代码看到相关的操作,其中汇编代码位于.text段.

使用以下指令对ELF文件进行反汇编

1
objdump -S hello.o

汇编代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

hello.o: file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:

int global_init = 0x11111111;
const int global_const = 0x22222222;

void main()
{
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 48 83 ec 10 sub $0x10,%rsp
static int static_var = 0x33333333;
static int static_var_uninit;

int auto_ver = 0x44444444;
c: c7 45 fc 44 44 44 44 movl $0x44444444,-0x4(%rbp)

printf("hello world\n");
13: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # 1a <main+0x1a>
1a: 48 89 c7 mov %rax,%rdi
1d: e8 00 00 00 00 call 22 <main+0x22>
return;
22: 90 nop
}
23: c9 leave
24: c3 ret

其中movl $0x44444444,-0x4(%rbp)表示将4字节的立即数0x44444444存储到栈上由%rbp基址指针寄存器向下偏移 4 字节的位置.

参考

  1. CTF Wiki
  2. 程序员的自我修养