Questions about this topic? Sign up to ask in the talk tab.

Difference between revisions of "User:Hatter/ELF format"

From NetSec
Jump to: navigation, search
(Parsing elf files)
(Parsing elf files)
 
(One intermediate revision by one other user not shown)
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
  je found_symbols
+
  jne next_section
jmp next_section
+
  
 
found_symbols:
 
found_symbols:
Line 74: Line 82:
 
  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
 
  addq $0x18, %r9
 +
 
next_symbol:
 
next_symbol:
 
  addq $0x18,%r9
 
  addq $0x18,%r9
Line 103: Line 112:
 
  syscall
 
  syscall
 
  jmp next_symbol
 
  jmp next_symbol
 
strlen:
 
xor %rdx, %rdx
 
next_byte:
 
inc %rdx
 
cmpb $0x00, (%rsi,%rdx,1);
 
jne next_byte
 
ret
 
 
</source>}}
 
</source>}}
  

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