Questions about this topic? Sign up to ask in the talk tab.
User:Hatter/ELF format
From NetSec
The Extecutable and Linkable Format (ELF) is used to construct binary executables for the Linux Operating System.
Reading ELF files
A variety of applications, debuggers, disassemblers, and resource viewers are available to read ELF formatted binaries:
- hexdump
- readelf
- objdump
Parsing elf files
It is relatively trivial to find your imagebase at runtime using some small assembly, but more difficult to actually parse out the ELF image. Here's an unstable (no error checking) assembly code that will dump its own symbols:
.section .data .section .text .globl _start _start: jmp startup getpc: mov (%rsp), %rax ret startup: xor %r15, %r15 push $0x0a0a0a mov %rsp, %r15 call getpc dec %rax xor %rcx, %rcx push $0x2 pop %rsi find_header: cmpl $0x464c457f, (%rax,%rcx,4) # Did we find our ELF base pointer? je find_sections dec %rax jmp find_header find_sections: # %rax now = base pointer of ELF image. xor %rbx, %rbx add $0x28, %bl xorl (%rax,%rbx,1), %ecx # %rcx = offset to section headers addq %rax, %rcx # %rcx = absolute address to section headers # each section header is 0x40 bytes in length. next_section: xor %rbx, %rbx xor %rbp, %rbp add $0x40, %rcx # %rcx now = address to first entry add $0x04, %bl xor (%rcx,%rbx,1), %ebp # %rbp now contains type cmp $0x02, %bpl je found_symbols jmp next_section found_symbols: xor %r8, %r8 mov %rcx, %r8 # %rcx = pointer to top of symbol section header add $0x40, %r8 # %r8 = pointer to top of string table section header xor %rbx, %rbx xor $0x18, %bl # pointer to actual section is $0x18 bytes from header base xor %r9, %r9 xor %r10, %r10 xor (%rcx,%rbx,1), %r9 xor (%r8,%rbx,1), %r10 addq %rax, %r9 # r9 should now point to the first symbol addq %rax, %r10 # r10 should now point to the first string next_symbol: add $0x24,%r9 xor %rcx, %rcx xor %rbp, %rbp xor %rdi, %rdi xor (%r9,%rcx,1), %ebp # %rbp now contains string offset. cmp %rbp, %rdi je next_symbol print_symbol_name: mov %rbp, %rsi addq %r10, %rsi # %rsi should now be a pointer to a string push $0x01 pop %rax push %rax pop %rdi call strlen syscall push $0x01 pop %rax push %rax pop %rdi push $0x02 pop %rdx push %r15 pop %rsi syscall jmp next_symbol strlen: xor %rdx, %rdx next_byte: inc %rdx cmpb $0x00, (%rsi,%rdx,1); jne next_byte ret |
[hatter@bha soinject]$ ./test_parser getpc next_section print_symbol_name __bss_start Segmentation fault
Headers
- Diagram of a 64-bit ELF Header:
0x0 - 0xf = "ELF Format Information" Entry-point = 0x18 - 0x1f Start of section headers = 0x28 - 0x2f Size of each section = 0x3a - 0x3b Number of section headers = 0x3c - 0x3d
- Diagram of a 64-bit section header: (length defined in ELF header)
[0x0-0x3] shstrtab offset for section name. shstrtab is defined between the end of .text and the beginning of the section headers
[0x4-0x7] section type - 0 is null, 1 is progbits, 2 is symtab, 3 is strtab [0x8-0xf] section flags [0x10-0x17] section address [0x18-0x1f] section offset [0x20-0x27] section size [0x28-0x2b] Section Link [0x2c-0x2f] Section Info [0x30-0x37] Section Align [0x38-0x3f] Section EntSize
Symbol Tables
- Diagram of a 64-bit symbol table entry: (0x18 bytes in length)
[0x0-0x3] Name offset from next string table [0x4-0x5] Bind [0x6-0x7] Ndx [0x8-0xf] Symbol pointer (Function pointer, data pointer, etc) [0x10-0x17] Null barrier