| May 2006 | > | |||||
| Su | Mo | Tu | We | Th | Fr | Sa |
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 | |||
Today while testing my shellcode, I suddenly had a weird idea. I used to think the mainline 2.6 branch of linux kernels from kernel.org is pretty secure these days and application level exploitation over these latest linux kernels are extinct concept because of the secure by default memory permissions.
Well, lets get going in my attempt to dig deeper into linux memory management
and paging implementations.
Currently I am running Gentoo with 2.6.14 on my laptop. The memory mappings as
available from /proc looks something like this:
note: I am using the gentoo-sources kernel from portage without any hack or
external patches like GrSecurity/PaX or SELinux/ExecShield.
neo@compaq ~ $ cat /proc/self/maps 08048000-0804c000 r-xp 00000000 03:06 38646 /bin/cat 0804c000-0804d000 rw-p 00003000 03:06 38646 /bin/cat 0804d000-0806e000 rw-p 0804d000 00:00 0 [heap] b7eb8000-b7fc1000 r-xp 00000000 03:06 87733 /lib/libc-2.3.5.so b7fc1000-b7fc2000 ---p 00109000 03:06 87733 /lib/libc-2.3.5.so b7fc2000-b7fc3000 r--p 00109000 03:06 87733 /lib/libc-2.3.5.so b7fc3000-b7fc6000 rw-p 0010a000 03:06 87733 /lib/libc-2.3.5.so b7fc6000-b7fc9000 rw-p b7fc6000 00:00 0 b7fe7000-b7ffc000 r-xp 00000000 03:06 87744 /lib/ld-2.3.5.so b7ffc000-b7ffd000 r--p 00014000 03:06 87744 /lib/ld-2.3.5.so b7ffd000-b7ffe000 rw-p 00015000 03:06 87744 /lib/ld-2.3.5.so bf8e7000-bf8fc000 rw-p bf8e7000 00:00 0 [stack] ffffe000-fffff000 ---p 00000000 00:00 0 [vdso] neo@compaq ~ $
Looking at the memory mappings, its quite apparent that there doesnt exists any segment with both write ("w") _AND_ execute ("x") permission. I have been looking into such memory mappings for quite some time now, assuring my paranoid mind that I am quite secure, atleast from arbitrary code injection/execution level exploitation techniques.
Due to some reason and unable to find out the technical reasonings for some
unexpected behaviour, I started playing with it.
The following code can be used to test the default memory permissions
implemented by my kernel.
#include <stdio.h>
/*
BITS 32
GLOBAL _start
_start:
call getString
db "Hello World",0x0a,0x00
getString:
pop ecx
mov edx, 12
mov ebx, 1
mov eax, 4
int 0x80
xor eax,eax
xor ebx, ebx
inc eax
int 0x80
*/
static char code[] =
"\xe8\x0d\x00\x00\x00\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64"
"\x0a\x00\x59\xba\x0c\x00\x00\x00\xbb\x01\x00\x00\x00\xb8\x04\x00"
"\x00\x00\xcd\x80\x31\xc0\x31\xdb\x40\xcd\x80";
int main(int argc, char **argv)
{
int (*funct)();
char temp;
funct = (int (*)()) code;
printf("code is at 0x%x\n",&code);
printf("sizeof code is 0x%x bytes\n",sizeof(code));
printf("Checking read/write on code's segment\n");
temp = code[10]; /* Read works */
code[10] = 0xff; /* Write works */
code[10] = temp; /* Restore the byte */
printf("All works\n");
printf("Executing code\n\n");
(int)(*funct)();
}
To my surprise (yeah may be I was wrong) I have results like this.
neo@compaq ~/CVSROOT/ $ gcc helloworld.c neo@compaq ~/CVSROOT/ $ ./a.out code is at 0x80496c0 sizeof code is 0x2c bytes Checking read/write on code's segment All works Executing code Hello World neo@compaq ~/CVSROOT/ $
Yes code was actually rwx (Readable,Writable, Executable).
Looking into address of ``code'' (0x080496c0), it appears to be in the
.data segment which is supposed to be non-executable as per /proc/{pid}/maps.
0x080496a0->0x080496ec at 0x000006a0: .data ALLOC LOAD DATA HAS_CONTENTS
http://www.adamantix.org/paxtest/
Some links for Linux kernel security stuff
http://www.grsecurity.net http://pax.grsecurity.net http://www.nsa.gov/selinux/index.cfm http://www.redhat.com/f/pdf/rhel/WHP0006US_Execshield.pdf
posted at: 19:06 | path: / | permanent link to this entry