Questions about this topic? Sign up to ask in the talk tab.
Difference between revisions of "User:Hatter/ELF format"
From NetSec
(→Parsing elf files) |
(→Parsing elf files) |
||
(4 intermediate revisions by one other user not shown) | |||
Line 10: | Line 10: | ||
== Parsing elf files == | == 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: | + | 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 or size checking) assembly code that will dump its own symbols: |
{{code|text=<source lang="asm"> | {{code|text=<source lang="asm"> | ||
.section .data | .section .data | ||
Line 19: | Line 19: | ||
_start: | _start: | ||
jmp startup | jmp startup | ||
+ | |||
+ | strlen: | ||
+ | xor %rdx, %rdx | ||
+ | |||
+ | next_byte: | ||
+ | inc %rdx | ||
+ | cmpb $0x00, (%rsi,%rdx,1); | ||
+ | jne next_byte | ||
+ | ret | ||
getpc: | getpc: | ||
Line 56: | Line 65: | ||
xor (%rcx,%rbx,1), %ebp # %rbp now contains type | xor (%rcx,%rbx,1), %ebp # %rbp now contains type | ||
cmp $0x02, %bpl | cmp $0x02, %bpl | ||
− | + | jne next_section | |
− | + | ||
found_symbols: | found_symbols: | ||
Line 73: | Line 81: | ||
addq %rax, %r9 # r9 should now point to the first symbol | addq %rax, %r9 # r9 should now point to the first symbol | ||
addq %rax, %r10 # r10 should now point to the first string | addq %rax, %r10 # r10 should now point to the first string | ||
+ | addq $0x18, %r9 | ||
next_symbol: | next_symbol: | ||
− | + | addq $0x18,%r9 | |
xor %rcx, %rcx | xor %rcx, %rcx | ||
xor %rbp, %rbp | xor %rbp, %rbp | ||
Line 103: | Line 112: | ||
syscall | syscall | ||
jmp next_symbol | jmp next_symbol | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</source>}} | </source>}} | ||
[hatter@bha soinject]$ ./test_parser | [hatter@bha soinject]$ ./test_parser | ||
+ | startup | ||
+ | |||
getpc | getpc | ||
+ | |||
+ | find_header | ||
+ | |||
+ | find_sections | ||
next_section | next_section | ||
+ | |||
+ | found_symbols | ||
+ | |||
+ | next_symbol | ||
print_symbol_name | print_symbol_name | ||
+ | |||
+ | strlen | ||
+ | |||
+ | next_byte | ||
+ | |||
+ | _start | ||
__bss_start | __bss_start | ||
+ | |||
+ | _edata | ||
+ | |||
+ | _end | ||
'''Segmentation fault''' | '''Segmentation fault''' | ||
− | |||
− | |||
== Headers == | == Headers == |
Latest revision as of 05:59, 19 September 2012
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 or size checking) assembly code that will dump its own symbols:
.section .data .section .text .globl _start _start: jmp startup strlen: xor %rdx, %rdx next_byte: inc %rdx cmpb $0x00, (%rsi,%rdx,1); jne next_byte ret 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 jne 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 addq $0x18, %r9 next_symbol: addq $0x18,%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 |
[hatter@bha soinject]$ ./test_parser startup getpc find_header find_sections next_section found_symbols next_symbol print_symbol_name strlen next_byte _start __bss_start _edata _end 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