AI手机网,短视频直播 硬改改机 一键新机 群控软件 刷机定制

 找回密码
 立即注册
搜索
查看: 1978|回复: 0

Odex文件二进制分析

[复制链接]
发表于 2020-7-4 19:16:51 | 显示全部楼层 |阅读模式
 最近在看ART虚拟机相关的内容,稍微有了解的都能知道/data/dalvik-cache下的.dex后缀的文件和odex文件实际上都是修改过的ELF文件,网上有很多说明,但是貌似都没有找到一篇对一个odex或者说oat文件做分析的。所以博主这里就想着尝试对odex文件做一个简单分析。
odex文件总体信息
  这里博主拿SystemUI的oat文件(/data/dalvik-cache/arm64/system@product@priv-app@SystemUI@SystemUI.apk@classes.dex)做例子,下面是通过readelf -e system@product@priv-app@SystemUI@SystemUI.apk@classes.dex得出的ELF header、Section header、Program header以及Section到Segmemnt的映射关系如下所示
首先我们来看ELF header信息
这里我们先把通过readelf读出来的信息贴出来
ELF Header:  Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00  Class:                             ELF64  Data:                              2's complement, little endian  Version:                           1 (current)  OS/ABI:                            UNIX - GNU  ABI Version:                       0  Type:                              DYN (Shared object file)  Machine:                           AArch64  Version:                           0x1  Entry point address:               0x0  Start of program headers:          64 (bytes into file)  Start of section headers:          3756960 (bytes into file)  Flags:                             0x0  Size of this header:               64 (bytes)  Size of program headers:           56 (bytes)  Number of program headers:         9  Size of section headers:           64 (bytes)  Number of section headers:         12  Section header string table index: 11
下面我们将代码中的ELF头定义贴出来
typedef struct elf64_hdr {  unsigned char e_ident[EI_NIDENT];  Elf64_Half e_type;  Elf64_Half e_machine;  Elf64_Word e_version;  Elf64_Addr e_entry;  Elf64_Off e_phoff;  Elf64_Off e_shoff;  Elf64_Word e_flags;  Elf64_Half e_ehsize;  Elf64_Half e_phentsize;  Elf64_Half e_phnum;  Elf64_Half e_shentsize;  Elf64_Half e_shnum;  Elf64_Half e_shstrndx;} Elf64_Ehdr;
最后是通过010Editor使用十六进制显示的内容


通过上面三个信息的对比,很多信息就很明显了有木有
  • 首先代码中的unsigned char e_ident[EI_NIDENT];的定义对应readelf信息的Magic,前面四个字节是固定的,定义如下:
#define ELFMAG0 0x7f#define ELFMAG1 'E'#define ELFMAG2 'L'#define ELFMAG3 'F'
随后紧接着的是文件的类型,这里是0x02,便是的是64位文件
// Object file classes.enum {  ELFCLASSNONE = 0,  ELFCLASS32 = 1, // 32-bit object file  ELFCLASS64 = 2  // 64-bit object file};
随后是文件字节排布的类型,即是大端字节序还是小端字节序,这里是0x01,代表是小端字节序
// Object file byte orderings.enum {  ELFDATANONE = 0, // Invalid data encoding.  ELFDATA2LSB = 1, // Little-endian object file  ELFDATA2MSB = 2  // Big-endian object file};
再接着代表文件的版本,固定位1,所以是0x01,到这里我们就将第一个分析e_ident[EI_NIDENT]的信息分析完了。
  • 接着我们分析struct余下的字段:
e_type代表的是OS ABI的类型,查看010Editor的信息,这里是0x03,对应的是GNU/Linux类型,也和readelf的信息对应上了
// OS ABI identification.enum {  ELFOSABI_NONE = 0,          // UNIX System V ABI  ELFOSABI_HPUX = 1,          // HP-UX operating system  ELFOSABI_NETBSD = 2,        // NetBSD  ELFOSABI_LINUX = 3,         // GNU/Linux  ELFOSABI_HURD = 4,          // GNU/Hurd  ELFOSABI_SOLARIS = 6,       // Solaris  ELFOSABI_AIX = 7,           // AIX  ELFOSABI_IRIX = 8,          // IRIX  ELFOSABI_FREEBSD = 9,       // FreeBSD  ELFOSABI_TRU64 = 10,        // TRU64 UNIX  ELFOSABI_MODESTO = 11,      // Novell Modesto  ELFOSABI_OPENBSD = 12,      // OpenBSD  ELFOSABI_OPENVMS = 13,      // OpenVMS  ELFOSABI_NSK = 14,          // Hewlett-Packard Non-Stop Kernel  ELFOSABI_AROS = 15,         // AROS  ELFOSABI_FENIXOS = 16,      // FenixOS  ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000  ELFOSABI_C6000_LINUX = 65,  // Linux TMS320C6000  ELFOSABI_ARM = 97,          // ARM  ELFOSABI_STANDALONE = 255   // Standalone (embedded) application};
后面的字段也类似,一次对应即可。这样ELF头信息就能很好的解读出来。接下来要说明的是section的信息了
Section hader解读Section Headers:  [Nr] Name              Type             Address           Offset       Size              EntSize          Flags  Link  Info  Align  [ 0]                   NULL             0000000000000000  00000000       0000000000000000  0000000000000000           0     0     0  [ 1] .rodata           PROGBITS         0000000000001000  00001000       00000000000bd000  0000000000000000   A       0     0     4096  [ 2] .text             PROGBITS         00000000000be000  000be000       00000000002aed00  0000000000000000  AX       0     0     4096  [ 3] .data.bimg.rel.ro PROGBITS         000000000036d000  0036d000       0000000000001560  0000000000000000   A       0     0     4096  [ 4] .bss              NOBITS           000000000036f000  00000000       0000000000005814  0000000000000000   A       0     0     4096  [ 5] .dex              NOBITS           0000000000375000  00000000       000000000000bed0  0000000000000000   A       0     0     4096  [ 6] .dynstr           STRTAB           0000000000381000  0036f000       00000000000000c7  0000000000000000   A       0     0     4096  [ 7] .dynsym           DYNSYM           00000000003810c8  0036f0c8       0000000000000120  0000000000000018   A       6     1     8  [ 8] .hash             HASH             00000000003811e8  0036f1e8       000000000000003c  0000000000000004   A       7     0     4  [ 9] .dynamic          DYNAMIC          0000000000382000  00370000       0000000000000070  0000000000000010   A       6     0     4096  [10] .gnu_debugdata    PROGBITS         0000000000000000  00371000       0000000000024338  0000000000000000           0     0     4096  [11] .shstrtab         STRTAB           0000000000000000  00395338       0000000000000063  0000000000000000           0     0     1
readelf section header获取到的信息如上,一共有11个section,其中第一个section是空的,这个是ELF的定义如此,那么我们要怎么在010Editor中找到对应字节的位置呢?首先在ELF header中,有一个关键的信息,就是section header的便宜,相信在上一节内容,你已经知道了,对应readelf的信息就是 Start of section headers: 3756960 (bytes into file),没错,这里就是和文件头的偏移量:3756960,即十六进制的3953A0。那么接下来我们在010Editor中跳转到3953A0位置看看


这里蓝色标注的内容就是一个section header描述的信息,section header在代码中的描述如下所示
// Section header for ELF64 - same fields as ELF32, different types.struct Elf64_Shdr {  Elf64_Word  sh_name;  Elf64_Word  sh_type;  Elf64_Xword sh_flags;  Elf64_Addr  sh_addr;  Elf64_Off   sh_offset;  Elf64_Xword sh_size;  Elf64_Word  sh_link;  Elf64_Word  sh_info;  Elf64_Xword sh_addralign;  Elf64_Xword sh_entsize;};
第一个sh_name,这个需要特别说明一下,这个sh_name是一个Elf64_Word,实际是uint_32类型的,里面存储的是一个地址,指向
.shstrtab section中某个字串的开始地址。所以我们先看看.shstrtab section中存储的是什么内容吧,通过readelf中Section Header信息可以知道.shstrtab节的偏移地址位0x00395338,是的,这里直接读出来的地址就已经是16进制过的了。然后在010Editor中查看这个地址在存储的内容是什么呢?


通过右边的字符串区可以看到一些可读信息,这里面存储的就是该odex文件中用到的section name。而在具体的section中,对应的sh_name的值就是.shstrtab section中的偏移量。
OK,因为博主也是最近才开始用010Editor查看并对照这代码来分析的,目前上面的信息暂时够用了,后续有要对各个section的内容做分析的时候,博主再补充了,或者各位看官有什么不懂得,可以提出来,后续博主再继续分析哈。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

技术交流售后群

QQ|小黑屋|手机版|站点找错-建议|AI手机网 |Sitemap



GMT+8, 2024-5-9 12:42 , Processed in 0.139602 second(s), 27 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表