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/i386-redhat8.0-linux/sections/objdump.sh
#!/bin/bash
cd tmp/i386-redhat8.0-linux/evil_magic
/bin/ls -Ll intel
/usr/bin/objdump -h intel |
Output: out/i386-redhat8.0-linux/sections/objdump
-rwxrwxr-x 1 alba alba 416 Feb 15 23:48 intel
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 00000000 08049098 08049098 00000097 2**0
CONTENTS
2 .comment 0000001f 00000000 00000000 00000097 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/i386-redhat8.0-linux/sections/readelf.sh
#!/bin/bash
cd tmp/i386-redhat8.0-linux/evil_magic
/bin/ls -Ll intel
/usr/bin/readelf -S intel |
Output: out/i386-redhat8.0-linux/sections/readelf
-rwxrwxr-x 1 alba alba 416 Feb 15 23:48 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 08049098 000097 000000 00 W 0 0 1
[ 3] .comment PROGBITS 00000000 000097 00001f 00 0 0 1
[ 4] .shstrtab STRTAB 00000000 0000b6 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.
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.
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).
[1] | |
[2] | http://www.linuxbase.org/spec/gLSB/gLSB/specialsections.html |