- Регистрация
- 9 Май 2015
- Сообщения
- 1,480
- Баллы
- 155
In this post, I'll explain and investigate the Executable and Linkable Format (ELF), which is the default binary format on Linux-based systems.
To make practices, I've written a simple copy.c source file and we will investigate this:
/**
* Copying a file content to another one.
*/
#include "../linux.h"
#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif
void main(int argc, char *argv[])
{
int inputFd, outputFd, openFlags;
mode_t filePerms;
ssize_t numRead;
char buf[BUF_SIZE];
if (argc != 3 || strcmp(argv[1], "--help") == 0)
usage_error("Wrong command-line usage");
/* Open input and output files */
inputFd = open(argv[1], O_RDONLY);
if (inputFd)
syscall_error();
openFlags = O_CREAT | O_WRONLY | O_TRUNC;
filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH; /* rw-rw-rw- */
outputFd = open(argv[2], openFlags, filePerms);
if (outputFd == -1)
syscall_error();
/* Transfer data until we encounter end of input or an error */
while ((numRead == read(inputFd, buf, BUF_SIZE)) > 0)
if (write(outputFd, buf, numRead) != numRead)
syscall_error();
if (numRead == -1)
syscall_error();
if (close(inputFd) == -1)
syscall_error();
if (close(outputFd) == -1)
syscall_error();
exit(EXIT_SUCCESS);
}
Compile this program like this:
gcc copy.c -o copy -O0 -g
Binary Composition
Firstly, let's look at binary composition. A binary includes many headers, sections and areas that lets the CPU to run required machine instructions. Below is the 64-bit ELF binary layout:
Every ELF file starts with an executable header, which is just a structured series of bytes telling you that it's an ELF file, what kind of ELF file it is, and where in the file to find all the other contents. It is defined in /usr/include/elf.h. You can see the executable header with readelf command:
$ readelf -h copy
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1160
Start of program headers: 64 (bytes into file)
Start of section headers: 17496 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 37
Section header string table index: 36
Inspecting Binary
To make practices, I've written a simple copy.c source file and we will investigate this:
/**
* Copying a file content to another one.
*/
#include "../linux.h"
#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif
void main(int argc, char *argv[])
{
int inputFd, outputFd, openFlags;
mode_t filePerms;
ssize_t numRead;
char buf[BUF_SIZE];
if (argc != 3 || strcmp(argv[1], "--help") == 0)
usage_error("Wrong command-line usage");
/* Open input and output files */
inputFd = open(argv[1], O_RDONLY);
if (inputFd)
syscall_error();
openFlags = O_CREAT | O_WRONLY | O_TRUNC;
filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH; /* rw-rw-rw- */
outputFd = open(argv[2], openFlags, filePerms);
if (outputFd == -1)
syscall_error();
/* Transfer data until we encounter end of input or an error */
while ((numRead == read(inputFd, buf, BUF_SIZE)) > 0)
if (write(outputFd, buf, numRead) != numRead)
syscall_error();
if (numRead == -1)
syscall_error();
if (close(inputFd) == -1)
syscall_error();
if (close(outputFd) == -1)
syscall_error();
exit(EXIT_SUCCESS);
}
Compile this program like this:
gcc copy.c -o copy -O0 -g
Binary Composition
Firstly, let's look at binary composition. A binary includes many headers, sections and areas that lets the CPU to run required machine instructions. Below is the 64-bit ELF binary layout:
Every ELF file starts with an executable header, which is just a structured series of bytes telling you that it's an ELF file, what kind of ELF file it is, and where in the file to find all the other contents. It is defined in /usr/include/elf.h. You can see the executable header with readelf command:
$ readelf -h copy
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1160
Start of program headers: 64 (bytes into file)
Start of section headers: 17496 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 37
Section header string table index: 36
Inspecting Binary
Источник: