导航菜单

ELF文件分析

ELF文件概述

1. 什么是ELF文件

ELF(Executable and Linkable Format)是Linux和其他类Unix系统下的可执行文件、目标代码、共享库和核心转储的标准文件格式。ELF文件包含了程序运行所需的所有信息,如代码、数据、符号表、重定位信息等。理解ELF文件结构对于逆向工程、安全分析和软件开发都至关重要。

ELF文件类型
  • ET_REL (1): 可重定位文件,如.o文件
  • ET_EXEC (2): 可执行文件,如/bin/ls
  • ET_DYN (3): 共享目标文件,如.so文件
  • ET_CORE (4): 核心转储文件
ELF文件标识
e_ident[0-3]: 魔数 (0x7F, 'E', 'L', 'F')
e_ident[4]: 文件类 (1=32位, 2=64位)
e_ident[5]: 数据编码 (1=小端, 2=大端)
e_ident[6]: ELF版本 (1=当前版本)
e_ident[7-15]: 保留字节
实际例题:识别ELF文件
# 使用hexdump查看ELF文件头
$ hexdump -C -n 16 /bin/ls
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|

# 分析结果:
# 7f 45 4c 46: ELF魔数
# 02: 64位文件
# 01: 小端序
# 01: ELF版本1

2. ELF文件的特点

  • 跨平台兼容:支持多种CPU架构和操作系统
    • x86, x86-64, ARM, MIPS等架构
    • Linux, FreeBSD, Android等系统
  • 动态链接:支持动态链接库(.so文件)
    • 运行时加载共享库
    • 支持符号版本控制
    • 支持延迟绑定
  • 可重定位:支持代码和数据在不同内存地址加载
    • 支持地址无关代码(PIC)
    • 支持基址重定位
    • 支持符号重定位
  • 符号表:包含丰富的调试和符号信息
    • 全局符号和局部符号
    • 弱符号和强符号
    • 调试符号信息
  • 节表:灵活的数据组织方式
    • 代码段和数据段分离
    • 支持自定义节
    • 支持节对齐和权限控制
  • 程序头表:描述段(Segment)信息
    • 可加载段
    • 动态链接信息
    • 程序解释器
实际例题:查看ELF文件段信息
# 使用readelf查看程序头表
$ readelf -l /bin/ls

Elf file type is DYN (Shared object file)
Entry point 0x5850
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000001f8 0x00000000000001f8  R      0x8
  INTERP         0x0000000000000238 0x0000000000000238 0x0000000000000238
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x000000000001e4a8 0x000000000001e4a8  R E    0x200000
  LOAD           0x000000000001e4b0 0x000000000021e4b0 0x000000000021e4b0
                 0x00000000000013b8 0x00000000000013b8  RW     0x200000
  DYNAMIC        0x000000000001e4e0 0x000000000021e4e0 0x000000000021e4e0
                 0x00000000000001f0 0x00000000000001f0  RW     0x8
  NOTE           0x0000000000000254 0x0000000000000254 0x0000000000000254
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_EH_FRAME   0x000000000001b6a0 0x000000000001b6a0 0x000000000001b6a0
                 0x0000000000000844 0x0000000000000844  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x000000000001e4b0 0x000000000021e4b0 0x000000000021e4b0
                 0x0000000000001350 0x0000000000001350  R      0x1

3. ELF文件的应用场景

  • 程序分析:分析程序的结构和行为
    • 函数调用关系分析
    • 控制流分析
    • 数据流分析
  • 漏洞挖掘:发现程序中的安全漏洞
    • 缓冲区溢出检测
    • 格式化字符串漏洞
    • 整数溢出检测
  • 恶意软件分析:分析病毒、木马等恶意程序
    • 行为分析
    • 特征提取
    • 家族分类
  • 软件保护:实现软件加密和保护机制
    • 代码混淆
    • 反调试技术
    • 完整性校验
  • 性能优化:分析程序的资源使用和性能特征
    • 内存使用分析
    • 函数调用开销
    • 热点代码识别
  • 兼容性研究:分析不同版本程序之间的差异
    • ABI兼容性
    • API变化分析
    • 版本迁移
实际例题:分析ELF文件符号表
# 使用nm查看符号表
$ nm -D /bin/ls

0000000000000000 A _IO_stdin_used
                 w __cxa_finalize
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U __libc_start_main
                 U __stack_chk_fail
                 U abort
                 U acl_extended_file
                 U acl_get_entry
                 U acl_get_tag_type
                 U acl_to_text
                 U bindtextdomain
                 U calloc
                 U clock_gettime
                 U closedir
                 U dcgettext
                 U dirfd
                 U dprintf
                 U endgrent
                 U endpwent
                 U error
                 U exit
                 U fchdir
                 U fchownat
                 U fclose
                 U fcntl
                 U fflush
                 U fgetfilecon
                 U fgetxattr
                 U fnmatch
                 U fopen
                 U fprintftime
                 U fprintf
                 U fputs
                 U freadlinkat
                 U free
                 U fstatat
                 U fts_children
                 U fts_close
                 U fts_open
                 U fts_read
                 U fts_set
                 U getenv
                 U getgrgid
                 U getgrnam
                 U getopt_long
                 U getpwnam
                 U getpwuid
                 U getxattr
                 U hash_get_n_entries
                 U hash_get_n_buckets
                 U hash_get_max_bucket_length
                 U hash_string
                 U iconv_open
                 U iswprint
                 U lchown
                 U lgetfilecon
                 U linkat
                 U llistxattr
                 U localeconv
                 U localtime
                 U lstat
                 U malloc
                 U mbrtowc
                 U mbsinit
                 U mbsrtowcs
                 U memcmp
                 U memcpy
                 U mempcpy
                 U memset
                 U mknodat
                 U mktime
                 U mmap
                 U mprotect
                 U mremap
                 U newlocale
                 U nl_langinfo
                 U openat
                 U opendir
                 U parse_gnu_standard_options_only
                 U posix_fadvise
                 U posix_openpt
                 U pread
                 U printf
                 U putchar
                 U puts
                 U qsort
                 U raise
                 U readdir
                 U readlink
                 U readlinkat
                 U realloc
                 U regcomp
                 U regexec
                 U regfree
                 U removexattr
                 U renameat
                 U rmdir
                 U setenv
                 U setlocale
                 U setvbuf
                 U sigaction
                 U siginterrupt
                 U stat
                 U strcasecmp
                 U strchr
                 U strcmp
                 U strcoll
                 U strcpy
                 U strcspn
                 U strdup
                 U strerror
                 U strftime
                 U strlen
                 U strncasecmp
                 U strncmp
                 U strncpy
                 U strndup
                 U strnlen
                 U strpbrk
                 U strrchr
                 U strspn
                 U strstr
                 U strtod
                 U strtol
                 U strtoul
                 U strverscmp
                 U symlinkat
                 U sysconf
                 U time
                 U tzset
                 U uname
                 U unlinkat
                 U unsetenv
                 U utime
                 U utimensat
                 U vfprintf
                 U vprintf
                 U wcrtomb
                 U wcscoll
                 U wcslen
                 U wcsnrtombs
                 U wcsrtombs
                 U wcstombs
                 U wctob
                 U wctomb
                 U wcwidth
                 U write

4. ELF文件分析的基本概念

文件头
  • 魔数:标识ELF文件格式
    • 固定值:0x7F 0x45 0x4C 0x46
    • 用于快速识别文件类型
  • 文件类型:可执行文件、可重定位文件、共享目标文件等
    • ET_REL (1): 可重定位文件
    • ET_EXEC (2): 可执行文件
    • ET_DYN (3): 共享目标文件
    • ET_CORE (4): 核心转储文件
  • 机器类型:支持的CPU架构
    • EM_386 (3): Intel 80386
    • EM_X86_64 (62): AMD x86-64
    • EM_ARM (40): ARM
    • EM_MIPS (8): MIPS
  • 入口点:程序执行的起始地址
    • 可执行文件的代码入口
    • 相对于基址的偏移
节表
  • .text:代码段
    • 包含可执行代码
    • 只读属性
    • 可执行属性
  • .data:已初始化数据段
    • 包含已初始化的全局变量
    • 读写属性
  • .bss:未初始化数据段
    • 包含未初始化的全局变量
    • 读写属性
    • 不占用文件空间
  • .rodata:只读数据段
    • 包含常量数据
    • 只读属性
  • .symtab:符号表
    • 包含所有符号信息
    • 用于链接和调试
  • .strtab:字符串表
    • 存储符号名称
    • 存储节名称
  • .rel:重定位表
    • 包含重定位信息
    • 用于动态链接
程序头表
  • LOAD:可加载段
    • 包含代码和数据
    • 指定内存权限
    • 指定文件偏移
  • DYNAMIC:动态链接信息
    • 包含动态链接库列表
    • 包含重定位信息
    • 包含符号表信息
  • INTERP:程序解释器
    • 指定动态链接器路径
    • 用于加载共享库
  • NOTE:注释信息
    • 包含版本信息
    • 包含ABI信息
实际例题:分析ELF文件节表
# 使用readelf查看节表
$ readelf -S /bin/ls

There are 31 section headers, starting at offset 0x1b168:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000000238  00000238
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             0000000000000254  00000254
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-id NOTE             0000000000000274  00000274
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000000298  00000298
       00000000000000a4  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           0000000000000340  00000340
       0000000000000c48  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           0000000000000f88  00000f88
       00000000000005c2  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           000000000000154a  0000154a
       0000000000000108  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          0000000000001658  00001658
       00000000000000f0  0000000000000000   A       6     2     8
  [ 9] .rela.dyn         RELA             0000000000001748  00001748
       0000000000000c18  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             0000000000002360  00002360
       0000000000000a08  0000000000000018  AI       5    24     8
  [11] .init             PROGBITS         0000000000003000  00003000
       0000000000000017  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         0000000000003020  00003020
       00000000000006b0  0000000000000010  AX       0     0     16
  [13] .plt.got          PROGBITS         00000000000036d0  000036d0
       0000000000000008  0000000000000008  AX       0     0     8
  [14] .text             PROGBITS         00000000000036e0  000036e0
       0000000000017f2a  0000000000000000  AX       0     0     16
  [15] .fini             PROGBITS         000000000001b60c  0001b60c
       0000000000000009  0000000000000000  AX       0     0     4
  [16] .rodata           PROGBITS         000000000001b620  0001b620
       0000000000003f20  0000000000000000   A       0     0     32
  [17] .eh_frame_hdr     PROGBITS         000000000001f540  0001f540
       0000000000000844  0000000000000000   A       0     0     4
  [18] .eh_frame         PROGBITS         000000000001fd88  0001fd88
       0000000000002c24  0000000000000000   A       0     0     8
  [19] .init_array       INIT_ARRAY       00000000000229b0  000229b0
       0000000000000008  0000000000000008  WA       0     0     8
  [20] .fini_array       FINI_ARRAY       00000000000229b8  000229b8
       0000000000000008  0000000000000008  WA       0     0     8
  [21] .data.rel.ro      PROGBITS         00000000000229c0  000229c0
       0000000000000b20  0000000000000000  WA       0     0     32
  [22] .dynamic          DYNAMIC          00000000000234e0  000234e0
       00000000000001f0  0000000000000010  WA       6     0     8
  [23] .got              PROGBITS         00000000000236d0  000236d0
       0000000000000330  0000000000000008  WA       0     0     8
  [24] .data             PROGBITS         0000000000023a00  00023a00
       0000000000000a60  0000000000000000  WA       0     0     32
  [25] .bss              NOBITS           0000000000024460  00024460
       0000000000001a68  0000000000000000  WA       0     0     32
  [26] .comment          PROGBITS         0000000000000000  00024460
       0000000000000029  0000000000000001  MS       0     0     1
  [27] .symtab           SYMTAB           0000000000000000  00024490
       0000000000000c48  0000000000000018          28    47     8
  [28] .strtab           STRTAB           0000000000000000  000250d8
       00000000000004c2  0000000000000000           0     0     1
  [29] .shstrtab         STRTAB           0000000000000000  0002559a
       0000000000000109  0000000000000000           0     0     1
  [30] .gnu_debuglink    PROGBITS         0000000000000000  000256a4
       0000000000000034  0000000000000000           0     0     4