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 5 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 =

0xd8 + 0x5 * 0x28 =

216 + 5 * 40 = 0x1a0 = 416

ls reported a file size of 416 bytes.

6.3. Observations

The start of section .text, 0x8048080, equals the entry point (compare with objdump -fp). This is nowhere specified in the standard. But further down it is demonstrated on /bin/bash. 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.4. Sections of /bin/tcsh

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

Command: pre/i386-redhat8.0-linux/sections/sh/readelf.sh
#!/bin/bash
shell=$( /bin/sed 1q \
	out/i386-redhat8.0-linux/scanner/segment_padding/infect )
/bin/ls -Ll ${shell}
/usr/bin/readelf -S ${shell}

Output: out/i386-redhat8.0-linux/sections/sh/readelf
-rwxr-xr-x    1 root     root       365432 Aug  8  2002 /bin/tcsh
There are 28 section headers, starting at offset 0x4dcfc:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        08048114 000114 000013 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            08048128 000128 000020 00   A  0   0  4
  [ 3] .hash             HASH            08048148 000148 000458 04   A  4   0  4
  [ 4] .dynsym           DYNSYM          080485a0 0005a0 000910 10   A  5   1  4
  [ 5] .dynstr           STRTAB          08048eb0 000eb0 000536 00   A  0   0  1
  [ 6] .gnu.version      VERSYM          080493e6 0013e6 000122 02   A  4   0  2
  [ 7] .gnu.version_r    VERNEED         08049508 001508 000060 00   A  5   2  4
  [ 8] .rel.dyn          REL             08049568 001568 000028 08   A  4   0  4
  [ 9] .rel.plt          REL             08049590 001590 0003d0 08   A  4   b  4
  [10] .init             PROGBITS        08049960 001960 000018 00  AX  0   0  4
  [11] .plt              PROGBITS        08049978 001978 0007b0 04  AX  0   0  4
  [12] .text             PROGBITS        0804a130 002130 0405ec 00  AX  0   0 16
  [13] .fini             PROGBITS        0808a71c 04271c 00001c 00  AX  0   0  4
  [14] .rodata           PROGBITS        0808a740 042740 006bcc 00   A  0   0 32
  [15] .eh_frame_hdr     PROGBITS        0809130c 04930c 00004c 00   A  0   0  4
  [16] .data             PROGBITS        08092360 049360 0034a0 00  WA  0   0 32
  [17] .eh_frame         PROGBITS        08095800 04c800 0002ac 00  WA  0   0  4
  [18] .dynamic          DYNAMIC         08095aac 04caac 0000d8 08  WA  5   0  4
  [19] .ctors            PROGBITS        08095b84 04cb84 000008 00  WA  0   0  4
  [20] .dtors            PROGBITS        08095b8c 04cb8c 000008 00  WA  0   0  4
  [21] .jcr              PROGBITS        08095b94 04cb94 000004 00  WA  0   0  4
  [22] .got              PROGBITS        08095b98 04cb98 0001f8 04  WA  0   0  4
  [23] .bss              NOBITS          08095da0 04cda0 030100 00  WA  0   0 32
  [24] .comment          PROGBITS        00000000 04cda0 000e7f 00      0   0  1
  [25] .shstrtab         STRTAB          00000000 04dc1f 0000dc 00      0   0  1
  [26] .symtab           SYMTAB          00000000 04e15c 006eb0 10     27 270  4
  [27] .strtab           STRTAB          00000000 05500c 00436c 00      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 =

0x4dcfc + 0x28 * 0x28 =

318716 + 40 * 40 = 0x4e33c = 320316

ls reported a file size of 365432 bytes.

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

Notes

[1]

http://www.linuxbase.org/

[2]

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