INSIGHTS | November 27, 2013

A Short Tale About executable_stack in elf_read_implies_exec() in the Linux Kernel

This is a short and basic analysis I did when I was uncertain about code execution in the data memory segment. Later on, I describe what’s happening in the kernel side as well as what seems to be a small logic bug.
I’m not a kernel hacker/developer/ninja; I’m just a Linux user trying to figure out the reason of this behavior by looking in key places such as the ELF loader and other related functions. So, if you see any mistakes or you realize that I approached this in a wrong way, please let me know, I’d really appreciate that.
This article also could be useful for anyone starting in shellcoding since they might think their code is wrong when, in reality, there are other things around to take care of in order to test the functionality of their shellcodes or any other kind of code.
USER-LAND: Why is it possible to execute code in the data segment if it doesn’t have the PF_EXEC enabled?
A couple of weeks ago I was reading an article (in Spanish) about shellcodes creation in Linux x64. For demonstration purposes I’ll use this 64-bit execve(“/bin/sh”) shellcode: 

#include <unistd.h>

char shellcode[] =
“x48x31xd2x48x31xf6x48xbf”
“x2fx62x69x6ex2fx73x68x11”
“x48xc1xe7x08x48xc1xefx08”
“x57x48x89xe7x48xb8x3bx11”
“x11x11x11x11x11x11x48xc1”
“xe0x38x48xc1xe8x38x0fx05”;

int main(int argc, char ** argv) {
void (*fp)();
fp = (void(*)())shellcode;
(void)(*fp)();

return 0;
}

The author suggests the following for the proper execution of the shellcodes:
We compile and with the execstack utility we specify that the stack region used in the binary will be executable…”.

Immediately, I thought it was wrong because of the code to be executed would be placed in the ‘shellcode’ symbol in the .data section within the ELF file, which, in turn, would be in the data memory segment, not in the stack segment at runtime. For some reason, when trying to execute it without enabling the executable stack bit, it failed, and the opposite when it was enabled:

 

According to the execstack’s man-page:

“… ELF binaries and shared libraries now can be marked as requiring executable stack or not requiring it… This marking is done through the p_flags field in the PT_GNU_STACK program header entry… The marking is done automatically by recent GCC versions”.
It only modifies one bit adding the PF_EXEC flag to the PT_GNU_STACK program header. It also can be done by modifying the binary with an ELF editor such as HTEditor or at linking time by passing the argument ‘-z execstack’ to gcc. 
The change can be seen simply observing the flags RWE (Read, Write, Execution) using the readelf utility. In our case, only the ‘E’ flag was added to the stack memory segment:

 
The first loadable segment in both binaries, with the ‘E’ flag enabled, is where the code itself resides (the .text section) and the second one is where all our data resides. It’s also possible to map which bytes from each section correspond to which memory segments (remember, at runtime, the sections are not taken into account, only the program headers) using ‘readelf -l shellcode’.

So far, everything makes sense to me, but, wait a minute, the shellcode, or any other variable declared outside main(), is not supposed to be in the stack right? Instead, it should be placed in the section where the initialized data resides (as far as I know it’s normally in .data or .rodata). Let’s see where exactly it is by showing the symbol table and the corresponding section of each symbol (if it applies):

It’s pretty clear that our shellcode will be located at the memory address 0x00600840 in runtime and that the bytes reside in the .data section. The same result for the other binary, ‘shellcode_execstack’.

By default, the data memory segment doesn’t have the PF_EXEC flag enabled in its program header, that’s why it’s not possible to jump and execute code in that segment at runtime (Segmentation Fault), but: when the stack is executable, why is it also possible to execute code in the data segment if it doesn’t have that flag enabled? 

 
Is it a normal behavior or it’s a bug in the dynamic linker or kernel that doesn’t take into account that flag when loading ELFs? So, to take the dynamic linker out of the game, my fellow Ilja van Sprundel gave me the idea to compile with -static to create a standalone executable. A static binary doesn’t pass through the dynamic linker, instead, it’s loaded directly by the kernel (as far as I know). The same result was obtained with this one, so this result pointed directly to the kernel.

I tested this in a 2.6 kernel (x86_64) and in a 3.2 kernel (i686), and I got the same behavior in both.
KERNEL-LAND: Is that a bug in elf_read_implies_exec()?

Now, for the interesting part, what is really happening in the kernel side? I went straight to load_elf_binary()in linux-2.6.32.61/fs/binfmt_elf.c and found that the program header table is parsed to find the stack segment so as to set the executable_stack variable correctly:

     int executable_stack = EXSTACK_DEFAULT;

elf_ppnt = elf_phdata;
for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++)
if (elf_ppnt->p_type == PT_GNU_STACK) {
if (elf_ppnt->p_flags & PF_X)
executable_stack = EXSTACK_ENABLE_X;

else
executable_stack = EXSTACK_DISABLE_X;
break;
}

Keep in mind that only those three constants about executable stack are defined in the kernel (linux-2.6.32.61/include/linux/binfmts.h):

/* Stack area protections */
#define EXSTACK_DEFAULT    0  /* Whatever the arch defaults to */
#define EXSTACK_DISABLE_X  1  /* Disable executable stacks */
#define EXSTACK_ENABLE_X   2  /* Enable executable stacks */

Later on, the process’ personality is updated as follows:

     /* Do this immediately, since STACK_TOP as used in setup_arg_pages may depend on the personality.  */
SET_PERSONALITY(loc->elf_ex);
     if (elf_read_implies_exec(loc->elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC;

if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
current->flags |= PF_RANDOMIZE;

elf_read_implies_exec() is a macro in linux-2.6.32.61/arch/x86/include/asm/elf.h:

/*
* An executable for which elf_read_implies_exec() returns TRUE 

 * will have the READ_IMPLIES_EXEC personality flag set automatically.
*/
#define elf_read_implies_exec(ex, executable_stack)
(executable_stack != EXSTACK_DISABLE_X)

In our case, having an ELF binary with the PF_EXEC flag enabled in the PT_GNU_STACK program header, that macro will return TRUE since EXSTACK_ENABLE_X != EXSTACK_DISABLE_X, thus, our process’ personality will have READ_IMPLIES_EXEC flag. This constant, READ_IMPLIES_EXEC, is checked in some memory related functions such as in mmap.c, mprotect.c and nommu.c (all in linux-2.6.32.61/mm/). For instance, when creating the VMAs (Virtual Memory Areas) by the do_mmap_pgoff() function in mmap.c, it verifies the personality so it can add the PROT_EXEC (execution allowed) to the memory segments [1]:

     /*
* Does the application expect PROT_READ to imply PROT_EXEC?
*
* (the exception is when the underlying filesystem is noexec
*  mounted, in which case we dont add PROT_EXEC.)
*/
if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
if (!(file && (file->f_path.mnt->mnt_flags & MNT_NOEXEC)))
prot |= PROT_EXEC;

And basically, that’s the reason of why code in the data segment can be executed when the stack is executable.

On the other hand, I had an idea: to delete the PT_GNU_STACK program header by changing its corresponding program header type to any other random value. Doing that, executable_stack would remain EXSTACK_DEFAULT when compared in elf_read_implies_exec(), which would return TRUE, right? Let’s see:


The program header type was modified from 0x6474e551 (PT_GNU_STACK) to 0xfee1dead, and note that the second LOAD (data segment, where our code to be executed is) doesn’t have the ‘E’xecutable flag enabled: 

 

The code was executed even when the execution flag is not enabled in the program header that holds it. I think it’s a logic bug in elf_read_implies_exec() because one can simply delete the PT_GNU_STACK header as to set executable_stack = EXSTACK_DEFAULT, making elf_read_implies_exec() to return TRUE. Instead comparing against EXSTACK_DISABLE_X, it should return TRUE only if executable_stack is EXSTACK_ENABLE_X:

#define elf_read_implies_exec(ex, executable_stack)
(executable_stack == EXSTACK_ENABLE_X)

Anyway, perhaps that’s the normal behavior of the Linux kernel for some compatibility issues or something else, but isn’t it weird that making the stack executable or deleting the PT_GNU_STACK header all the memory segments are loaded with execution permissions even when the PF_EXEC flag is not set?

What do you think?
Side notes:
       Kernel developers pass loc->elf_ex and never use it in:
#define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X)

       Two constants are defined but never used in the whole kernel code:
#define INTERPRETER_NONE 0
#define INTERPRETER_ELF  2
Finally, I’d like to thank my collegues Ilja van Sprundel and Diego Bauche Madero for giving me some ideas.
Thanks for reading.
References:
[1] “Understanding the Linux Virtual Memory Manager”. Mel Gorman.
Chapter 4 – Process Address Space.

 

INSIGHTS | December 18, 2012

Striking Back GDB and IDA debuggers through malformed ELF executables

Day by day the endless fight between the bad guys and good guys mostly depends on how fast a countermeasure or anti-reversing protection can be broken. These anti-reversing mechanisms can be used by attackers in a number of ways: to create malware, to be used in precompiled zero-day exploits in the black market, to hinder forensic analysis, and so on. But they can also be used by software companies or developers that want to protect the internal logic of their software products (copyright).

The other day I was thinking: why run and hide (implementing anti-reversing techniques such as the aforementioned) instead of standing up straight and give the debugger a punch in the face (crashing the debugging application). In the next paragraphs I’ll explain briefly how I could implement this anti-reversing technique on ELF binaries using a counterattack approach.

ELF executables are the equivalent to the .exe files in Windows systems, but in UNIX-based systems (such as Linux and *BSD). As an executable file format, there are many documented reversing [1] and anti-reversing techniques on ELF binaries, such as the use of the ptrace() syscall for dynamic anti-debugging [2]:
 
void anti_debug(void) __attribute__ ((constructor));
 
void anti_debug(void)
{
     if(ptrace(PTRACE_TRACEME, 0, 0, 0) == -1){
           printf(“Debugging not allowed!n”);
           exit(0xdead);
     }
}
 
Trying to debug with GNU debugger (the most famous and commonly used debugger in UNIX-based systems) an ELF executable that contains the above code will result in:

However, as can be seen, even with the anti-debugging technique at runtime, the ELF file was completely loaded and parsed by the debugger.

The ELF files contain different data structures, such as section headers, program headers, debugging information, and so on. So the Linux ELF loader and other third party applications know how to build their layout in memory and execute/analyze them. However, these third party applications, such as debuggers, sometimes *TRUST* on the metadata of the supplied ELF file to be analyzed, and here is where the fun begins.
I found one bug in GNU gdb 7.5.1 and another one in IDA Pro 6.3 (the latest versions when this paper was written), using Frixyon fuzzer (my ELF file format fuzzer still in development). To explain these little bugs that crash the debuggers, we’ll use the following code (evil.c):

 

#include <stdio.h>
 
int main()
{
        printf(“It could be a malicious program }:)n”);
 
        return 0;
}

Crashing GNU gdb 7.5.1
Compiling this with gcc using the –ggdb flag, the resulting ELF file will have section headers with debugging-related information:
 
 

 

After a bit of analysis, I found a bug in the DWARF [3] (a debugging file format used by many compilers and debuggers to support source-level debugging) processor that fails when parsing the data within the .debug_line section. This prevents gdb from loading an ELF executable for debugging due to a NULL pointer dereference. Evidently it could be used to patch malicious executables (such as rootkits, zero-day exploits, and malware) that wouldn’t be able to be analyzed by gdb.

In gdb-7.5.1/gdb/dwarf2read.c is the following data structure:

 

 
struct line_header
{
  unsigned int num_include_dirs, include_dirs_size;
  char **include_dirs;
  struct file_entry
  {
    char *name;
    unsigned int dir_index;
    unsigned int mod_time;
    unsigned int length;
  } *file_names;
}
 
The problem exists when trying to open a malformed ELF that contains a file_entry.dir_index > 0 and char **include_dirs pointing to NULL. To identify the bug, I did something called inception debugging: to debug gdb with gdb:
 
 
The root cause of the problem is that there’s no validation to verify if include_dirs is different from NULLbefore referencing it.
To simplify this process, I’ve developed a tool to patch the ELF executable given as an argument, gdb_751_elf_shield.c:
 
 
After patching a binary with this code, it will be completely executable since the operating system ELF loader only uses the Program Headers (not the Section Headers). But, it wouldn’t be able to be loaded by gdb as shown below:

 

 

T

Timeline:
12/11/2012      The bug was found on GNU gdb 7.5.
19/11/2012      The bug was reported through the official GNU gdb’s bug tracker:
http://sourceware.org/bugzilla/show_bug.cgi?id=14855
10/12/2012      Retested with the latest release (7.5.1), which still has the bug.
12/12/2012      The status on the tracker is still “NEW”.
 

C

Crashing IDA Pro 6.3
The IDA Pro ELF loader warns you when it finds invalid or malformed headers or fields, and asks if you want to continue with the disassembly process. However, there’s a specific combination of fields that makes IDA Pro enter an unrecoverable state and closes itself completely, which shouldn’t happen.
The aforementioned fields are found in the ELF headers, e_shstrndxand e_shnum, where the first one is an index of the Section Header Table with e_shnumelements. So IDA will fail if e_shstrndx > e_shnum because there is no validation to verify both values before referencing it.
The following screenshot illustrates the unrecoverable error:
 
 

I have also programmed a simple tool (ida_63_elf_shield.c) to patch the ELF executables to make them impossible for IDA Pro to load. This code only generates two random numbers and assigns the bigger one to e_shstrndx:

      srand(time(NULL)); // seed for rand()
 
      new_shnum    = (Elf32_Half) rand() % 0x1337;
      new_shstrndx = (Elf32_Half) 0;
 
      while(new_shstrndx < new_shnum)
            new_shstrndx = (Elf32_Half) rand() % 0xDEAD;
 
      header->e_shnum    = new_shnum;
      header->e_shstrndx = new_shstrndx;
 
After patching a file, IDA will open a pop-up window saying that an error has occurred and after clicking the OK button, IDA will close:

 

 
imeline:
21/11/2012      The bug was found on IDA Demo 6.3.
22/11/2012      The bug was tested on IDA Pro 6.3.120531 (32-bit).
22/11/2012      The bug was reported through the official Hex-Rays contact emails.
23/11/2012     Hex-Rays replied and agreed that the bug leads to an unrecoverable state and will be fixed in the next release.
A real life scenario
Finally, to illustrate that neither patching tool will corrupt the integrity of the ELF files at execution, I will insert a parasite code to an ELF executable using Silvio Cesare’s algorithm [4], patching the entrypoint to a “fork() + portbind(31337) + auth(Password: n33tr0u5)” payload [5], which at the end has a jump to the original entrypoint:
 

As can be seen, the original binary (hostname) works perfectly after executing the parasite code (backdoor on port 31337). Now, let’s see what happens after patching it:

 

It worked perfectly and evidently it cannot be loaded by gdb !
In conclusion, the debuggers have certain parsing tasks and are software too, therefore they are also prone to bugs and security flaws. Debugging tools shouldn’t blindly trust in the data input supplied, in this case, the metadata of an ELF executable file. Always perform bound checking before trying to access invalid memory areas that might crash our applications.
Thanks for reading.
Alejandro.
Tools
– gdb (GNU debugger) <= 7.5.1 (crash due a NULL pointer dereference)
ELF anti-debugging/reversing patcher
– IDA Pro 6.3 (crash due an internal error)
ELF anti-debugging/reversing patcher
References
[1] Reverse Engineering under Linux by Diego Bauche Madero
[2] Abusing .CTORS and .DTORS for fun ‘n profit by Itzik Kotler
[3] DWARF
[4] UNIX Viruses by Silvio Cesare
[5] ELF_data_infector.c by Alejandro Hernández