前言 了解这些之前,我们应该先知道我们写的C代码,它经历怎样的过程才变成了可执行程序。
从helloworld说起
#include
int main()
{
printf("Hello World\n");
return 0;
}
【ELF,PE文件格式 及 延迟绑定(PLT、GOT表)、动态链接(.dynamic段)】在Linux下我们可以用GCC编译器来编译helloword程序,只需用一条命令就可以
$gcc hello.c
$./a.out
Hello World
事实上,上述过程可分解为四个步骤,分别是预处理,编译,汇编和链接。
预处理
预编译过程主要处理那些源代码文件中以“#”开始的预编译指令
$gcc -E hello.c -o hello.i
编译
$gcc -S hello.i -o hello.s
查看hello.s可以看到汇编代码,值得注意的是程序里我们只用了printf函数,怎么变成了puts函数?
答案是编译器通过扫描、语法分析、语义分析、源代码优化、代码生成、和目标代码优化,把printf函数优化成了puts函数。因为我们没用printf函数的参数(%s),就相当于了puts函数。
文章图片
汇编
汇编过程就是把汇编代码变成机器可以执行的指令,每一条汇编语句几乎都对应一条机器指令。
$gcc -c hello.c -o hello.o
链接
链接的过程相比前面三个过程比较复杂,最基本的连接过程:每个模块的源代码文件经过编译器编译成目标文件(一般扩展名为.o),目标文件和库(Library)一起连接形成可执行文件。而最常见的库就是运行时库,还有别的静态库,动态库。
- 运行时库:Unix中一个典型的运行时库例子就是libc,它包含标准的C函数,如,print(),exit()等等,用户能创建他们自己的运行库(在Windows中是DLL),而具体的细节依赖编译器和操作系统的。
- 静态库:函数和数据被编译进一个二进制文件(通常扩展名为.lib),静态库实际上是在链接时被链接到EXE的,库本身不需要与可执行文件一起发行。
- 动态库:用VC++创建的动态库包含两个文件,一个lib文件和一个dll文件,这个lib文件就是引入库,不是静态库,引入库有时也叫输入库或导入库。
$ld -static /usr/lib/crtl.o /usr/lib/crti.o
/usr/lib/gcc/i686-linux-gnu/6.0.0/crtbeginT.o
-L/usr/lib/gcc/i686-linux-gnu/6.0.0
-L/usr/lib -L/lib
hello.o
-start-group -lgcc -lgcc_eh -lc
--end-group /usr/lib/gcc/i686-linux-gnu/6.0.0/crtend.o /usr/lib/crtn.o
ELF、PE文件格式 现在PC平台上流行的文件格式主要是Windos下的PE(像.exe)和Linux下的ELF,他们都是COFF格式的变种。
在linux下可以使用file命令查看相应的文件格式
文章图片
ELF文件中的内容至少有编译后的机器指令代码、代码,一般目标文件按照不同属性,以段的形式存储。常见的段有:
- .text 代码段 存储编译后的机器指令
- .data 数据段 存储初始化的全局变量和局部变量
- .bss 数据段 存储未初始化的全局变量和局部变量
- .rodata 只读数据段
- .rel.text 重定位的代码段
- .comment 注释信息段
- .plt 保存函数的地址
- .got 保存全局变量引用的地址
- .got.plt 用来保存函数引用的地址
- .dynamic 动态链接信息
- .debug 调试信息
- 第一项保存的是.dynamic的地址
- 第二项保存的是本模块的ID
- 第三项保存的是_dll_runtime_resolve()的地址
文章图片
参考文章:
https://www.cnblogs.com/qinfengxiaoyue/archive/2012/05/27/2519703.html
https://www.cnblogs.com/muahao/p/10346724.html
《程序员的自我修养》
推荐阅读
- [V&N2020 公开赛]babybabypwn[srop]
- babyheap_0ctf_2017
- BUUCTF|【BUUCTF - PWN】babyheap_0ctf_2017
- BUUCTF|【BUUCTF - PWN】babyrop
- buuctf中的一些pwn题总结(不断更新)
- pwn|关于沙箱关闭execve的绕过技巧及SROP的简单利用方法 --(buuctf[V&N2020 公开赛])babybabypwn + warmup
- 堆溢出|House of force —— gyctf_2020_force
- 栈溢出|非常规情况下栈溢出系统调用——PicoCTF_2018_can-you-gets-me
- 堆溢出|libc2.26以下的单一堆溢出漏洞利用——0ctf_2017_babyheap