The ELF Virus Writing HOWTO: i386-redhat7.3-linux
Prev |  | Next

# 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

Command: pre/i386-redhat7.3-linux/sections/objdump.sh

    #!/bin/bash
    /bin/ls -Ll tmp/i386-redhat7.3-linux/evil_magic/intel
    /usr/bin/objdump -h tmp/i386-redhat7.3-linux/evil_magic/intel

Output: out/i386-redhat7.3-linux/sections/objdump

    -rwxrwxr-x    1 alba     alba          416 Jan  8 23:08 tmp/i386-redhat7.3-linux/evil_magic/intel

    tmp/i386-redhat7.3-linux/evil_magic/intel:     file format elf32-i386

    Sections:
    Idx Name          Size      VMA       LMA       File off  Algn
      0 .text         00000017  08048080  08048080  00000080  2**4
                      CONTENTS, ALLOC, LOAD, READONLY, CODE
      1 .bss          00000001  08049097  08049097  00000097  2**0
                      CONTENTS
      2 .comment      0000001f  00000000  00000000  00000098  2**0
                      CONTENTS, READONLY

`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`.

## 6.2. readelf

Command: pre/i386-redhat7.3-linux/sections/readelf.sh

    #!/bin/bash
    /bin/ls -Ll tmp/i386-redhat7.3-linux/evil_magic/intel
    /usr/bin/readelf -S tmp/i386-redhat7.3-linux/evil_magic/intel

Output: out/i386-redhat7.3-linux/sections/readelf

    -rwxrwxr-x    1 alba     alba          416 Jan  8 23:08 tmp/i386-redhat7.3-linux/evil_magic/intel
    There are 5 section headers, starting at offset 0xd8:

    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            00000000 000000 000000 00      0   0  0
      [ 1] .text             PROGBITS        08048080 000080 000017 00  AX  0   0 16
      [ 2] .bss              PROGBITS        08049097 000097 000001 00   W  0   0  1
      [ 3] .comment          PROGBITS        00000000 000098 00001f 00      0   0  1
      [ 4] .shstrtab         STRTAB          00000000 0000b7 00001f 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)

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/sh

Anyway, we see that even for trivial examples the code is surrounded by lots of other stuff. Let's zoom in on our target.

Command: pre/i386-redhat7.3-linux/sections/sh/readelf.sh

    #!/bin/bash
    /bin/ls -Ll /bin/bash
    /usr/bin/readelf -S /bin/bash

Output: out/i386-redhat7.3-linux/sections/sh/readelf

    -rwxr-xr-x    1 root     root       541096 Apr 12  2002 /bin/bash
    There are 23 section headers, starting at offset 0x83e10:

    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        080480f4 0000f4 000013 00   A  0   0  1
      [ 2] .note.ABI-tag     NOTE            08048108 000108 000020 00   A  0   0  4
      [ 3] .hash             HASH            08048128 000128 002a20 04   A  4   0  4
      [ 4] .dynsym           DYNSYM          0804ab48 002b48 0067f0 10   A  5   1  4
      [ 5] .dynstr           STRTAB          08051338 009338 006538 00   A  0   0  1
      [ 6] .gnu.version      VERSYM          08057870 00f870 000cfe 02   A  4   0  2
      [ 7] .gnu.version_r    VERNEED         08058570 010570 000070 00   A  5   2  4
      [ 8] .rel.dyn          REL             080585e0 0105e0 000058 08   A  4   0  4
      [ 9] .rel.plt          REL             08058638 010638 0004a0 08   A  4   b  4
      [10] .init             PROGBITS        08058ad8 010ad8 000018 00  AX  0   0  4
      [11] .plt              PROGBITS        08058af0 010af0 000950 04  AX  0   0  4
      [12] .text             PROGBITS        08059440 011440 058680 00  AX  0   0 16
      [13] .fini             PROGBITS        080b1ac0 069ac0 00001e 00  AX  0   0  4
      [14] .rodata           PROGBITS        080b1ae0 069ae0 014934 00   A  0   0 32
      [15] .data             PROGBITS        080c7420 07e420 0055e8 00  WA  0   0 32
      [16] .eh_frame         PROGBITS        080cca08 083a08 000004 00  WA  0   0  4
      [17] .dynamic          DYNAMIC         080cca0c 083a0c 0000d8 08  WA  5   0  4
      [18] .ctors            PROGBITS        080ccae4 083ae4 000008 00  WA  0   0  4
      [19] .dtors            PROGBITS        080ccaec 083aec 000008 00  WA  0   0  4
      [20] .got              PROGBITS        080ccaf4 083af4 000260 04  WA  0   0  4
      [21] .bss              NOBITS          080ccd60 083d60 004190 00  WA  0   0 32
      [22] .shstrtab         STRTAB          00000000 083d60 0000b0 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 =`

> `0x83e10 + 0x23 * 0x28 =`

> `540176 + 35 * 40 = 0x84388 = 541576`

`ls` reported a file size of 541096 bytes.

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

### Notes

[1] | http://www.linuxbase.org/
[2] | http://www.linuxbase.org/spec/gLSB/gLSB/specialsections.html

Prev | Home | Next
Segments |  | Scanners