ELF deep look

tags: pwn 👻

tool

  • readelf
    • -h: file header
      Image Not Showing Possible Reasons
      • The image file may be corrupted
      • The server hosting the image is unavailable
      • The image path is incorrect
      • The image format is not supported
      Learn More →
    • -S: section header (= objdump -h <file>)
      Image Not Showing Possible Reasons
      • The image file may be corrupted
      • The server hosting the image is unavailable
      • The image path is incorrect
      • The image format is not supported
      Learn More →
    • -s: symbol (dynsym & symtab) (= nm <file>)
      Image Not Showing Possible Reasons
      • The image file may be corrupted
      • The server hosting the image is unavailable
      • The image path is incorrect
      • The image format is not supported
      Learn More →

      Image Not Showing Possible Reasons
      • The image file may be corrupted
      • The server hosting the image is unavailable
      • The image path is incorrect
      • The image format is not supported
      Learn More →
    • -r: show relocs
      Image Not Showing Possible Reasons
      • The image file may be corrupted
      • The server hosting the image is unavailable
      • The image path is incorrect
      • The image format is not supported
      Learn More →

elf

executable linkable format, 為 linux 下的可執行檔

可以用 readelf -s <file> 查看

  • 分成:
    1. relocatable file: 包含 code & data 的檔案, 用來連結形成 resulting file or shared object (.o .a)
    2. executable file: 可以直接執行 (無副檔名)
    3. shared object file: 包含 code & data 的檔案, (.so) 在兩種情況下使用:
      1. linker 用來與其他 relocatable file, shared object file 組成新的 shared object file
      2. dynamic linking, map 到 memory 中給各 process 共享
    4. core dump file: process 意外終止時的紀錄檔
  • file 可查看其特性
typedef struct {
    unsigned char e_ident[16]; // magic, class, ABI version...
    Elf32_Half e_type; // ex. rel (relocatable file)
    Elf32_Half e_machine; // ex. intel80386
    Elf32_Word e_version; // 1 generally
    Elf32_Addr e_entry; // exec: _start, rel: 0x0
    Elf32_Off e_phoff; // start of program headers
    Elf32_Off e_shoff; // start of section headers
    Elf32_Word e_flags; // some flag
    Elf32_Half e_ehsize; // size of this header, elf header 本身大小
    Elf32_Half e_phentsize; // size of program headers
    Elf32_Half e_phnum; // number of program headers
    Elf32_Half e_shentsize; // size of section headers
    Elf32_Half e_shnum; // number of section headers
    Elf32_Half e_shstrndx; // section header string table index
} Elf32_Ehdr;

symbol

由 compiler 產生, 目的是讓 linker 可以將不同的 obj, 其 function & variable & others 可以 relocate 至 resulting file

可以用 readelf -s <file> 查看

  • 分成兩種
    1. dynsym: 只含 global symbols 的 symtab 子集合
    2. symtab: 包含所有 non-allocable section 的 section info
typedef struct {
    Elf32_Word st_name;
    Elf32_Word st_value;
    Elf32_Word st_size;
    unsigned char st_info;
    unsigned char st_other; // 0, no use
    Elf32_Half st_shndx;
} Elf32_Sym;
  • st_info:
    • second 4 bit for symbol type
      1. local: 0, local symbol, 外部不可見
      2. global: 1, 全域, 外部可見
      3. weak: 2, 弱引用 (未定義仍能使用)
    • first 28 bit for symbol binding
      1. notype: 0, unknown type symbol
      2. object: 1, variable, arr 等物件
      3. func: 2, function or code
      4. section: 3, 為 section, type 皆為 local
      5. file: 檔案名稱, type 皆為 local, shndx 必為 abs
  • st_shndx:
    1. value: 對應到的 section header index, 沒對應到的話則該 symbol 為外部定義 or 為特殊符號
    2. abs: 0xfff1, 一絕對值 (ex. file name symbol)
    3. common: 0xfff2, 未初始化的 global symbol
    4. undef: 0, symbol 未定義
  • st_value:
    1. st_shndxcommon, 則 st_value 代表 section offset
    2. 反之即為 symbol 的 alignment attribute
  • 弱符號 & 強符號
    • 強符號: 不能被重複定義的 symbol
    • 弱符號: 可以被重複定義的 symbol, ex. 為未初始化的 variable. 因為其尚未被 assign value, 在生成 resulting file 之前, 其 var type 仍能更改, 所以可以被當作弱符號

section

將不同種類的 info 分成多個 section, 能根據 info 的特性去限制 memory 使用權限, 或是在多個副本可以 shared 部分 section

  • sections 分成
    1. runtime used, 又稱 allocable section (ex. code, data)
    2. needed by linker, debuger, 又稱 non-allocable section
    • 當 ELF 被執行後, 只有 allocable section 會被 map 到 memory 裡
    • strip 可以 remove non-allocable section, 使 ELF file size 減少, 因為他們只會在 debug 或其他特定情況才會使用到
    • 在沒有 dynamic linking 之前, 只有 non-allocable section (symtab)
  • .data: 已初始化的 global or static variable
  • .text: 程式碼片段
  • .bss: 未初始化的 global or static variable (or 初始化值為 0)
  • .rodata: read only data, 像是 printf("%d");"%d" 即是 rodata, 不可修改
  • .comment: 編譯器版本資訊
  • .note.GNU-stack: stack 提示 section
  • .strtab: 字串表
    • 用來放普通的 string
    • 內部存放連續的 string, 以 \0 隔開, 透過 offset 即可存取特定 string
  • .shstrtab: section string table
    • 用來放 section name string
    • .strtab
  • .symtab: symbol table
  • .plt: procedure linkage table
  • .init: initial code
  • .fini: finish code
  • .dynamic: dynamic linking info
  • .rel.plt: relocate function
  • .rel.dyn: relocate variable
  • .got: global variable offset
  • .got.plt: global function offset
  • .dynsym: dynamic linking symbol
  • .dynstr: dynamic linking string
  • for more
    • .rel.dyn corresponds to R_386_GLOB_DAT, which is global data
    • .rel.plt corresponds to R_386_JUMP_SLOT, which is function
      Image Not Showing Possible Reasons
      • The image file may be corrupted
      • The server hosting the image is unavailable
      • The image path is incorrect
      • The image format is not supported
      Learn More →

dynamic section struct

.dynamic section

可以用 readelf -d <file> 查看

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

typedef struct {
    Elf32_Sword d_tag;
    union {
        Elf32_Word d_val;
        Elf32_Addr d_ptr;
    } d_un;
} Elf32_Dyn;
  • d_tag:
    1. symtab: dynamic linking symbol table address (.dynsym)
    2. strtab: dynamic linking string table address (.dynstr)
    3. strsz: dynamic linking string table size
    4. hash: dynamic linking hash table address
    5. soname
    6. rpath
    7. init: initial code address
    8. finit: finish code address
    9. need: shared object name
    10. rel: .rel.dyn address (for variable)
    11. jmprel: .rel.plt address (for function)
    12. relent: .rel.dyn entry + .rel.plt entry

relocable section struct

.rel.plt, .rel.dyn section

可以用 readelf -r <file> 查看

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

typedef struct {
    Elf32_Addr r_offset;
    // target offset (ex. lazy binding 時, .rel.plt 內的 offset 即是 func@got 的 address)
    Elf32_Word r_info;
    // first 3 bytes for reloc symbol index in symbol table (.dynsym 的 num)
    // last 1 byte for reloc type
} Elf32_Rel;

#define ELF32_R_SYM(r_info) (r_info >> 8)
#define ELF32_R_TYPE(r_info) (r_info & 0xff)

got section

  • .got.plt 前三項:
    1. .dynamic section address
    2. module ID
    3. <_dl_runtime_resolve> 的 address

symbol section struct

.dynsym .sym section struct

readelf --dyn-syms <file> ==> .dynsym
readelf -s <file> ==> .dynsym + .symtab

typedef struct {
    Elf32_Word st_name; // 在 .strtab or .dynstr 的 offset
    Elf32_Word st_value;
    Elf32_Word st_size;
    unsigned char st_info; // symbol type and binding
    unsigned char st_other;
    Elf32_Half st_shndx;
} Elf32_Sym;
  • A reloc entry rel:
    • ELF32_R_SYM(rel->r_info): rel 在 dynamic symbol table(.dynsym) 的 index
      • rel entry 在 .dynsym 皆有 num 可以對應
    • .dynsym address(ex. 0x080481d8) + .dynsym entry size(ex. 0x10) * index: rel 其 symbol struct info, 我們假設他為 rel_sym
    • rel_sym first 8 bytes 為 st_name, value 為其在 .strtab 的 offset
    • rel_sym->st_name + .dynstr: 為該 rel_sym 的 string name

section header

紀錄 section 的各種 info, 如 size, name, offset 等等

可以用 readelf -S <file> 查看

section header table: 紀錄各個 section header 的一個 section

typedef struct {
    Elf32_Word sh_name;
    // section name 為一字串, 存在 .shstrtab 字串表
    // sh_name 存該 section name 字串在 .shstrtab 字串表的 offset
    Elf32_Word sh_type;
    Elf32_Word sh_flags;
    Elf32_Addr sh_addr;
    Elf32_Off sh_offset; // section 在 elf file 中的 offset
    Elf32_Word sh_size; // section size
    Elf32_Word sh_link;
    Elf32_Word sh_info;
    Elf32_Word sh_addralign;
    Elf32_Word sh_entsize; // section entry size
} Elf32_Shdr;
  • sh_type:
    1. NULL: 無效區段
    2. PROGBITS: 程式區段(.text, .data)
    3. SYMTAB: symbol table 符號表
    4. STRTAB: string table 字串表
    5. RELA: relocation table
    6. HASH: symbol table hash
    7. DYNAMIC: dynamic linking info
    8. NOTE: 提示性 info
    9. NOBITS: no content (ex. .bss)
    10. REL: relocation info
    11. SHLIB: 保留
    12. DYNSYM: dynamic linking symbol table
  • sh_flags:
    1. WRITE: 1, 可寫
    2. ALLOC: 2, 該 section 需分配空間
    3. EXECINSTR: 4, 可執行 section