用户
搜索
  • TA的每日心情
    慵懒
    7 天前
  • 签到天数: 117 天

    连续签到: 2 天

    [LV.6]常住居民II

    i春秋作家

    推荐小组成员

    Rank: 7Rank: 7Rank: 7

    109

    主题

    258

    帖子

    544

    魔法币
    收听
    0
    粉丝
    15
    注册时间
    2017-7-24

    幽默灌水王突出贡献春秋文阁i春秋签约作者i春秋推荐小组积极活跃奖春秋游侠秦

    HAI_ i春秋作家 推荐小组成员 幽默灌水王 突出贡献 春秋文阁 i春秋签约作者 i春秋推荐小组 积极活跃奖 春秋游侠 秦 楼主
    发表于 2018-2-18 15:45:09 122391

    本文章首发于i春秋,未经允许,禁止转载。

    0x00 前言

    有价之宝:戳这里
    无价之宝:戳这里

    内容

    ELF文件分析
    (1)ELF Header
    (2)Program Headers

    说明

    文件分析,分析起来真的是头有点炸。不过又是必经之路,不分析又不行。之后可能考虑使用各种语言对elf文件进行一个分析。

    0x01 ELF 分析。

    ELF介绍

    ELF(可执行链接格式),最初由UNIX系统实验室开发并发布的,作为应用程序二进制接口的一部分。

    ELF标准的目的是为软件开发人员提供一组二进制接口定义。

    ELF文件格式

    简介:

    文件的三种格式

    1.可重定位文件:适用于其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。

    2.可执行文件:包含于执行的一个程序,此文件规定了exec()如何创建一个程序的进程映像。

    3.共享目标文件:包含可在两种上下文中链接的代码和数据。

    目标文件格式

    文件开始是一个ELF头部,用来描述整个文件的组织。

    节区部分包含连接视图的大量信息。

    程序头部表:如果存在的话,告诉系统如何创建进程映像。用来构造进程映像的目标文件必须具有程序头部表,可重定位文件不需要这个表。

    节区头部表:包含了描述文件节区的信息,每个节区在表中都有一项,每一项给诸如节区名称。节区大小等信息。

    ELF Header

    文件最开始几个字节给出如何解释文件的提示信息。

    ELF Header :

    #define EI_NIDENT 16
    typedef struce{
        unsigned char e_ident[EI_NIDENT];
        ELf32_Half e_type;
        Elf32_half e_machine;
        Elf32_Word e_version;
        Elf32_Addr e_entry;
        Elf32_Off e_phoff;
        Elf32_Off e_short;
        Elf32_Word e_flags;
        ELf32_Half e_ehsize;
        Elf32_half e_phentsize;
        Elf32_half e_phnum;
        Elf32_half e_shentsize;
        Elf32_half e_shnum;
        Elf32_Half e_shstrndx;
    };

    首先是 e_ident[EI_NIDENT]
    这里有一个每一个元素的表。

    这里写图片描述
    接下来对e_ident[]的内容进行说明。

    e_ident

    魔数部分

    魔数,标志此文件是一个ELF文件

    EI_MAG0   0x7f
    EI_MAG1  'E'
    EI_MAG2  'L'
    EI_MAG3  'F'

    容量

    EI_CLASS

    分类:
    ELFCLASSNONE,取值为0,非法类别
    ELFCLASS32,取值为1, 32位目标
    ELFCLASS64,取值为2,64位目标

    数据编码方式

    EI_DATA

    取值为0的时候,ELFDATANONE,非法数据编码

    取值为1的时候,ELFDATA2LSB,高危在前

    取值为2的时候,ELFDATA2MSB,低位在前

    版本号

    EI_VERSION

    未使用字节的开始

    EI_PAD,初始化为0。

    实例分析

    readelf -h 显示elf文件开始的文件头信息. 

    这里写图片描述

    首先是e_ident

    前四位是魔数部分:7f 45 4c 46

    第五位代表文件类型 这里是01,对比之后我们发现,这是一个32位文件。

    第六位代表数据编码格式:这里是01,也就是说是高位在前的编码格式。

    第七位代表头部版本号:文件版本号是01。

    有了实例之后发现理解一下子就上来了。

    我们再来看一下hex文件。

    这里写图片描述

    e_type 文件类型 2个字节

    这里写图片描述

    这里写图片描述

    这里看到 数据是 03 00,对比一下知道这个文件是共享文件。

    再来看下readelf显示。
    这里写图片描述

    e_machine 体系结构类型 2个字节

    这里写图片描述
    这里写图片描述

    这里写图片描述

    因为资料的原因,所有ARM处理器比ELF文件出现的更晚。

    这里写图片描述

    e_version 文件版本 4个字节

    这里写图片描述

    这里写图片描述

    当为1的时候 为当前版本

    这里写图片描述

    e_entry  4个字节

    程序入口的虚拟地址,如果目标文件没有程序入口,可以为0

    这里写图片描述

    这里是00 00 00 00所以 没有程序入口。

    这里写图片描述

    ps:之前找到的资料,要嘛就是有问题,要嘛就不是分析so的,虽然说北京实验室的资料是高级论文,但是,它没有告诉我每一个字段的大小啊,或许是自己的愚笨,没有猜到。

    真的是。

    e_phoff 4个字节

    程序头部表格的偏移量,如果文件没有程序头部表格,可以为0

    首先来看hex文件分析。

    这里写图片描述

    34 00 ,也就是十进制的52

    这里写图片描述

    e_shoff 4个字节

    节区头部表格的偏移量。如果文件没有节区头部表格,可以为0

    来看hex文件分析

    这里写图片描述

    这里是 30 31 00 00,转换成二进制就是 12592,我们和readelf来对比

    这里写图片描述

    e_flags 4个字节

    保存于文件相关的,特定于处理器的标志。标志名称采用EF_machine_flag的格式

    先来看hex文件,这里是 00 00 00 05
    这里写图片描述

    然后来对比readelf。

    这里写图片描述

    e_ehsize  2个字节

    ELF 头部的大小(字节计算)

    怎么办,我懒的截图了。。。算了,先截图吧,没有必要我就不截图了。

    这里写图片描述

    34 00就是十进制 52,没有什么好说的,发现分析了elf文件格式,都知道简单的16转10进制的数字了。

    这里写图片描述

    e_phentsize 2个字节

    程序头部表格的表项大小

    20 00,就是二进制的32
    这里写图片描述

    这个是readelf文件格式
    这里写图片描述

    e_phnum 2个字节

    程序头部表格的表项数目

    这里写图片描述
    这里是07 00 ,就是7

    这里写图片描述

    突然想起来,我是不是应该用各种语言进行一个二进制流的分析。万一面试的问我说有没有linux下编程的经历。这我就尴尬了。

    e_shentsize 2个字节

    节区头部表格的表项大小(字节计算)

    这里写图片描述

    这里写图片描述

    这里很简单直接对比就可以了。

    e_shnum 2个字节

    节区头部表格的表项数目。可以为 0。

    这里写图片描述

    这里是10进制的21

    这里写图片描述

    e_shstrndx

    节区头部表格中与节区名称字符串表相关的表项的索引。如果文件没有节
    区名称字符串表,此参数可以为 SHN_UNDEF。

    这里写图片描述
    这里就是十进制的20。

    这里写图片描述

    还是自己比较一下,自己过一遍的理解深刻。这个倒是事实。

    Program Headers

    elf文件除了包含整体的文件头以外,还包含各个部分的program headers。这些program headers向操作系统描述了程序load和execute所需要的一切信息,它描述的是系统准备程序运行所需要的一个段和其他信息。

    这里找到了一个好的文章:http://www.jollen.org/blog/2007/03/elf_program_loading_1_segment.html

    文件格式

    typedef struct
    {
      Elf32_Word    p_type;                 /* Segment type */
      Elf32_Off     p_offset;               /* Segment file offset */
      Elf32_Addr    p_vaddr;                /* Segment virtual address */
      Elf32_Addr    p_paddr;                /* Segment physical address */
      Elf32_Word    p_filesz;               /* Segment size in file */
      Elf32_Word    p_memsz;                /* Segment size in memory */
      Elf32_Word    p_flags;                /* Segment flags */
      Elf32_Word    p_align;                /* Segment alignment */
    } Elf32_Phdr;

    说明

    segment 在ELF Header中进行说明。
    这里写图片描述

    用这个命令测试一下:

    readelf -l xxxx.so

    这里写图片描述

    p_type

    首先来看看资料对照:

    #define PT_NULL         0               /* Program header table entry unused */
    #define PT_LOAD         1               /* Loadable program segment */
    #define PT_DYNAMIC      2               /* Dynamic linking information */
    #define PT_INTERP       3               /* Program interpreter */
    #define PT_NOTE         4               /* Auxiliary information */
    #define PT_SHLIB        5               /* Reserved */
    #define PT_PHDR         6               /* Entry for header table itself */
    #define PT_TLS          7               /* Thread-local storage segment */
    #define PT_NUM          8               /* Number of defined types */
    #define PT_LOOS         0x60000000      /* Start of OS-specific */
    #define PT_GNU_EH_FRAME 0x6474e550      /* GCC .eh_frame_hdr segment */
    #define PT_LOSUNW       0x6ffffffa
    #define PT_SUNWBSS      0x6ffffffa      /* Sun Specific segment */
    #define PT_SUNWSTACK    0x6ffffffb      /* Stack segment */
    #define PT_HISUNW       0x6fffffff
    #define PT_HIOS         0x6fffffff      /* End of OS-specific */
    #define PT_LOPROC       0x70000000      /* Start of processor-specific */
    #define PT_HIPROC       0x7fffffff      /* End of processor-specific */

    先来看看实例。

    这里写图片描述

    这里是06 00 00 00,也就是10进制的6 ,对比资料就知道是PT_PHDR

    Entry for header table itself ,也就是Header自己本身的Entry。

    readelf分析

    这里写图片描述

    p_offset 4个字节

    我们来看实例分析。
    这里写图片描述

    这里不懂。。。我去看.h源码了

    好了找到了。

    p_offset, File offset of contents,就是文件的偏移量。

    相当于这个实例的偏移量是34。

    p_vaddr 4个字节

    含义:Virtual address in memory image

    含义:内存映像中的虚拟地址

    实例:
    这里写图片描述

    readelf 解析:

    这里写图片描述

    p_paddr 4个字节

    Physical address (not used)
    物理地址(未使用)

    实例
    这里写图片描述

    readelf分析。

    这里写图片描述

    p_filesz 4个字节

    Size of contents in file
    文件的内容大小

    实例:
    这里写图片描述
    实例里说明是:E0 00 00 00
    readelf对比:
    这里写图片描述

    p_memsz 4个字节

    Size of contents in memory
    内存中内容的大小

    实例:
    这里写图片描述
    实例就是:E0 00 00 00

    对比readelf:
    这里写图片描述

    p_flags 4个字节

    Access permission flags.
    访问许可标志。
    来看下资料:

    /* Values for p_flags. */
    #define PF_X        0x1 /* Executable. */
    #define PF_W        0x2 /* Writable. */
    #define PF_R        0x4 /* Readable. */
    

    实例分析。

    这里写图片描述

    这里是 04 00 00 00,对比资料可以发现是PF_R,也就是Readable,就是可读的意思。

    readelf对比分析
    这里写图片描述

    p_align四个字节

    Alignment in memory and file.
    在内存和文件中的对齐。

    实例分析。

    这里写图片描述

    readelf进行对比:

    这里写图片描述

    总结

    这里写图片描述

    大小总共是32bytes。和header相对应。

    0x02 结束语

    新年快乐~

    以上。

    本帖被以下淘专辑推荐:

    破解的目的是为了更好的开发
    发表于 2018-2-28 18:45:56
    给逆向大佬递茶,
    我能拜师么
    求知若饥,虚心若愚。
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册