The ELF Virus Writing HOWTO: sparc-sunos5.7
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/sparc-sunos5.7/sections/objdump.sh

    #!/usr/xpg4/bin/sh
    /usr/xpg4/bin/ls -Ll tmp/sparc-sunos5.7/evil_magic/att
    /usr/local/bin/objdump -h tmp/sparc-sunos5.7/evil_magic/att

Output: out/sparc-sunos5.7/sections/objdump

    -rwxr-xr-x   1 alba     alba         444 Jan  8 23:11 tmp/sparc-sunos5.7/evil_magic/att

    tmp/sparc-sunos5.7/evil_magic/att:     file format elf32-sparc

    Sections:
    Idx Name          Size      VMA               LMA               File off  Algn
      0 .text         00000024  0000000000010074  0000000000010074  00000074  2**0
                      CONTENTS, ALLOC, LOAD, READONLY, CODE
      1 .data         00000000  0000000000020098  0000000000020098  00000098  2**0
                      CONTENTS, ALLOC, LOAD, DATA
      2 .sbss         00000000  0000000000020098  0000000000020098  00000098  2**0
                      CONTENTS
      3 .bss          00000000  0000000000020098  0000000000020098  00000098  2**0
                      ALLOC

`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/sparc-sunos5.7/sections/readelf.sh

    #!/usr/xpg4/bin/sh
    /usr/xpg4/bin/ls -Ll tmp/sparc-sunos5.7/evil_magic/att
    /usr/local/bin/readelf -S tmp/sparc-sunos5.7/evil_magic/att

Output: out/sparc-sunos5.7/sections/readelf

    -rwxr-xr-x   1 alba     alba         444 Jan  8 23:11 tmp/sparc-sunos5.7/evil_magic/att
    There are 6 section headers, starting at offset 0xcc:

    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        00010074 000074 000024 00  AX  0   0  1
      [ 2] .data             PROGBITS        00020098 000098 000000 00  WA  0   0  1
      [ 3] .sbss             PROGBITS        00020098 000098 000000 00   W  0   0  1
      [ 4] .bss              NOBITS          00020098 000098 000000 00  WA  0   0  1
      [ 5] .shstrtab         STRTAB          00000000 000098 000032 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 6 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 =`

> `0xcc + 0x6 * 0x28 =`

> `204 + 6 * 40 = 0x1bc = 444`

`ls` reported a file size of 444 bytes.

## 6.3. elfdump

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

Command: pre/sparc-sunos5.7/sections/elfdump.sh

    #!/usr/xpg4/bin/sh
    /usr/ccs/bin/elfdump -c tmp/sparc-sunos5.7/evil_magic/att

Output: out/sparc-sunos5.7/sections/elfdump

    Section Header[1]:  sh_name: .text
        sh_addr:      0x10074         sh_flags:   [ SHF_ALLOC  SHF_EXECINSTR ]
        sh_size:      0x24            sh_type:    [ SHT_PROGBITS ]
        sh_offset:    0x74            sh_entsize: 0
        sh_link:      0               sh_info:    0
        sh_addralign: 0x1

    Section Header[2]:  sh_name: .data
        sh_addr:      0x20098         sh_flags:   [ SHF_WRITE  SHF_ALLOC ]
        sh_size:      0               sh_type:    [ SHT_PROGBITS ]
        sh_offset:    0x98            sh_entsize: 0
        sh_link:      0               sh_info:    0
        sh_addralign: 0x1

    Section Header[3]:  sh_name: .sbss
        sh_addr:      0x20098         sh_flags:   [ SHF_WRITE ]
        sh_size:      0               sh_type:    [ SHT_PROGBITS ]
        sh_offset:    0x98            sh_entsize: 0
        sh_link:      0               sh_info:    0
        sh_addralign: 0x1

    Section Header[4]:  sh_name: .bss
        sh_addr:      0x20098         sh_flags:   [ SHF_WRITE  SHF_ALLOC ]
        sh_size:      0               sh_type:    [ SHT_NOBITS ]
        sh_offset:    0x98            sh_entsize: 0
        sh_link:      0               sh_info:    0
        sh_addralign: 0x1

    Section Header[5]:  sh_name: .shstrtab
        sh_addr:      0               sh_flags:   0
        sh_size:      0x32            sh_type:    [ SHT_STRTAB ]
        sh_offset:    0x98            sh_entsize: 0
        sh_link:      0               sh_info:    0
        sh_addralign: 0x1

## 6.4. Observations

The start of section `.text`, `0x10074`, 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 /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/sparc-sunos5.7/sections/sh/readelf.sh

    #!/usr/xpg4/bin/sh
    /usr/xpg4/bin/ls -Ll /usr/xpg4/bin/sh
    /usr/local/bin/readelf -S /usr/xpg4/bin/sh

Output: out/sparc-sunos5.7/sections/sh/readelf

    -r-xr-xr-x   2 bin      bin       193804 Nov 28 00:03 /usr/xpg4/bin/sh
    There are 25 section headers, starting at offset 0x2f124:

    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        000100d4 0000d4 000011 00   A  0   0  1
      [ 2] .hash             HASH            000100e8 0000e8 0014c0 04   A  3   0  4
      [ 3] .dynsym           DYNSYM          000115a8 0015a8 002a10 10   A  4  19  4
      [ 4] .dynstr           STRTAB          00013fb8 003fb8 002fc8 00   A  0   0  1
      [ 5] .SUNW_version     VERNEED         00016f80 006f80 000050 00   A  4   2  4
      [ 6] .rela.ex_shared   RELA            00016fd0 006fd0 000018 0c   A  3  13  4
      [ 7] .rela.data        RELA            00016fe8 006fe8 000024 0c   A  3  14  4
      [ 8] .rela.bss         RELA            0001700c 00700c 00000c 0c   A  3  16  4
      [ 9] .rela.plt         RELA            00017018 007018 0005ac 0c   A  3  11  4
      [10] .text             PROGBITS        000175c4 0075c4 02504c 00  AX  0   0  4
      [11] .init             PROGBITS        0003c610 02c610 000038 00  AX  0   0  4
      [12] .fini             PROGBITS        0003c648 02c648 000038 00  AX  0   0  4
      [13] .exception_ranges PROGBITS        0003c680 02c680 000004 00   A  0   0  4
      [14] .rodata           PROGBITS        0003c684 02c684 00157b 00   A  0   0  4
      [15] .rodata1          PROGBITS        0003dc00 02dc00 000906 00   A  0   0  4
      [16] .got              PROGBITS        0004e508 02e508 000004 04  WA  0   0  4
      [17] .plt              PROGBITS        0004e50c 02e50c 0005e0 0c WAX  0   0  4
      [18] .dynamic          DYNAMIC         0004eaec 02eaec 0000b8 08  WA  4   0  4
      [19] .ex_shared        PROGBITS        0004eba4 02eba4 000020 00  WA  0   0  4
      [20] .data             PROGBITS        0004ebc8 02ebc8 000310 00  WA  0   0  8
      [21] .data1            PROGBITS        0004eed8 02eed8 000148 00  WA  0   0  4
      [22] .bss              NOBITS          0004f020 02f020 001513 00  WA  0   0  8
      [23] .comment          PROGBITS        00000000 02f020 000030 00      0   0  1
      [24] .shstrtab         STRTAB          00000000 02f050 0000d4 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 =`

> `0x2f124 + 0x25 * 0x28 =`

> `192804 + 37 * 40 = 0x2f6ec = 194284`

`ls` reported a file size of 193804 bytes.

LSB [1] has a good overview of section names. [2] Anyway, a detailed look on section `.text` shows that its start address (0x175c4) 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