The structure of ELF files has much in common with Portable Executable (PE) files. PE is the main executable file format for the Window 9 x and Windows NT platforms; therefore, the concepts of infection for these file formats are similar, although differently implemented.
From the most general point of view, an ELF file is made up of the ELF header , which describes the main features of the file behavior; the program header table ; and one or more segments , which contain code, initialized or uninitialized data, and other structures (see Listing 19.1). Each segment represents a continuous memory region with its own access attributes (typically, the code segment is available only for execution and data segments are available for reading and, if necessary, for writing). The term "segment" must not confuse you, because it has nothing in common with the segmented memory model. Most 32-bit UNIX implementations place all segments of an ELF file into one 4-GB "processor" segment. In the memory, all ELF segments must be aligned to the page (on the x86 platform, the page size is equal to 4 KB). However, in the ELF file segments are stored unaligned, directly adjacent to each other. The ELF header and the program header formally are not included into the first segment; however, they are conjointly loaded into the memory, and the beginning of the segment follows directly after the end of the program header and is not aligned by the page boundary.
ELF Header Program header table Segment 1 Segment 2 Section header table (optional)
The last structure of the ELF file is the section header table. For executable files this is an optional component, which is actually used only in object files. This component is also needed for debuggers , because an executable file with a damaged section header table cannot be debugged using GDB or other debuggers based on it. The operating system, however, processes such files normally.
Segments are divided into sections in a natural way. A typical code segment comprises the following sections: .init (initialization procedure), .pit (procedure linkage table), .text (main code of the program), and . finit ( finalization procedure). The attributes of these sections are described in the section header. The operating system loader doesn't know anything about the sections, ignores their attributes, and loads the entire segment. Nevertheless, to ensure the usability of an infected file under the debugger, the virus must simultaneously correct both the program header and the section header.
The general structure of the executable ELF file is shown in Listing 19.1.
The main structure of an ELF file is described in the /usr/include/elf.h file and appears as shown in Listings 19.2 to 19.4.
typedef struct { unsigned char e_ident[EI_NIDENT]; /* ELF file identifier: 7F 45 4C */ Elf32_Half e_type; /* File type */ Elf32_Half e_machine; /* Architecture */ Elf32_Word e_version; /* Version of the object file */ Elf32_Addr e_entry; /* Virtual entry point address */ Elf32_Off e_phoff; /* Program header physical offset */ Elf32_Off e_shoff; /* Section header physical offset */ Elf32_Word e_flags; /* Flags */ Elf32_Half e_ehsize; /* ELF header size in bytes */ Elf32_Half e_phentsize; /* Program header element size in bytes */ Elf32_Half e_phnum; /* Number of program header elements */ Elf32_Half e_shentsize; /* Section header element size in bytes */ Elf32_Half e_shnum; /* Number of section header elements */ Elf32_Half e_shstrndx; /* String table index in section header */ } Elf32_Ehdr;
typedef struct { Elf32_Word p_type; /* Segment type */ Elf32_Off P_offset; /* Physical offset of the file segment */ Elf32_Addr p_vaddr; /* Virtual address of the segment start */ Elf32_Addr p_paddr; /* Physical address of the segment */ Elf32_Word p_filesz; /* Physical size of the file segment */ Elf32_Word p_memsz; /* Size of the segment in memory */ Elf32_Word p_flags; /* Flags */ Elf32_Word p_align; /* Alignment repetition factor */ } Elf32_Phdr;
typedef struct { Elf32_Word sh_name; /* Section name (tbl-index) */ Elf32_Word sh_type; /* Section type */ Elf32_Word sh_flags; /* Section flags */ Elf32_Addr sh_addr; /* Virtual address of the section start */ Elf32_Off sh_offset; /* Physical offset of the file section */ Elf32_Word sh_size; /* Section size in bytes */ Elf32_Word sh_link; /* Link to another section */ Elf32_Word sh_info; /* Additional information about the section */ Elf32_Word sh_addralign; /* Section alignment factor */ Elf32_Word sh_entsize; /* Size of the nested element (if any) */ } Elf32_Shdr;
More detailed information on this topic can be found in the original ELF file specification ( http://www.x86.org/ftp/manuals/tools/elf.pdf ).