Linux process execution and the useless ELF header fields

When we are in userland calling execve(), the process uses a software-interrupt to call the syscall. You raise a software interrupt via the INT instruction (x86 Arch), then the CPU consults another table: the IDT (Interrupt Descriptor Table) to know which routines it needs to call.

The only operand taken by the INT instruction is an index in this table. That means when a 'int 80h' is executed, the CPU consults the IDT and executes the function stored at the index 0x80.

In the Linux word, the syscalls handler is stored at the index 0x80. Then the handler look at the RAX content to know which syscall it'll call. To do that, the syscalls handler uses the syscalls table ; and RAX is an index in this table. The following diagram shows what I just said:

After all this operations, the function execve is called. Now, several steps are necessary before execution.

Prepare binprm credentials

Initialization binprm memory

Prepare binprm

Search which function calls for load/parse binary

Parse ELF header

Parse Program header

Setup MM & VMA

Start thread

Free binprm

The main structure which describes the process is 'linux_binprm', it's this structure which contains all information about the process memory. The interesting fields of the structure are described below.

v3.7.4/include/linux/binfmts.h14structlinux_binprm{..16#ifdefCONFIG_MMU17structvm_area_struct*vma;18unsignedlongvma_pages;19#else..23structmm_struct*mm;..35structfile*file;36structcred*cred;/* new credentials */39intargc,envc;40constchar*filename;/* Name of binary as seen by procps */41constchar*interp;/*Nameofthebinaryreallyexecuted.Most42ofthetimesameasfilename,butcouldbe43..48};

To initialize the cred structure, the kernel calls the prepare_exec_creds function, it creates a new creds structure with the creds of the calling process.

Before execution, the Kernel needs to load and to parse the binary. The function load_elf_binary is called, this function checks if the ELF header is valid, and it also sets several pointers: code, brk and stack. If you want more information about ASLR, you can read this post. The VMAs are also set, the following diagram represents the design of Process Memory.

When the binprm struct has been fully filled the kernel can create a new thread and executes it.

It's quite fun because when the kernel loads the ELF binary, it doesn't use the ElfX_Shdr, it only needs the ElfX_Phdr to set up the VMAs. According to this, we can say that the following ElfX_Ehdr's fields are kinda useless: e_shoff, e_shentsize, e_shnum, e_shstrndx.

Now we can build a very simple antidebug trick if you delete these fields. Check that: