pwn 👻
readelf
-h
: file header-S
: section header (= objdump -h <file>
)-s
: symbol (dynsym & symtab) (= nm <file>
)-r
: show relocsexecutable linkable format, 為 linux 下的可執行檔
可以用 readelf -s <file>
查看
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;
由 compiler 產生, 目的是讓 linker 可以將不同的 obj, 其 function & variable & others 可以 relocate 至 resulting file
可以用 readelf -s <file>
查看
dynsym
: 只含 global symbols 的 symtab 子集合symtab
: 包含所有 non-allocable section 的 section infotypedef 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
:
local
: 0, local symbol, 外部不可見global
: 1, 全域, 外部可見weak
: 2, 弱引用 (未定義仍能使用)notype
: 0, unknown type symbolobject
: 1, variable, arr 等物件func
: 2, function or codesection
: 3, 為 section, type 皆為 local
file
: 檔案名稱, type 皆為 local
, shndx
必為 absst_shndx
:
abs
: 0xfff1, 一絕對值 (ex. file name symbol)common
: 0xfff2, 未初始化的 global symbolundef
: 0, symbol 未定義st_value
:
st_shndx
非 common
, 則 st_value
代表 section offset將不同種類的 info 分成多個 section, 能根據 info 的特性去限制 memory 使用權限, 或是在多個副本可以 shared 部分 section
strip
可以 remove non-allocable section, 使 ELF file size 減少, 因為他們只會在 debug 或其他特定情況才會使用到.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
: 字串表
\0
隔開, 透過 offset 即可存取特定 string.shstrtab
: section string table
.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.rel.dyn
corresponds to R_386_GLOB_DAT
, which is global data.rel.plt
corresponds to R_386_JUMP_SLOT
, which is function.dynamic section
可以用 readelf -d <file>
查看
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
d_tag
:
symtab
: dynamic linking symbol table address (.dynsym)strtab
: dynamic linking string table address (.dynstr)strsz
: dynamic linking string table sizehash
: dynamic linking hash table addresssoname
rpath
init
: initial code addressfinit
: finish code addressneed
: shared object namerel
: .rel.dyn address (for variable)jmprel
: .rel.plt address (for function)relent
: .rel.dyn entry + .rel.plt entry.rel.plt, .rel.dyn section
可以用 readelf -r <file>
查看
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.plt
前三項:
.dynamic
section address<_dl_runtime_resolve>
的 address.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;
rel
:
ELF32_R_SYM(rel->r_info)
: rel 在 dynamic symbol table(.dynsym) 的 index
.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
的 offsetrel_sym->st_name
+ .dynstr
: 為該 rel_sym 的 string name紀錄 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
:
NULL
: 無效區段PROGBITS
: 程式區段(.text, .data…)SYMTAB
: symbol table 符號表STRTAB
: string table 字串表RELA
: relocation tableHASH
: symbol table hashDYNAMIC
: dynamic linking infoNOTE
: 提示性 infoNOBITS
: no content (ex. .bss)REL
: relocation infoSHLIB
: 保留DYNSYM
: dynamic linking symbol tablesh_flags
:
WRITE
: 1, 可寫ALLOC
: 2, 該 section 需分配空間EXECINSTR
: 4, 可執行 section