Getting the big picture with readelf

Linux executables are in the Executable and Linkable Format (ELF). An ELF file is an object file, which can be viewed in two different ways, depending on what you are trying to do with it. Figure 10.9 shows the two views and different parts of the file that are relevant to each view.

FIGURE 10.9

The two views of an ELF file.

As shown in Figure 10.9, all ELF files have a header. When the file is being executed, the Program Header Table (PHT) that follows the header is read. The PHT describes various segments (large chunks) in the file. In the linking view the PHT is ignored and the Section Header Table (SHT) at the end of the file is read. The SHT describes various sections (which are subparts of segments) in the file.

The readelf utility parses different parts of an ELF file. Thanks to this handy program, there is little need to dig into the details of the ELF structures. The command readelf –file-header <file> will display the header information. The results of running this command against xingyi_bindshell are shown in Figure 10.10. From the figure, we see this is a 64-bit executable with nine program headers and thirty section headers. All ELF files begin with the “magic number” 0x7F, followed by the string “ELF”, or just 0x7F 0x45 0x4C 0x46 in hexadecimal.

FIGURE 10.10

The ELF header information for xingyi_bindshell.

The readelf –section-headers <file> command is used to display section information. The output from running readelf –section-headers -W xingyi_bindshell is shown in Figure 10.11. The -W option specifies wide format (not restricted to 80 characters of width). The sections are described in Table 10.2. The sections from this file are fairly typical.

FIGURE 10.11

Sections from the xingyi_bindshell file.

Table 10.2. Sections from xingyi_bindshell.

Name Description
Null
.interp Dynamic linker name
.note.ABI-tag Note containing “GNU” followed by architecture information
.note.gnu.build-id Unique ID that is same for debug and stripped programs (displayed by file)
.gnu.hash Describes a hash table (don’t worry if you don’t know what this is)
.dynsym Symbol table for dynamic linking
.dynstr Strings that are required for dynamic linking
.gnu.version Symbol Version Table that corresponds to .dynsym
.gnu.version_r Required symbol version definitions
.rela.dyn Relocation information for .dynamic
.rela.plt Relocation information for .plt
.init Initialization code for this program
.plt Procedure Linkage Table
.text The actual executable code (machine code)
.fini Termination code for this program
.rodata Read-only data
.eh_frame_hdr Exception handling C++ code for accessing .eh_frame
.eh_frame Exception handling (exceptions are used for error processing)
.init_array List of initialization code to call on startup
.fini_array List of termination code to call on termination
.jcr Information to register compiled Java classes
.dynamic Dynamic linking information
.got Global Offset Table (used for address resolution during relocation)
.got.plt Global Offset Table (used for address resolution during relocation)
.data Initialized data
.bss Unitialized data
.comment Comment (normally for version control)
.shstrtab Section names (section header string table)
.symtab Symbol Table
.strtab Symbol Table entry names

Do not be overly concerned if you don’t understand all the of the sections described in Table 10.2. I would posit that the majority of professional programmers do not know about all of these either. The most import ones for our purposes are .text, .data, and .bss, which contain program code, initialized data, and uninitialized data, respectively. The fact that our file has all these sections suggests that the program was written in C, or similar language, and compiled with GCC (the GNU Compiler Collection). In theory, this should make it easier to reverse engineer than handcrafted Assembly code.

The command readelf –program-headers <file> is used to parse the

Program Header Table (PHT). The results of running this command on xingyi_bindshell are shown in Figure 10.12. As can be seen from the figure, most segments consist of a list of sections. Notable exceptions to this are segments 00 and 07 which contain the Program Header Table and stack, respectively. The description of each of these segments can be found in Table 10.3. The PHT also specifies where each segment should be loaded and what byte-alignment it requires.

FIGURE 10.12

Program Header Table for xingyi_bindshell.

Table 10.3. Segments from xingyi_bindshell.

Number and Type Description
00 – PHDR Program Header Table
01 – INTERP Dynamic linker to use (/lib64/ld-linux-x86-64.so.2)
02 – LOAD Portion of file to load into memory (first one)
03 – LOAD Portion of file to load into memory (second one)
04 – DYNAMIC Dynamic linking information
05 – NOTE Extra information
06 - GNU_EH_FRAME Exception handling information
07 – GNU_STACK The program stack
08 – GNU_RELRO Memory that should be read-only after relocation is done

If a file has not been stripped, readelf can be used to list symbols. Partial output from running readelf –symbols -W xingyi_bindshell is shown in Figure

10.13. Notice that this output is more verbose than that produced by nm. It is also a bit more orderly.

FIGURE 10.13

Partial output from running readelf –symbols against xingyi_bindshell.

Each of the sections may be displayed using the command readelf –hex-dump= <file>. This can help you get some insight into the file without having to decipher the different metadata structures yourself. Running this command for a few of the sections in xingyi_bindshell is shown in Figure 10.14. From the figure,we can see the program was compiled with GCC version 4.8.2-19 for Ubuntu, should be loaded with /lib64/ld-linux-x86-64.so.2, and has the SHA Build ID of 12c43054c53c2e67b668eb566ed7cdb747d9dfda. It is probably best to avoid running this command on sections containing code as these will not be displayed in a meaningful manner. In the next section, we will cover a better tool for examining executable code.

FIGURE 10.14

Dumping a few sections from xingyi_bindshell with readelf –hex-dump.

results matching ""

    No results matching ""