What Are Fake ELF Section Headers?

Ali Bahrami — Thursday November 01, 2007

Surfing with the Linker-Aliens

I'd like to take a moment to explain an unusual feature we added to elfdump last summer. The -P option tells elfdump to ignore the section headers in the file (if any) and to instead generate a "fake" set from the program headers. So, what are fake section headers, and why would you want them?

Earlier this year, there was an "incident" in which a previously unknown hole in the Solaris telnet daemon was used by a worm. As soon as we got a copy of this worm, we tried to examine it with elfdump to see what we might learn:

% elfdump zoneadmd

ELF Header
  ei_magic:   { 0x7f, E, L, F }
  ei_class:   ELFCLASS32          ei_data:      ELFDATA2LSB
  e_machine:  EM_386              e_version:    EV_CURRENT
  e_type:     ET_EXEC
  e_flags:                     0
  e_entry:             0x80512d4  e_ehsize:     52  e_shstrndx:  0
  e_shoff:                     0  e_shentsize:   0  e_shnum:     0
  e_phoff:                  0x34  e_phentsize:  32  e_phnum:     5

Program Header[0]:
    p_vaddr:      0x8050034   p_flags:    [ PF_X  PF_R ]
    p_paddr:      0           p_type:     [ PT_PHDR ]
    p_filesz:     0xa0        p_memsz:    0xa0
    p_offset:     0x34        p_align:    0

Program Header[1]:
    p_vaddr:      0           p_flags:    [ PF_R ]
    p_paddr:      0           p_type:     [ PT_INTERP ]
    p_filesz:     0x11        p_memsz:    0
    p_offset:     0xd4        p_align:    0

Program Header[2]:
    p_vaddr:      0x8050000   p_flags:    [ PF_X  PF_R ]
    p_paddr:      0           p_type:     [ PT_LOAD ]
    p_filesz:     0x6491      p_memsz:    0x6491
    p_offset:     0           p_align:    0x10000

Program Header[3]:
    p_vaddr:      0x8066494   p_flags:    [ PF_X  PF_W  PF_R ]
    p_paddr:      0           p_type:     [ PT_LOAD ]
    p_filesz:     0x3e0       p_memsz:    0xc10
    p_offset:     0x6494      p_align:    0x10000

Program Header[4]:
    p_vaddr:      0x80665c4   p_flags:    [ PF_X  PF_W  PF_R ]
    p_paddr:      0           p_type:     [ PT_DYNAMIC ]
    p_filesz:     0xd8        p_memsz:    0
    p_offset:     0x65c4      p_align:    0
That's it — everything that elfdump could tell us about this object. We sure didn't learn much from that!

If you look at the ELF header, you'll see that our bad guy has set the e_shnum, e_shoff, and e_shentsize fields to zero. These fields are used to locate the section headers for an ELF object. The section headers in turn contain the information needed to look deeper into an object. Section headers are not used to run a program, only to examine it. Zeroing them is a crude, but effective way to obscure what's inside. ELF objects are just files after all, and anyone with write access can modify them. It's not unheard of to modify an ELF object using a binary capable editor like emacs.

Fortunately, the design of ELF makes it difficult to actually hide what an object calls from other sharable objects. And since the system call stubs are all located in libc, you can't hide the system calls your code makes. Here is one way to look inside:

% ldd -r -e LD_DEBUG=bindings zoneadmd 2>&1 | fgrep "binding file=zoneadmd"
04992: binding file=zoneadmd to 0x0 (undefined weak): symbol `__deregister_frame_info_bases'
04992: binding file=zoneadmd to 0x0 (undefined weak): symbol `__register_frame_info_bases'
04992: binding file=zoneadmd to 0x0 (undefined weak): symbol `_Jv_RegisterClasses'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `_environ'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `__iob'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `_cleanup'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `atexit'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `__fpstart'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `exit'
04992: binding file=zoneadmd to 0x0 (undefined weak): symbol `__deregister_frame_info_bases'
04992: binding file=zoneadmd to 0x0 (undefined weak): symbol `_Jv_RegisterClasses'
04992: binding file=zoneadmd to 0x0 (undefined weak): symbol `__register_frame_info_bases'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `getenv'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `setsid'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `printf'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fflush'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `signal'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `pthread_create'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `pthread_join'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `malloc'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `pthread_cancel'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `free'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `close'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `snprintf'
04992: binding file=zoneadmd to file=/lib/libnsl.so.1: symbol `inet_addr'
04992: binding file=zoneadmd to file=/lib/libnsl.so.1: symbol `gethostbyname'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `bcopy'
04992: binding file=zoneadmd to file=/lib/libsocket.so.1: symbol `ntohl'
04992: binding file=zoneadmd to file=/lib/libsocket.so.1: symbol `socket'
04992: binding file=zoneadmd to file=/lib/libsocket.so.1: symbol `htons'
04992: binding file=zoneadmd to file=/lib/libsocket.so.1: symbol `htonl'
04992: binding file=zoneadmd to file=/lib/libsocket.so.1: symbol `connect'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `___errno'
04992: binding file=zoneadmd to file=/lib/libsocket.so.1: symbol `getsockopt'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fcntl'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `select'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `write'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `read'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `strcpy'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `gettimeofday'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `strstr'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `mkstemp'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fdopen'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fopen'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `unlink'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fputs'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fputc'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `lseek'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fclose'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fprintf'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fread'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `putc'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `_xstat'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `_lxstat'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `_fxstat'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `_xmknod'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `open'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `mmap'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `strrchr'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `nanosleep'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `fork'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `dup2'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `pipe'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `execve'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `kill'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `waitpid'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `localtime_r'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `utimes'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `strchr'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `sscanf'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `strtoul'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `rename'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `chmod'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `execl'
04992: binding file=zoneadmd to file=/lib/libc.so.1: symbol `lockf' 
Unlike some other object systems, ELF inter-object references are always looked up by name at runtime. The runtime linker hashes the name and looks it up on the first reference. So if you want to actually call something outside of your own object, you have to call it by its real name. This information is located via the object's program headers, and unlike the section headers, they need to be reasonably accurate for the object to work.

The above experience led us to consider a new feature for elfdump. What if we started with the program headers, and generated a set of "fake" section headers based on the information they contain? Obviously the information available would be reduced in comparison to the real section headers, because the program headers only contain the information needed to run the object. Nonetheless, it would certainly be better than nothing in the case where the section headers are gone. And what about the case where they are present, but we fear that they have been maliciously modified? The information from the "fake" section headers could be compared to that from the actual section headers.

As a result of this worm episode and the aftermath, I added the -P option to elfdump last July:

PSARC 2007/395 Add -P option to elfdump
6530249 elfdump should handle ELF files with no section header table
With an object that has section headers, fake section headers will not be used unless you explicitly use the -P option. If an object doesn't have any section headers, then elfdump automatically turns on the -P option for you.

Let's use the new elfdump with fake section headers to examine the telnet worm. I apologize for the length of this output, but the length underscores the point — there is a lot of information that we can recover from this damaged object:

% elfdump zoneadmd

ELF Header
  ei_magic:   { 0x7f, E, L, F }
  ei_class:   ELFCLASS32          ei_data:      ELFDATA2LSB
  e_machine:  EM_386              e_version:    EV_CURRENT
  e_type:     ET_EXEC
  e_flags:                     0
  e_entry:             0x80512d4  e_ehsize:     52  e_shstrndx:  0
  e_shoff:                     0  e_shentsize:   0  e_shnum:     0  (see shdr[0].sh_size)
  e_phoff:                  0x34  e_phentsize:  32  e_phnum:     5

Program Header[0]:
    p_vaddr:      0x8050034   p_flags:    [ PF_X PF_R ]
    p_paddr:      0           p_type:     [ PT_PHDR ]
    p_filesz:     0xa0        p_memsz:    0xa0
    p_offset:     0x34        p_align:    0

Program Header[1]:
    p_vaddr:      0           p_flags:    [ PF_R ]
    p_paddr:      0           p_type:     [ PT_INTERP ]
    p_filesz:     0x11        p_memsz:    0
    p_offset:     0xd4        p_align:    0

Program Header[2]:
    p_vaddr:      0x8050000   p_flags:    [ PF_X PF_R ]
    p_paddr:      0           p_type:     [ PT_LOAD ]
    p_filesz:     0x6491      p_memsz:    0x6491
    p_offset:     0           p_align:    0x10000

Program Header[3]:
    p_vaddr:      0x8066494   p_flags:    [ PF_X PF_W PF_R ]
    p_paddr:      0           p_type:     [ PT_LOAD ]
    p_filesz:     0x3e0       p_memsz:    0xc10
    p_offset:     0x6494      p_align:    0x10000

Program Header[4]:
    p_vaddr:      0x80665c4   p_flags:    [ PF_X PF_W PF_R ]
    p_paddr:      0           p_type:     [ PT_DYNAMIC ]
    p_filesz:     0xd8        p_memsz:    0
    p_offset:     0x65c4      p_align:    0

Section Header[1]:  sh_name: .dynamic(phdr)
    sh_addr:      0x80665c4       sh_flags:   [ SHF_WRITE SHF_ALLOC ]
    sh_size:      0xd8            sh_type:    [ SHT_DYNAMIC ]
    sh_offset:    0x65c4          sh_entsize: 0x8 (27 entries)
    sh_link:      2               sh_info:    0
    sh_addralign: 0x4       

Section Header[2]:  sh_name: .dynstr(phdr)
    sh_addr:      0x8050890       sh_flags:   [ SHF_ALLOC ]
    sh_size:      0x2da           sh_type:    [ SHT_STRTAB ]
    sh_offset:    0x890           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1       

Section Header[3]:  sh_name: .dynsym(phdr)
    sh_addr:      0x8050380       sh_flags:   [ SHF_ALLOC ]
    sh_size:      0x510           sh_type:    [ SHT_DYNSYM ]
    sh_offset:    0x380           sh_entsize: 0x10 (81 entries)
    sh_link:      2               sh_info:    1
    sh_addralign: 0x4       

Section Header[4]:  sh_name: .hash(phdr)
    sh_addr:      0x80500e8       sh_flags:   [ SHF_ALLOC ]
    sh_size:      0x298           sh_type:    [ SHT_HASH ]
    sh_offset:    0xe8            sh_entsize: 0x4 (166 entries)
    sh_link:      3               sh_info:    0
    sh_addralign: 0x4       

Section Header[5]:  sh_name: .SUNW_version(phdr)
    sh_addr:      0x8050b6c       sh_flags:   [ SHF_ALLOC ]
    sh_size:      0xa0            sh_type:    [ SHT_SUNW_verneed ]
    sh_offset:    0xb6c           sh_entsize: 0x1 (160 entries)
    sh_link:      2               sh_info:    5
    sh_addralign: 0x4       

Section Header[6]:  sh_name: .interp(phdr)
    sh_addr:      0x80500d4       sh_flags:   [ SHF_ALLOC ]
    sh_size:      0x11            sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0xd4            sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1       

Section Header[7]:  sh_name: .rel(phdr)
    sh_addr:      0x8050c0c       sh_flags:   [ SHF_ALLOC ]
    sh_size:      0x258           sh_type:    [ SHT_REL ]
    sh_offset:    0xc0c           sh_entsize: 0x8 (75 entries)
    sh_link:      3               sh_info:    0
    sh_addralign: 0x4       

Interpreter Section:  .interp(phdr)
	/usr/lib/ld.so.1

Version Needed Section:  .SUNW_version(phdr)
            file                        version
            libnsl.so.1                 SUNW_0.7             
            libsocket.so.1              SUNW_0.7             
            librt.so.1                  SUNW_1.2             
            libpthread.so.1             SUNW_1.2             
            libc.so.1                   SUNW_1.1             

Symbol Table Section:  .dynsym(phdr)
     index    value      size      type bind oth ver shndx          name
       [0]  0x00000000 0x00000000  NOTY LOCL  D    0 UNDEF          
       [1]  0x08067088 0x00000004  OBJT WEAK  D    0 22             environ
       [2]  0x080511f4 0x00000000  FUNC GLOB  D    0 UNDEF          dup2
       [3]  0x00000000 0x00000000  NOTY WEAK  D    0 UNDEF          _Jv_RegisterClasses
       [4]  0x080510a4 0x00000000  FUNC GLOB  D    0 UNDEF          strstr
       [5]  0x08050f64 0x00000000  FUNC GLOB  D    0 UNDEF          pthread_cancel
       [6]  0x080511a4 0x00000000  FUNC GLOB  D    0 UNDEF          open
       [7]  0x080511d4 0x00000000  FUNC GLOB  D    0 UNDEF          nanosleep
       [8]  0x08051244 0x00000000  FUNC GLOB  D    0 UNDEF          localtime_r
       [9]  0x080665c4 0x00000000  OBJT GLOB  D    0 15             _DYNAMIC
      [10]  0x08050ea4 0x00000000  FUNC GLOB  D    0 UNDEF          exit
      [11]  0x08051174 0x00000000  FUNC GLOB  D    0 UNDEF          _lxstat
      [12]  0x080670a4 0x00000000  OBJT GLOB  D    0 22             _end
      [13]  0x08050fd4 0x00000000  FUNC GLOB  D    0 UNDEF          ntohl
      [14]  0x080510e4 0x00000000  FUNC GLOB  D    0 UNDEF          unlink
      [15]  0x08051114 0x00000000  FUNC GLOB  D    0 UNDEF          lseek
      [16]  0x08050ee4 0x00000000  FUNC GLOB  D    0 UNDEF          getenv
      [17]  0x08051234 0x00000000  FUNC GLOB  D    0 UNDEF          waitpid
      [18]  0x080510d4 0x00000000  FUNC GLOB  D    0 UNDEF          fopen
      [19]  0x08051164 0x00000000  FUNC GLOB  D    0 UNDEF          _xstat
      [20]  0x08051074 0x00000000  FUNC GLOB  D    0 UNDEF          read
      [21]  0x080511e4 0x00000000  FUNC GLOB  D    0 UNDEF          fork
      [22]  0x08051094 0x00000000  FUNC GLOB  D    0 UNDEF          gettimeofday
      [23]  0x08050fe4 0x00000000  FUNC GLOB  D    0 UNDEF          socket
      [24]  0x00000000 0x00000000  NOTY WEAK  D    0 UNDEF          __deregister_frame_info_bases
      [25]  0x08051294 0x00000000  FUNC GLOB  D    0 UNDEF          rename
      [26]  0x08050f54 0x00000000  FUNC GLOB  D    0 UNDEF          malloc
      [27]  0x080511b4 0x00000000  FUNC GLOB  D    0 UNDEF          mmap
      [28]  0x08050f94 0x00000000  FUNC GLOB  D    0 UNDEF          snprintf
      [29]  0x08051284 0x00000000  FUNC GLOB  D    0 UNDEF          strtoul
      [30]  0x08051264 0x00000000  FUNC GLOB  D    0 UNDEF          strchr
      [31]  0x08051274 0x00000000  FUNC GLOB  D    0 UNDEF          sscanf
      [32]  0x08051224 0x00000000  FUNC GLOB  D    0 UNDEF          kill
      [33]  0x08051254 0x00000000  FUNC GLOB  D    0 UNDEF          utimes
      [34]  0x08051184 0x00000000  FUNC GLOB  D    0 UNDEF          _fxstat
      [35]  0x08050e94 0x00000000  FUNC GLOB  D    0 UNDEF          __fpstart
      [36]  0x08051124 0x00000000  FUNC GLOB  D    0 UNDEF          fclose
      [37]  0x080510b4 0x00000000  FUNC GLOB  D    0 UNDEF          mkstemp
      [38]  0x08066494 0x00000000  OBJT GLOB  D    0 14             _GLOBAL_OFFSET_TABLE_
      [39]  0x080512b4 0x00000000  FUNC GLOB  D    0 UNDEF          execl
      [40]  0x08051214 0x00000000  FUNC GLOB  D    0 UNDEF          execve
      [41]  0x08051144 0x00000000  FUNC GLOB  D    0 UNDEF          fread
      [42]  0x08050e74 0x00000000  FUNC WEAK  D    0 UNDEF          _cleanup
      [43]  0x08050f24 0x00000000  FUNC GLOB  D    0 UNDEF          signal
      [44]  0x08051064 0x00000000  FUNC GLOB  D    0 UNDEF          write
      [45]  0x080510c4 0x00000000  FUNC GLOB  D    0 UNDEF          fdopen
      [46]  0x08050e64 0x00000000  OBJT GLOB  D    0 9              _PROCEDURE_LINKAGE_TABLE_
      [47]  0x08051154 0x00000000  FUNC GLOB  D    0 UNDEF          putc
      [48]  0x08056491 0x00000000  OBJT GLOB  D    0 13             _etext
      [49]  0x08050ef4 0x00000000  FUNC GLOB  D    0 UNDEF          setsid
      [50]  0x080512a4 0x00000000  FUNC GLOB  D    0 UNDEF          chmod
      [51]  0x08051194 0x00000000  FUNC GLOB  D    0 UNDEF          _xmknod
      [52]  0x08066874 0x00000000  OBJT GLOB  D    0 21             _edata
      [53]  0x08051054 0x00000000  FUNC GLOB  D    0 UNDEF          select
      [54]  0x080668a0 0x000003c0  OBJT WEAK  D    0 22             _iob
      [55]  0x08051014 0x00000000  FUNC GLOB  D    0 UNDEF          connect
      [56]  0x08050fb4 0x00000000  FUNC GLOB  D    0 UNDEF          gethostbyname
      [57]  0x080511c4 0x00000000  FUNC GLOB  D    0 UNDEF          strrchr
      [58]  0x080668a0 0x000003c0  OBJT GLOB  D    0 22             __iob
      [59]  0x08050f14 0x00000000  FUNC GLOB  D    0 UNDEF          fflush
      [60]  0x08051034 0x00000000  FUNC GLOB  D    0 UNDEF          getsockopt
      [61]  0x08051044 0x00000000  FUNC GLOB  D    0 UNDEF          fcntl
      [62]  0x080512c4 0x00000000  FUNC GLOB  D    0 UNDEF          lockf
      [63]  0x08050fa4 0x00000000  FUNC GLOB  D    0 UNDEF          inet_addr
      [64]  0x08050f44 0x00000000  FUNC GLOB  D    0 UNDEF          pthread_join
      [65]  0x08051024 0x00000000  FUNC GLOB  D    0 UNDEF          ___errno
      [66]  0x08051104 0x00000000  FUNC GLOB  D    0 UNDEF          fputc
      [67]  0x08050e84 0x00000000  FUNC GLOB  D    0 UNDEF          atexit
      [68]  0x08050f04 0x00000000  FUNC GLOB  D    0 UNDEF          printf
      [69]  0x00000000 0x00000000  NOTY WEAK  D    0 UNDEF          __register_frame_info_bases
      [70]  0x08051204 0x00000000  FUNC GLOB  D    0 UNDEF          pipe
      [71]  0x08051004 0x00000000  FUNC GLOB  D    0 UNDEF          htonl
      [72]  0x08050fc4 0x00000000  FUNC GLOB  D    0 UNDEF          bcopy
      [73]  0x08050ff4 0x00000000  FUNC GLOB  D    0 UNDEF          htons
      [74]  0x08050f34 0x00000000  FUNC GLOB  D    0 UNDEF          pthread_create
      [75]  0x08067088 0x00000004  OBJT GLOB  D    0 22             _environ
      [76]  0x08050f84 0x00000000  FUNC GLOB  D    0 UNDEF          close
      [77]  0x08050f74 0x00000000  FUNC GLOB  D    0 UNDEF          free
      [78]  0x080510f4 0x00000000  FUNC GLOB  D    0 UNDEF          fputs
      [79]  0x08051134 0x00000000  FUNC GLOB  D    0 UNDEF          fprintf
      [80]  0x08051084 0x00000000  FUNC GLOB  D    0 UNDEF          strcpy

Hash Section:  .hash(phdr)
    bucket  symndx      name
         0  [1]         environ
            [2]         dup2
         1  [3]         _Jv_RegisterClasses
            [4]         strstr
         2  [5]         pthread_cancel
            [6]         open
            [7]         nanosleep
            [8]         localtime_r
         3  [9]         _DYNAMIC
         4  [10]        exit
         6  [11]        _lxstat
        10  [12]        _end
        15  [13]        ntohl
            [14]        unlink
        18  [15]        lseek
            [16]        getenv
        19  [17]        waitpid
        20  [18]        fopen
        21  [19]        _xstat
            [20]        read
        22  [21]        fork
        23  [22]        gettimeofday
            [23]        socket
            [24]        __deregister_frame_info_bases
        24  [25]        rename
            [26]        malloc
        27  [27]        mmap
        28  [28]        snprintf
        29  [29]        strtoul
            [30]        strchr
        30  [31]        sscanf
            [32]        kill
        31  [33]        utimes
        33  [34]        _fxstat
            [35]        __fpstart
            [36]        fclose
        34  [37]        mkstemp
        35  [38]        _GLOBAL_OFFSET_TABLE_
        38  [39]        execl
        39  [40]        execve
            [41]        fread
        41  [42]        _cleanup
        43  [43]        signal
            [44]        write
        44  [45]        fdopen
        46  [46]        _PROCEDURE_LINKAGE_TABLE_
            [47]        putc
            [48]        _etext
        47  [49]        setsid
        48  [50]        chmod
        49  [51]        _xmknod
        52  [52]        _edata
            [53]        select
            [54]        _iob
        53  [55]        connect
        55  [56]        gethostbyname
            [57]        strrchr
        59  [58]        __iob
            [59]        fflush
        62  [60]        getsockopt
            [61]        fcntl
            [62]        lockf
        63  [63]        inet_addr
            [64]        pthread_join
            [65]        ___errno
        64  [66]        fputc
            [67]        atexit
        65  [68]        printf
        66  [69]        __register_frame_info_bases
            [70]        pipe
            [71]        htonl
        71  [72]        bcopy
        73  [73]        htons
        76  [74]        pthread_create
        77  [75]        _environ
            [76]        close
        78  [77]        free
        80  [78]        fputs
            [79]        fprintf
        81  [80]        strcpy

        35  buckets contain        0 symbols
        25  buckets contain        1 symbols
        15  buckets contain        2 symbols
         7  buckets contain        3 symbols
         1  buckets contain        4 symbols
        83  buckets               80 symbols (globals)

Relocation Section:  .rel(phdr)
    type                       offset             section        symbol
  R_386_GLOB_DAT            0x80664b0             .rel(phdr)     __deregister_frame_info_bases
  R_386_GLOB_DAT            0x80664b8             .rel(phdr)     __register_frame_info_bases
  R_386_GLOB_DAT            0x80664bc             .rel(phdr)     _Jv_RegisterClasses
  R_386_COPY                0x8067088             .rel(phdr)     _environ
  R_386_COPY                0x80668a0             .rel(phdr)     __iob
  R_386_JMP_SLOT            0x80664a0             .rel(phdr)     _cleanup
  R_386_JMP_SLOT            0x80664a4             .rel(phdr)     atexit
  R_386_JMP_SLOT            0x80664a8             .rel(phdr)     __fpstart
  R_386_JMP_SLOT            0x80664ac             .rel(phdr)     exit
  R_386_JMP_SLOT            0x80664b4             .rel(phdr)     __deregister_frame_info_bases
  R_386_JMP_SLOT            0x80664c0             .rel(phdr)     _Jv_RegisterClasses
  R_386_JMP_SLOT            0x80664c4             .rel(phdr)     __register_frame_info_bases
  R_386_JMP_SLOT            0x80664c8             .rel(phdr)     getenv
  R_386_JMP_SLOT            0x80664cc             .rel(phdr)     setsid
  R_386_JMP_SLOT            0x80664d0             .rel(phdr)     printf
  R_386_JMP_SLOT            0x80664d4             .rel(phdr)     fflush
  R_386_JMP_SLOT            0x80664d8             .rel(phdr)     signal
  R_386_JMP_SLOT            0x80664dc             .rel(phdr)     pthread_create
  R_386_JMP_SLOT            0x80664e0             .rel(phdr)     pthread_join
  R_386_JMP_SLOT            0x80664e4             .rel(phdr)     malloc
  R_386_JMP_SLOT            0x80664e8             .rel(phdr)     pthread_cancel
  R_386_JMP_SLOT            0x80664ec             .rel(phdr)     free
  R_386_JMP_SLOT            0x80664f0             .rel(phdr)     close
  R_386_JMP_SLOT            0x80664f4             .rel(phdr)     snprintf
  R_386_JMP_SLOT            0x80664f8             .rel(phdr)     inet_addr
  R_386_JMP_SLOT            0x80664fc             .rel(phdr)     gethostbyname
  R_386_JMP_SLOT            0x8066500             .rel(phdr)     bcopy
  R_386_JMP_SLOT            0x8066504             .rel(phdr)     ntohl
  R_386_JMP_SLOT            0x8066508             .rel(phdr)     socket
  R_386_JMP_SLOT            0x806650c             .rel(phdr)     htons
  R_386_JMP_SLOT            0x8066510             .rel(phdr)     htonl
  R_386_JMP_SLOT            0x8066514             .rel(phdr)     connect
  R_386_JMP_SLOT            0x8066518             .rel(phdr)     ___errno
  R_386_JMP_SLOT            0x806651c             .rel(phdr)     getsockopt
  R_386_JMP_SLOT            0x8066520             .rel(phdr)     fcntl
  R_386_JMP_SLOT            0x8066524             .rel(phdr)     select
  R_386_JMP_SLOT            0x8066528             .rel(phdr)     write
  R_386_JMP_SLOT            0x806652c             .rel(phdr)     read
  R_386_JMP_SLOT            0x8066530             .rel(phdr)     strcpy
  R_386_JMP_SLOT            0x8066534             .rel(phdr)     gettimeofday
  R_386_JMP_SLOT            0x8066538             .rel(phdr)     strstr
  R_386_JMP_SLOT            0x806653c             .rel(phdr)     mkstemp
  R_386_JMP_SLOT            0x8066540             .rel(phdr)     fdopen
  R_386_JMP_SLOT            0x8066544             .rel(phdr)     fopen
  R_386_JMP_SLOT            0x8066548             .rel(phdr)     unlink
  R_386_JMP_SLOT            0x806654c             .rel(phdr)     fputs
  R_386_JMP_SLOT            0x8066550             .rel(phdr)     fputc
  R_386_JMP_SLOT            0x8066554             .rel(phdr)     lseek
  R_386_JMP_SLOT            0x8066558             .rel(phdr)     fclose
  R_386_JMP_SLOT            0x806655c             .rel(phdr)     fprintf
  R_386_JMP_SLOT            0x8066560             .rel(phdr)     fread
  R_386_JMP_SLOT            0x8066564             .rel(phdr)     putc
  R_386_JMP_SLOT            0x8066568             .rel(phdr)     _xstat
  R_386_JMP_SLOT            0x806656c             .rel(phdr)     _lxstat
  R_386_JMP_SLOT            0x8066570             .rel(phdr)     _fxstat
  R_386_JMP_SLOT            0x8066574             .rel(phdr)     _xmknod
  R_386_JMP_SLOT            0x8066578             .rel(phdr)     open
  R_386_JMP_SLOT            0x806657c             .rel(phdr)     mmap
  R_386_JMP_SLOT            0x8066580             .rel(phdr)     strrchr
  R_386_JMP_SLOT            0x8066584             .rel(phdr)     nanosleep
  R_386_JMP_SLOT            0x8066588             .rel(phdr)     fork
  R_386_JMP_SLOT            0x806658c             .rel(phdr)     dup2
  R_386_JMP_SLOT            0x8066590             .rel(phdr)     pipe
  R_386_JMP_SLOT            0x8066594             .rel(phdr)     execve
  R_386_JMP_SLOT            0x8066598             .rel(phdr)     kill
  R_386_JMP_SLOT            0x806659c             .rel(phdr)     waitpid
  R_386_JMP_SLOT            0x80665a0             .rel(phdr)     localtime_r
  R_386_JMP_SLOT            0x80665a4             .rel(phdr)     utimes
  R_386_JMP_SLOT            0x80665a8             .rel(phdr)     strchr
  R_386_JMP_SLOT            0x80665ac             .rel(phdr)     sscanf
  R_386_JMP_SLOT            0x80665b0             .rel(phdr)     strtoul
  R_386_JMP_SLOT            0x80665b4             .rel(phdr)     rename
  R_386_JMP_SLOT            0x80665b8             .rel(phdr)     chmod
  R_386_JMP_SLOT            0x80665bc             .rel(phdr)     execl
  R_386_JMP_SLOT            0x80665c0             .rel(phdr)     lockf

Dynamic Section:  .dynamic(phdr)
     index  tag                value
       [0]  NEEDED            0x27f               libnsl.so.1
       [1]  NEEDED            0x294               libsocket.so.1
       [2]  NEEDED            0x2a3               librt.so.1
       [3]  NEEDED            0x2b7               libpthread.so.1
       [4]  NEEDED            0x2c7               libc.so.1
       [5]  INIT              0x80538fc           
       [6]  FINI              0x8053909           
       [7]  HASH              0x80500e8           
       [8]  STRTAB            0x8050890           
       [9]  STRSZ             0x2da               
      [10]  SYMTAB            0x8050380           
      [11]  SYMENT            0x10                
      [12]  CHECKSUM          0x3126              
      [13]  VERNEED           0x8050b6c           
      [14]  VERNEEDNUM        0x5                 
      [15]  PLTRELSZ          0x230               
      [16]  PLTREL            0x11                
      [17]  JMPREL            0x8050c34           
      [18]  REL               0x8050c0c           
      [19]  RELSZ             0x258               
      [20]  RELENT            0x8                 
      [21]  DEBUG             0                   
      [22]  FEATURE_1         0x1                 [ PARINIT ]
      [23]  FLAGS             0                   0
      [24]  FLAGS_1           0                   0
      [25]  PLTGOT            0x8066494           
      [26]  NULL              0                   
I don't expect this feature to get much daily use, but it will be handy to have it in the forensic toolchest next time we're scrambling to understand a damaged or malicious object.
Surfing with the Linker-Aliens

Published Elsewhere

https://blogs.sun.com/ali/entry/what_are_fake_elf_section/
https://blogs.oracle.com/ali/entry/what_are_fake_elf_section/
https://blogs.oracle.com/ali/what-are-fake-elf-section-headers/

Surfing with the Linker-Aliens

[7] Changing ELF Runpaths
Blog Index (ali)
[9] Introducing elfedit