6. Sections

 

All trails have more uphill sections than they have downhill sections.

 Shedenhelm's Law

The standard describes section headers as optional for programs, but you can't build dynamically linked executables without them. Still worse, strip(1) performs a destructive operation on the section headers that will break infected executables if we don't maintain the section headers as well. Let's have another look at The language of evil.

6.1. objdump -h

objdump's output for sections is outright disgusting. A real problem is the broken numbering due to ignored entries in the section table. The item on index 0 is actually of type SHT_NULL. Its index (SHN_UNDEF = 0) serves to mark an unused value of sh_link. Less troublesome is the ignored string table, a section of type STRTAB. And it does not help at all that the section type itself is not included in the output.

6.2. readelf

The line starting with "There are 17 section headers" shows the value of e_shnum and e_shoff. Since Offset of e_entry we know that sizeof(Elf32_Shdr) is 40.

First byte beyond the section header table:

e_shoff + e_shnum * sizeof_Shdr =

0x3d0 + 0x11 * 0x28 =

976 + 17 * 40 = 0x678 = 1656

ls reported a file size of 1416 bytes.

6.3. elfdump

elfdump also omits section SHT_NULL but at least gets the numbering right.

Output: out/sparc-sunos5.9/sections/elfdump
-rwxr-xr-x   1 alba     alba        1416 Feb 15  2003 att

Section Header[1]:  sh_name: .interp
    sh_addr:      0x100d4         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[2]:  sh_name: .hash
    sh_addr:      0x100e8         sh_flags:   [ SHF_ALLOC ]
    sh_size:      0x44            sh_type:    [ SHT_HASH ]
    sh_offset:    0xe8            sh_entsize: 0x4
    sh_link:      3               sh_info:    0
    sh_addralign: 0x4           

Section Header[3]:  sh_name: .dynsym
    sh_addr:      0x1012c         sh_flags:   [ SHF_ALLOC ]
    sh_size:      0x80            sh_type:    [ SHT_DYNSYM ]
    sh_offset:    0x12c           sh_entsize: 0x10
    sh_link:      4               sh_info:    1
    sh_addralign: 0x4           

Section Header[4]:  sh_name: .dynstr
    sh_addr:      0x101ac         sh_flags:   [ SHF_ALLOC  SHF_STRINGS ]
    sh_size:      0xa2            sh_type:    [ SHT_STRTAB ]
    sh_offset:    0x1ac           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1           

Section Header[5]:  sh_name: .text
    sh_addr:      0x10250         sh_flags:   [ SHF_ALLOC  SHF_EXECINSTR ]
    sh_size:      0x24            sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x250           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x4           

Section Header[6]:  sh_name: .got
    sh_addr:      0x20274         sh_flags:   [ SHF_WRITE  SHF_ALLOC ]
    sh_size:      0x4             sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x274           sh_entsize: 0x4
    sh_link:      0               sh_info:    0
    sh_addralign: 0x4           

Section Header[7]:  sh_name: .dynamic
    sh_addr:      0x20278         sh_flags:   [ SHF_WRITE  SHF_ALLOC ]
    sh_size:      0x90            sh_type:    [ SHT_DYNAMIC ]
    sh_offset:    0x278           sh_entsize: 0x8
    sh_link:      4               sh_info:    0
    sh_addralign: 0x4           

Section Header[8]:  sh_name: .bss
    sh_addr:      0x20308         sh_flags:   [ SHF_WRITE  SHF_ALLOC ]
    sh_size:      0               sh_type:    [ SHT_NOBITS ]
    sh_offset:    0x308           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1           

Section Header[9]:  sh_name: .comment
    sh_addr:      0               sh_flags:   0
    sh_size:      0x6b            sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x308           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1           

Section Header[10]:  sh_name: .shstrtab
    sh_addr:      0               sh_flags:   [ SHF_STRINGS ]
    sh_size:      0x5b            sh_type:    [ SHT_STRTAB ]
    sh_offset:    0x373           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x1           

6.4. Observations

The start of section .text, 0x10250, equals the entry point (compare with objdump -fp). This is nowhere specified in the standard. But further down it is demonstrated on /usr/xpg4/bin/sh. See Scan entry point for empirical prove.

The relation between file size and ELF header is more complicated. In most executables the section header table itself is the last region of the file. But there is a second kind where the section described by the last item of the section header table is the last region of the file. With gcc the type of this last section is always SHT_STRTAB. Some of Sun's native sparc executables have a section called .comment (type SHT_PROGBITS) there instead. See Scan file size for empirical prove.

6.5. Sections of /usr/bin/csh

Let's zoom in on our target. [1].

Command: pre/sparc-sunos5.9/sections/sh/readelf.sh
#!/usr/xpg4/bin/sh
shell=$( /usr/xpg4/bin/sed 1q \
	out/sparc-sunos5.9/scanner/segment_padding/infect )
/usr/xpg4/bin/ls -Ll ${shell}
/opt/sfw/bin/greadelf -S ${shell}

Output: out/sparc-sunos5.9/sections/sh/readelf
-r-xr-xr-x   2 root     bin       159332 Apr  7  2002 /usr/bin/csh
There are 28 section headers, starting at offset 0x26a04:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .SUNW_syminfo     VERDEF          000100f4 0000f4 000d44 04  AI  4  14  4
  [ 2] .interp           PROGBITS        00010e38 000e38 000011 00   A  0   0  1
  [ 3] .hash             HASH            00010e4c 000e4c 001a98 04   A  4   0  4
  [ 4] .dynsym           DYNSYM          000128e4 0028e4 003510 10   A  5   1  4
  [ 5] .dynstr           STRTAB          00015df4 005df4 001ac9 00  AS  0   0  1
  [ 6] .SUNW_version     VERNEED         000178c0 0078c0 000070 00   A  5   3  4
  [ 7] .rela.ex_shared   RELA            00017930 007930 000030 0c  AI  4  15  4
  [ 8] .rela.cpp_finidat RELA            00017960 007960 00000c 0c  AI  4  16  4
  [ 9] .rela.data        RELA            0001796c 00796c 00000c 0c  AI  4  17  4
  [10] .rela.bss         RELA            00017978 007978 000018 0c  AI  4  19  4
  [11] .rela.plt         RELA            00017990 007990 00057c 0c  AI  4  13  4
  [12] .text             PROGBITS        00017f0c 007f0c 01af8c 00  AX  0   0  4
  [13] .init             PROGBITS        00032e98 022e98 000050 00  AX  0   0  4
  [14] .fini             PROGBITS        00032ee8 022ee8 000080 00  AX  0   0  4
  [15] .exception_ranges PROGBITS        00032f68 022f68 000004 00   A  0   0  4
  [16] .rodata           PROGBITS        00032f6c 022f6c 00003c 00   A  0   0  4
  [17] .rodata1          PROGBITS        00032fa8 022fa8 0004fc 00   A  0   0  4
  [18] .got              PROGBITS        00044000 024000 000004 04  WA  0   0 8192
  [19] .plt              PROGBITS        00044004 024004 0005b0 0c WAX  0   0  4
  [20] .dynamic          DYNAMIC         000445b4 0245b4 000100 08  WA  5   0  4
  [21] .ex_shared        PROGBITS        000446b4 0246b4 000028 00  WA  0   0  4
  [22] .cpp_finidata     PROGBITS        000446dc 0246dc 00000c 00  WA  0   0  4
  [23] .data             PROGBITS        000446e8 0246e8 001600 00  WA  0   0  8
  [24] .data1            PROGBITS        00045ce8 025ce8 000bf8 00  WA  0   0  4
  [25] .bss              NOBITS          000468e0 0268e0 003958 00  WA  0   0  8
  [26] .comment          PROGBITS        00000000 0268e0 000020 00      0   0  1
  [27] .shstrtab         STRTAB          00000000 026900 000103 00   S  0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

First byte beyond the section header table:

e_shoff + e_shnum * sizeof_Shdr =

0x26a04 + 0x28 * 0x28 =

158212 + 40 * 40 = 0x27044 = 159812

ls reported a file size of 159332 bytes.

LSB [1] has a good overview of section names. [2] Anyway, a detailed look on section .text shows that its start address (0x17f0c) equals the entry point (compare with Segments of /usr/bin/csh).

Notes

[1]

http://www.linuxbase.org/

[2]

http://www.linuxbase.org/spec/gLSB/gLSB/specialsections.html