ELF那些事

一. 什么是ELF

     ELF是一类文件类型,而不是特指某一后缀的文件。ELF(Executable and Linkable Format,可执行与可链接格式)文件格式,在Linux下主要有如下三种文件:

  • 可执行文件(.out):Executable File,包含代码和数据,是可以直接运行的程序。其代码和数据都有固定的地址 (或相对于基地址的偏移 ),系统可根据这些地址信息把程序加载到内存执行。
  • 可重定位文件(.o文件):Relocatable File,包含基础代码和数据,但它的代码及数据都没有指定绝对地址,因此它适合于与其他目标文件链接来创建可执行文件或者共享目标文件。
  • 共享目标文件(.so):Shared Object File,也称动态库文件,包含了代码和数据,这些数据是在链接时被链接器(ld)和运行时动态链接器(ld.so.l、libc.so.l、ld-linux.so.l)使用的。

    ELF格式可结构大致为

 

     

    ELF文件由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。实际上,一个文件中不一定包含全部内容,而且它们的位置也未必如同所示这样安排,只有ELF头的位置是固定的,其余各部分的位置、大小等信息由ELF头中的各项值来决定

二. elf 文件分析

    2.1. readelf工具

          在Linux下,我们可以使用readelf 命令工具可以查看ELF格式文件的一些信息

 

 

    2.2. 准备测试demo

 

         2.2.1. main.c

#include "test.h"
int main(void)
{
    print_hello();
    return 0;
}
View Code

        2.2.2. test.c

#include "test.h"
void print_hello(void)
{
    printf("hello world\n");
}
View Code

        2.2.3. test.h

#ifndef __TEST_H
#define __TEST_H
#include <stdio.h>
void print_hello(void);
#endif
View Code

         2.2.4. 执行相关命令生成相关文件:.out文件、.o文件、.so文件

 

         PS -fPIC: 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。-L参数跟着的是库文件所在的目录名,-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名.

    2.3. 查看可执行文件头部信息

 

     查看可执行文件头部信息是,我们发现这样一个问题,头部信息中的类型竟然是共享库文件,而我们查看的是可执行文件,自相矛盾?

    查了一些资料:

https://blog.csdn.net/cclethe/article/details/83387685

    发现:gcc编译默认加了--enable-default-pie选项:

     

 

     Position-Independent-Executable是Binutils,glibc和gcc的一个功能,能用来创建介于共享库和通常可执行代码之间的代码–能像共享库一样可重分配地址的程序,这种程序必须连接到Scrt1.o。标准的可执行程序需要固定的地址,并且只有被装载到这个地址时,程序才能正确执行。PIE能使程序像共享库一样在主存任何位置装载,这需要将程序编译成位置无关,并链接为ELF共享对象。

    引入PIE的原因是让程序能装载在随机的地址,通常情况下,内核都在固定的地址运行,如果能改用位置无关,那攻击者就很难借助系统中的可执行码实施攻击了。类似缓冲区溢出之类的攻击将无法实施。而且这种安全提升的代价很小。

也就是说,pie这是一种保护我们可执行程序的一种手段。这里我们只是做实验,我们可以加-no-pie参数先把pie给关掉:

 

     可以看到,类型终于对得上了。ELF头部信息还包含有Entry point address(入口地址)、Start of program headers(程序头的起始字节)、Start of section headers(节头的起始字节)等信息

2.4. 查看可重定位文件头部信息:

    

 

    2.5. 查看共享目标文件头部信息

 

 

     2.6. 拓展,查看单片机目标文件.axf

 

 

三. objdump工具的使用

objdump工具用于显示一个或多个目标文件的信息。objdump命令格式:

objdump <option(s)> <file(s)>

可执行文件、可重定位文件与共享目标文件都属于目标文件,所以都可以使用这个命令来查看一些信息。

 

 

 

参考文献:https://www.toutiao.com/i6856218790460391944/?tt_from=copy_link&utm_campaign=client_share&timestamp=1596428878&app=news_article_lite&utm_source=copy_link&utm_medium=toutiao_ios&use_new_style=1&req_id=202008031227570101941000981F092EA6&group_id=6856218790460391944

 参考文献:https://blog.csdn.net/cclethe/article/details/83387685

posted @ 2020-08-09 01:20  三七鸽  阅读(607)  评论(0编辑  收藏  举报