PWN二进制安全修仙秘籍【第二章#二进制文件篇01】从源代码到可执行文件

进入到了第二章的学习,第二章主要学习二进制文件是如何产生的,以及Linux中的二进制文件ELF文件

这一小节我们先学习二进制文件是如何产生的,即从源代码到可执行文件的过程

1. 展示源代码

下面将采用一段Hello World程序来演示这个过程

#include <stdio.h>
int main() {
    print("Hello, world!\n");
}

使用如下命令对以上C语言程序进行编译

gcc hello.c -o hello -save-temps --verbose

以上命令中,-save-temps表示将编译过程中生成的中间文件保存下来,--verbose表示查看GCC编译的详细工作流程。

2. 解读中间文件

众所周知,GCC编译共四个阶段:预处理编译汇编链接

2.1 预编译阶段

 /usr/lib/gcc/x86_64-linux-gnu/11/cc1这是第一阶段,cc1是编译器,对应预处理编译阶段。

 何为预处理

预处理就是处理源代码中以“#”开始的预处理指令,比如“#include”、“#define”等,将其转化后直接插入到程序文本中,得到另一个程序,通常以“.i”作为文件扩展名。

你也可以敲入以下命令得到一个预编译文件:

gcc -E hello.c -o hello.i

-E表示单独执行预处理过程。

经过预处理后的 hello.i 文件大概长这样👇(GCC版本不同,编译出来的东西也不同)

# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
……
extern int printf(const char *__restrict __format, …);
……
int main() {
    printf("Hello, world!\n");
}

通过以上预处理文件,我们可以观察发现,在文件进行预处理阶段时,主要进行了以下动作:

  • 递归处理“#include”预处理指令,将对应文件的内容复制到该指令的位置;
  • 删除所有“#define”指令,并且在其被引用的位置递归地展开所有的宏定义;
  • 处理所有条件预处理指令:“#if”、“#ifdef”、“#elif”、“#else”、“#endif”等;
  • 删除所有注释
  • 添加行号和文件名标识。

2.2 编译阶段

GCC编译的第二阶段即编译

在编译阶段主要进行了词法分析、语法分析、语义分析以及优化等一系列动作,最终生成汇编代码。

你也可以敲以下命令得到编译后的文件:

gcc -S hello.c -o hello.s

-S表示将预处理和编译合并处理,操作对象可以是源代码hello.o或者是预处理文件hello.i

hello.s文件如下所示:

        .file   "hello.c"
        .text
        .section        .rodata
.LC0:
        .string "Hello, world!\n"
        .text
        .globl  main

 2.3 汇编阶段

as是汇编器,对应第三阶段——汇编。汇编器根据汇编指令与机器指令的对照表进行翻译,将hello.s汇编成目标文件hello.o。

你也可以使用如下命令直接生成目标文件:

gcc -c hello.c -o hello.o

此时生成的hello.o为可重定位文件,使用objdump -sd hello.o命令查看其内容:

 先解释一下参数的意思,-s表示sections段,-d表示disassemble,即反汇编;sections段不理解没关系,这个以后会解释。

继续解释一下里面的汇编代码的意思。

由于尚未进行链接,对象文件中符号的虚拟地址无法确定,因此“Hello,world!”这个字符串的地址被设置为0x0000,看下图👇

“call puts”指令中函数puts()的地址被设置为下一条指令的地址0x1c

2.4 链接阶段

collect2是链接器,是对ld命令的封装,用于将C语言运行时库(CRT)中的目标文件(crt1.o、crti.o、crtbegin.o、crtend.o、crtn.o)以及所需的动态链接库(libgcc.so、libgcc_s.so、ligc.so)链接到可执行hello中。

链接分为两种:静态链接动态链接

GCC默认使用动态链接

若要使用静态链接应添加编译选项“-static”即可指定使用静态链接

链接阶段主要进行地址和空间分配、符号绑定、重定位等操作。  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Merrill He

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值