3

In the way to understanding binaries (Virtual memory layout, execution...etc), I've written a C code that declares a global string which contains bytes of an executable code, then i overwrote the return address from the main() function to that executable code using a simple trick by declaring a pointer (PTR) in main() which is a local area of memory reserved on the stack 2 WORDS far away from the return address from the main(), so all i do is assigning the address of the return address to that pointer (PTR=(int*)&PTR+2) and then overwrite the content of that address with the address of the executable code (the static string).

Now the dilemma is that, whenever i compile and i execute, i receive a segmentation fault. The executable code does no memory input/output (its just a bunch of NOPs).

Using GDB i made sure that the process works perfectly: the return address is changed to be the string's address but the return never happens.

All i know is that the executable code is mapped to pages in virtual memory thar are marked RW (.data & .bss segments) so maybe there's no way to do such a code execution unless code is injected in an executable area of memory (Pages that are marked RE). That's my theory about the subject, i invite you to give more details.

char code[]="\x90\x90\x90\x90\x90\x90\x90\x90"; //a static string contains executable code

int main()
{
int *return_address; //Pointer to the return address - uninitialized
return_address = (int *)&return_address + 2; //Initializing the return address - according to stack layout
(*return_address) = (int)code; //Overwriting the return address with the code's address
}
Karim Manaouil
  • 1,177
  • 10
  • 24
  • You may want to call mprotect sycall with PROT_EXEC flag added... There is no x permission on data page on many architectures (x86 too), check the memory maps in linux by reading /proc/$PID/maps file while the application is running (stopped in gdb), where $PID is the pid of target process. You will see data/bss segment loaded with rw- permission. – osgx Jun 30 '16 at 03:50
  • @osgx It is exactly the same thing i guessed, does older linux kernels (like before 2007) allow this kind of execution ? – Karim Manaouil Jun 30 '16 at 03:57
  • did you? You may check maps file on older kernel. There is wiki page on technology: https://en.wikipedia.org/wiki/Executable_space_protection and "NX bit" / "XD bit" technology may be needed in CPU and kernel to ... add 'Executable' bit to page-level translations of hardware (OS may have 3bit rwx permissions; but hardware had no x bit). PAE should be turned on in 32-bit x86 mode too. (detailed information is here https://en.wikipedia.org/wiki/NX_bit) – osgx Jun 30 '16 at 04:00
  • afr0ck, and what is your real question? Do you want any more detailed links? – osgx Jun 30 '16 at 04:15
  • Linux kernels > 2.3 supports full PAE with XD bit so i really need a very old Linux kernel to make such an attempt. Btw thanks for helping. @osgx – Karim Manaouil Jun 30 '16 at 04:19
  • The question was : can i execute the program above without having an segmentation fault ?...and it turned out to be impossible due to memory protection ! – Karim Manaouil Jun 30 '16 at 04:21
  • afr0ck, there are tools to change linux settings for one application, for example `execstack` tool (http://linux.die.net/man/8/execstack; the stack may be switched to rwx; check 2004 article). kernels >2.3 may support PAE, but at the same time, PAE may be not enabled in kernel configuration (at build time; there was linux-generic-pae variant of kernel). – osgx Jun 30 '16 at 04:22
  • linker may change flags on sections: http://stackoverflow.com/questions/7863200/why-data-and-stack-segments-are-executable – osgx Jun 30 '16 at 04:23
  • That was literally helpful, Thanks @osgx. – Karim Manaouil Jun 30 '16 at 04:27
  • If you want to close the question as solved, you may (or may not) click "v"-shaped button left to the correct answer (accept it). Or you may want to wait for someone with better answer.. – osgx Jun 30 '16 at 04:31

1 Answers1

3

i receive a segmentation fault.

It is hardware control of data execution prevention (https://en.wikipedia.org/wiki/Executable_space_protection#Linux) - you can't just jump to data page if it has no 'x' (execute) bit set in page tables. Memory mappings with all bits are listed in /proc/$pid/maps / /proc/$pid/smaps files as 'rwx' for writable code, 'rw-' for data without execution, 'r--' for readonly data, 'r-x' for normal code.

If you want to execute data, you should call mprotect syscall with PROT_EXEC flag on the section of your data which wants to be code.

In x86 world this was fully implemented as "NX bit" / "XD bit" feature in Pentium 4 (Prescott) and newer (Core, Core2, Core i*, core m) / in Athlon 64 / Opteron and newer. If OS works in 32-bit mode, it must turn on PAE to have this bit in page table. In x86_64 mode (64-bit) there is always NX/XD bit supported.

First variants of support were added to linux around 2004: http://linuxgazette.net/107/pramode.html

In 2007 you may have outdated hardware, old kernel or 32-bit mode kernel without PAE.

Info about NX/XD bits: https://en.wikipedia.org/wiki/NX_bit

Sometimes 'rwx' mode may be prohibited, check https://en.wikipedia.org/wiki/W^X.

For pre-NX systems there were solutions based on segment registers of x86 to partially disable part of memory space from executing.

can i execute the program above without having an segmentation fault ?

You can:

  • make the data page executable by calling mprotect on it with PROT_READ|PROT_EXEC
  • make the data segment of elf file marked as executable (need to hack deeply inside ld scripts - default is in ld --verbose)
  • make all pages including .data and the heap executable (not just the stack)
    with ld or gcc -z execstack
  • move shellcode to text data of elf file
  • try to disable nx/xd bit in kernel (hard; recompilation may be needed)
  • use 32-bit OS (kernel) without PAE option enabled (build time option).
  • use older cpu without NX/XD
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
osgx
  • 90,338
  • 53
  • 357
  • 513
  • PS: someone may (but should not, according to law) use *spray* to get own code written in remote process in executable pages (https://en.wikipedia.org/wiki/JIT_spraying). Will not work on RISC and gogole NaCL (they have no variable length instruction encoding or jump to the middle of instruction) and on modern JIT with anti-spray. – osgx Jun 30 '16 at 04:14
  • ubuntus page of nx/xd: https://wiki.ubuntu.com/Security/Features#nx "The 64bit and 32bit -server and -generic-pae kernels are compiled with PAE addressing. Starting in Ubuntu 9.10, this protection is partially emulated for processors lacking NX when running on a 32bit kernel .. Starting in Ubuntu 11.04, BIOS NX settings are ignored by the kernel." And color matrix. – osgx Jun 30 '16 at 04:26
  • 1
    Turns out that using `mprotect` is quite easy, giving a zone through start address and length. The only attention point is that the start address must be page-aligned (`addr & ~4095`). Note that GDB (at least rr) freaks out when stepping inside mprotect call. – fuujuhi Feb 13 '20 at 22:59