An Analysis of the ELF File Format: Use NASM to generate an elf file as small as possible. Use the binary mode, the objdump mode, and the readelf mode to analyze the loading memory and running rules, and draw a conclusion. Edit a small ASM file as follows:
crq@ $ cat new18.asmglobal _start_start: ud0 ud1 ud2
It is very simple. Only ud0, ud1, and ud2 commands are used to generate invalid opcode. Compile and generate elf as follows:
crq@ $ nasm -f elf new18.asmcrq@ $ ld new18.o
In this way, a. Out is generated as an elf file, and then the irrelevant section is removed using objcopy:
crq@ $ objcopy -S -R .comment -R .bss a.out
Run:
crq@ $ ./a.outIllegal instruction
As expected, the program receives a sigill signal, which is killed by default. Then, use objdump to disassemble it:
crq@ $ objdump -d a.outa.out: file format elf32-i386Disassembly of section .text:08048080 <.text>: 8048080: 0f ff (bad) 8048082: 0f b9 ud2b 8048084: 0f 0b ud2a
The text section contains only three lines of assembly language instructions. File Size:
crq@ $ ls -l a.out-rwxr-xr-x 1 crq users 272 Nov 22 09:22 a.out
The remaining 272 bytes. Use readelf for analysis:
crq@ $ readelf -a a.outELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x8048080 Start of program headers: 52 (bytes into file) Start of section headers: 152 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 1 Size of section headers: 40 (bytes) Number of section headers: 3 Section header string table index: 2Section 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 000006 00 AX 0 0 16 [ 2] .shstrtab STRTAB 00000000 000086 000011 00 0 0 1Key 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)Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x08048000 0x08048000 0x00086 0x00086 R E 0x1000 Section to Segment mapping: Segment Sections... 00 .textThere is no dynamic segment in this file.There are no relocations in this file.There are no unwind sections in this file.No version information found in this file.
The elf header is partially normal. There are three items in section headers. The first item is null by convention. There is only one program headers. Then the binary code is printed as follows:
crq@ $ hexdump -C a.out00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|00000010 02 00 03 00 01 00 00 00 80 80 04 08 34 00 00 00 |............4...|00000020 98 00 00 00 00 00 00 00 34 00 20 00 01 00 28 00 |........4. ...(.|00000030 03 00 02 00 01 00 00 00 00 00 00 00 00 80 04 08 |................|00000040 00 80 04 08 86 00 00 00 86 00 00 00 05 00 00 00 |................|00000050 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*00000080 0f ff 0f b9 0f 0b 00 2e 73 68 73 74 72 74 61 62 |........shstrtab|00000090 00 2e 74 65 78 74 00 00 00 00 00 00 00 00 00 00 |..text..........|000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*000000c0 0b 00 00 00 01 00 00 00 06 00 00 00 80 80 04 08 |................|000000d0 80 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................|000000e0 10 00 00 00 00 00 00 00 01 00 00 00 03 00 00 00 |................|000000f0 00 00 00 00 00 00 00 00 86 00 00 00 11 00 00 00 |................|00000100 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|00000110
0x000 ~ 0x034 is the elf header; 0x034 ~ 0x054 is a program headers; 0x054 ~ 0x080 indicates zero-byte filling; 0x080 ~ 0x086 is the content of the. Text Segment; 0x086 ~ 0x098 is the content of the. shstrtab segment; 0x098 ~ 0x110 is the three section headers. The analysis is as follows:
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|00000010 02 00 03 00 01 00 00 00 80 80 04 08 34 00 00 00 |............4...|00000020 98 00 00 00 00 00 00 00 34 00 20 00 01 00 28 00 |........4. ...(.|00000030 03 00 02 00 |.... |typedef struct elf32_hdr { unsigned char e_ident[EI_NIDENT]; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; /* Entry point */ Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx;} Elf32_Ehdr;
Among them, elf32_half is 16 bits, and other types of elf32_word, elf32_addr, and elf32_off are all 32 bits. Macro ei_nident is defined as 16, that is, the elf header has 16 bytes feature bytes.
00000030 01 00 00 00 00 00 00 00 00 80 04 08 | ............|00000040 00 80 04 08 86 00 00 00 86 00 00 00 05 00 00 00 |................|00000050 00 10 00 00 |.... |typedef struct elf32_phdr{ Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_Word p_align;} Elf32_Phdr;
00000080 0f ff 0f b9 0f 0b |...... |
00000080 00 2e 73 68 73 74 72 74 61 62 | ..shstrtab|00000090 00 2e 74 65 78 74 00 00 |..text.. |
00000090 00 00 00 00 00 00 00 00 | ........|000000a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|000000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|000000c0 0b 00 00 00 01 00 00 00 06 00 00 00 80 80 04 08 |................|000000d0 80 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 |................|000000e0 10 00 00 00 00 00 00 00 |........ |000000e0 01 00 00 00 03 00 00 00 | ........|000000f0 00 00 00 00 00 00 00 00 86 00 00 00 11 00 00 00 |................|00000100 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|typedef struct { Elf32_Word sh_name; Elf32_Word sh_type; Elf32_Word sh_flags; Elf32_Addr sh_addr; Elf32_Off sh_offset; Elf32_Word sh_size; Elf32_Word sh_link; Elf32_Word sh_info; Elf32_Word sh_addralign; Elf32_Word sh_entsize;} Elf32_Shdr;
Refer to the description of the three ud commands in nasmdoc.txt as follows:
B.4.320 `UD0', `UD1', `UD2': Undefined Instruction UD0 ; 0F FF [186,UNDOC] UD1 ; 0F B9 [186,UNDOC] UD2 ; 0F 0B [186] `UDx' can be used to generate an invalid opcode exception, for testing purposes. `UD0' is specifically documented by AMD as being reserved for this purpose. `UD1' is documented by Intel as being available for this purpose. `UD2' is specifically documented by Intel as being reserved for this purpose. Intel document this as the preferred method of generating an invalid opcode exception. All these opcodes can be used to generate invalid opcode exceptions on all currently available processors.
Interestingly, note the output of the objdump:
8048080: 0f ff (bad) 8048082: 0f b9 ud2b 8048084: 0f 0b ud2a
The three valid commands in NASM have only two valid commands in GNU as, and their names are different. ud2a and ud2b are used to generate opcode exceptions.