游戏安全实验室 首页 技术入门 查看内容

 阅读目录

Android平台ELF文件格式

发布于:2016-4-25 17:24   |    244889次阅读 作者: 管理员    |   原作者: TP   |   来自: 原创

ELF英文全程为:Executable Linkable Format,ELF属于Linux平台下可执行文件。ELF文件格式与Windows下的PE(Portable Executable)文件格式相似,都是属于COFF(Common File Format)文件格式变种。谷歌的Android操作系统内核采用Linux内核框架实现,所以Android平台原生文件格式与Linux可执行文件格式完全相似,同属于ELF类型文件。

Android平台下游戏逻辑通常使用C、C++语言实现,编译之后的可执行文件属于ELF文件格式,ELF文件格式整体布局如下图所示:

谷歌的Android NDK提供工具方便开发者查看ELF文件格式,对应工具名为:arm-linux-androideabi-readelf,工具所在NDK根目录的相对路径为:android-ndk-r9c\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\,arm-linux-androideabi-readelf工具部分使用说明如下图所示:

本章使用“libTest.so”文件作为实例介绍ELF格式信息。下面将详细讲解ELF文件格式,以便让读者对Android平台原生程序的文件格式有较好理解。

1.1.1文件头信息

ELF文件头描述文件基本属性信息,包括ELF文件版本号、目标机器型号、程序入口、段表描述信息等信息。ELF文件头数据大小为0x34字节,实例文件的ELF文件头信息二进制数据如下所示:

上图中标为蓝色的数据为ELF文件头二进制内存数据,最右边可明显看出有“ELF”字符串,读者也许已猜到数据对应ELF文件标志,即判断是否为ELF文件表示。arm-linux-androideabi-readelf工具可方便查看ELF文件头信息。

利用arm-linux-androideabi-readelf工具查看ELF文件头信息命令如下:

arm-linux-androideabi-readelf.exe -h libTest.so

对应获取的文件头信息如下:

上图重要信息解释如下:

Magic:表示魔数标志信息,用来指明该文件是一个ELF目标文件,第一个字节固定为“7F”,后面三个字节为E、L、F字母的ASCII数值。同时魔数信息中还包含:版本信息、机器类型、文件类型等。

Type:表明文件类型,“DYN”表示实例所使用的文件属于动态链接库文件。

Machine:标识文件所采用指令类型,“ARM“表示当前ELF采用Arm指令集。

    Start of program headers:表示程序头信息的起始偏移。        

    Start of section headers: 表示节表头信息的起始。                                 

    Size of program headers:表示程序头信息总共大小。      

    Number of program headers:表示程序头信息总共包含的项数。         

    Size of section headers: 表示节表头信息总共大小。      

    Number of section headers: 表示节表头信息总共包含的项数。    

下面附上ELF文件头每项数据定义:

typedef struct elf32_hdr{ 
    unsigned char e_ident[EI_NIDENT]; 
    Elf32_Half    e_type; 
    Elf32_Half    e_machine; 
    Elf32_Word    e_version; 
    Elf32_Addr    e_entry;  // Entry point 
    Elf32_Off e_phoff; 
    Elf32_Off e_shoff; 
    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; 
  } Elf32_Ehdr; 

   ELF文件头属于最开始的信息,从整理描述ELF文件下面各子项信息。

1.1.2 程序头信息

ELF文件程序头信息(program headers)是一个数据结构,每个数据结构描述一个段或者系统准备程序执行所需的其他信息,ELF文件的段(Segment)包含一个或者多个节区(Section)。ELF文件的段是为方便操作系统根据相同权限区段合并到一个段进行映射。ELF文件的程序头信息定义如下:

typedef struct elf32_phdr{  
   Elf32_Word    p_type;   
   Elf32_Off      p_offset;  
   Elf32_Addr    p_vaddr;        /* virtual address */  
   Elf32_Addr    p_paddr;        /* ignore */  
   Elf32_Word    p_filesz;       /* segment size in file */  
   Elf32_Word    p_memsz;        /* size in memory */  
   Elf32_Word    p_flags;  
   Elf32_Word    p_align;       
} Elf32_Phdr;  

利用arm-linux-androideabi-readelf工具查看ELF文件程序头信息,对应的命令如下:

arm-linux-androideabi-readelf.exe -l libTest.so

获取到的ELF文件程序头信息如下图所示:

上图总共有7个段信息,通过每个段的FLg表示可获取到段对应的内存属性。实际上真正需要装载到内存中的只有类型为LOAD段,即:只有第2个和第3个需要装载到内存中并且还可以看到每一个段的起始文件偏移地址、起始内存偏移地址、段大小、段权限、段对齐方式等信息。

命令输出的信息中包含“Section to Segment mapping数据,该项信息代表section到segment的映射关键,例如:标号为2的Load段包含了: .fini_array”、“.init_array”、“.dynamic”、 .got”、“.data”、“.bss”六个节信息。

1.1.3 节表头信息

ELF文件中包含各种节段信息,它是一个Elf32_Shdr结构的数组,数据内容的定义如下所示:

typedef struct {  

   Elf32_Word    sh_name;    /* name of section, index */  

   Elf32_Word    sh_type;      

   Elf32_Word    sh_flags;  

   Elf32_Addr     sh_addr;       /* memory address, if any */  

   Elf32_Off      sh_offset;  

   Elf32_Word    sh_size;        /* section size in file */  

   Elf32_Word    sh_link;  

   Elf32_Word    sh_info;  

   Elf32_Word    sh_addralign;  

   Elf32_Word    sh_entsize;     /* fixed entry size, if have */  

} Elf32_Shdr;  

利用arm-linux-androideabi-readelf工具查看ELF文件节表头信息,对应的命令如下:

arm-linux-androideabi-readelf.exe -S libTest.so

获取到的ELF文件节表头信息如下图所示:

从节表头信息可获取到每个节段名字、长度、内存和文件的相对偏移、链接器、编译器、装载器等信息。实例样本总共有21个阶段,其中“.text”属于出现频率非常高的节段,绝大部分代码编译之后存放于“.text”段中。

 ELF文件格式主要由以上介绍的三部分信息组成,分别为:ELF文件头、ELF程序头、ELF节表头。通过以上学习,读者可掌握Android平台原生ELF文件格式的结构信息。


*转载请注明来自游戏安全实验室(GSLAB.QQ.COM)

分享到:
踩1 赞0

收藏

上一篇:ARM反汇编速成班

下一篇:IOS平台Mach-O文件格式介绍

最新评论
B Color Image Link Quote Code Smilies

发表评论