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.
Command: pre/sparc-sunos5.9/sections/objdump.sh
#!/usr/xpg4/bin/sh
cd tmp/sparc-sunos5.9/evil_magic
/usr/xpg4/bin/ls -Ll att
/opt/sfw/bin/gobjdump -h att |
Output: out/sparc-sunos5.9/sections/objdump
-rwxr-xr-x 1 alba alba 1416 Feb 15 2003 att
att: file format elf32-sparc
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000011 00000000000100d4 00000000000100d4 000000d4 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .hash 00000044 00000000000100e8 00000000000100e8 000000e8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .dynsym 00000080 000000000001012c 000000000001012c 0000012c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynstr 000000a2 00000000000101ac 00000000000101ac 000001ac 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .text 00000024 0000000000010250 0000000000010250 00000250 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
5 .got 00000004 0000000000020274 0000000000020274 00000274 2**2
CONTENTS, ALLOC, LOAD, DATA
6 .dynamic 00000090 0000000000020278 0000000000020278 00000278 2**2
CONTENTS, ALLOC, LOAD, DATA
7 .bss 00000000 0000000000020308 0000000000020308 00000308 2**0
ALLOC
8 .comment 0000006b 0000000000000000 0000000000000000 00000308 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. And it does not help at all that the section type itself is not included in the output.
Command: pre/sparc-sunos5.9/sections/readelf.sh
#!/usr/xpg4/bin/sh
cd tmp/sparc-sunos5.9/evil_magic
/usr/xpg4/bin/ls -Ll att
/opt/sfw/bin/greadelf -S att |
Output: out/sparc-sunos5.9/sections/readelf
-rwxr-xr-x 1 alba alba 1416 Feb 15 2003 att
There are 11 section headers, starting at offset 0x3d0:
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 000044 04 A 3 0 4
[ 3] .dynsym DYNSYM 0001012c 00012c 000080 10 A 4 1 4
[ 4] .dynstr STRTAB 000101ac 0001ac 0000a2 00 AS 0 0 1
[ 5] .text PROGBITS 00010250 000250 000024 00 AX 0 0 4
[ 6] .got PROGBITS 00020274 000274 000004 04 WA 0 0 4
[ 7] .dynamic DYNAMIC 00020278 000278 000090 08 WA 4 0 4
[ 8] .bss NOBITS 00020308 000308 000000 00 WA 0 0 1
[ 9] .comment PROGBITS 00000000 000308 00006b 00 0 0 1
[10] .shstrtab STRTAB 00000000 000373 00005b 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) |
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.
elfdump also omits section SHT_NULL but at least gets the numbering right.
Command: pre/sparc-sunos5.9/sections/elfdump.sh
#!/usr/xpg4/bin/sh
cd tmp/sparc-sunos5.9/evil_magic
/usr/xpg4/bin/ls -Ll att
/usr/ccs/bin/elfdump -c att |
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 |
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.
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).
[1] | |
[2] | http://www.linuxbase.org/spec/gLSB/gLSB/specialsections.html |