PLanET ABhisEK
May 2006 >
SuMoTuWeThFrSa
  1 2 3 4 5 6
7 8 910111213
14151617181920
21222324252627
28293031   

Wed, 31 May 2006 19:06:00 IST

GAMES WITH LINUX MEMORY PERMISSIONS

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

So whats the meaning of this?
a) /proc/self/maps gives incorrect results?
b) I am doing something wrong?
c) Explanation is already available, just that I need to look for it?

I'll dig more into it and post some results if I find out something. In the mean time if somebody accidentaly lands up in this thing and have something to say, please drop me a mail at abhisek[dot]datta[at]gmail[dot]com

And oh, if anybody is interested in testing the kernel's memory permissions/protections then I'll suggest take a look at:

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

Thu, 25 May 2006 00:00:00 IST

BUBBLE BUBBLE

Once upon a time, not so long ago but quite some time ago, when I was doing my first year graduation, somebody asked me something about bubble sort (yes probably the most simple sorting algorithm) and I remember I could not answer. Well, now here is my little try at the question posed to me quite some time ago...



;;
;; BUBBLE SORT IN 32BIT x86 ASSEMBLY
;; SHOULD WORK OVER LINUX KERNEL

;; THIS MADNESS IS DEDICATED TO THE GRAND OCCASSION OF 2nd JUNE 2006
;; HAIL PEPSI
;; MAY YOU AND I REST IN PEACE SOMEDAY
;;
;; POSITION INDEPENDENT ASSEMBLY COMPONENT
;; YOU CAN MAKE A RELIABLE SHELLCODE OUT OF THIS
;; EVIL HAXORZ CAN USE PWNED BOX FOR DOING BUBBLE SORT
;;
BITS 32

GLOBAL _start

%define FD_STDOUT    1
%define FD_STDIN     0

%define __NR_READ    3
%define __NR_WRITE   4
%define __NR_EXIT    1

_start:
   push ebp
   mov ebp, esp

   sub esp, 4

   call helloStr
   db "Enter the number of elements to sort: ",0x00
   
helloStr:      
   pop ecx
   push ecx
   call sub_PrintStr

   call sub_ReadDword
   mov ecx, eax
   mov dword [ebp - 4], ecx

elementReaderLoop:

   call getAskString
   db "Enter number: ",0x00
   
getAskString:
   pop esi
   push ecx
   
   push esi
   call sub_PrintStr
   pop esi
   pop ecx

   push ecx
   call sub_ReadDword
   pop ecx
   
   push eax

   loop elementReaderLoop

   mov eax, dword [ebp - 4]
   push eax             ; Number of elements to sort
   int3
   call sub_BUBBLES

   int3
   call sub_Exit

   ; sub_BUBBLES(n, A[n])
   ; This procedure will sort A[n] in descending order using the bubble sort algorithm
   ; The _list_ A is modified _in_ _place_ for sorting
sub_BUBBLES:
   push ebp,
   mov ebp, esp

   call startMsg
   db "Bubble sort start..",0x0a,0x00
startMsg:
   pop ecx
   push ecx
   call sub_PrintStr

   mov ebx, [ebp+8]
   dec ebx
   xor ecx, ecx

   add ebp, 12 ; EBP now points to param array base
   
bubbleSortLoop1:
   
   mov edx, ecx
   
bubbleSortLoop2:
   pusha
   mov eax, [ebp + edx * 4]
   mov ebx, [ebp + ecx * 4]
   cmp eax, ebx
   popa
   jl swap
   jmp loop2

swap:
   push dword [ebp + edx * 4]
   push dword [ebp + ecx * 4]
   pop dword [ebp + edx * 4]
   pop dword [ebp + ecx * 4]

loop2:
   inc edx
   cmp edx, ebx
   jl bubbleSortLoop2

   inc ecx
   cmp ecx, ebx
   jl bubbleSortLoop1

   call endMsg
   db "Bubble sort ends..",0x0a,0x00
endMsg:
   pop ecx
   push ecx
   call sub_PrintStr
      
   sub ebp, 12   ; Restore EBP
      
   mov esp, ebp
   pop ebp
   ret

   ; sub_Strlen(str_ptr)
sub_Strlen:
   push ebp
   mov ebp, esp

   mov edi, [ebp+8]
   xor ecx, ecx
   xor al, al
   not ecx
   cld
   repne scasb
   not ecx
   dec ecx 
   
   mov eax, ecx
   
   mov esp, ebp
   pop ebp
   ret
   
   ; sub_PrintStr(str_ptr)
sub_PrintStr:
   push ebp
   mov ebp, esp

   mov eax, [ebp+8]
   push eax
   call sub_Strlen

   mov ebx, FD_STDOUT
   mov ecx, [ebp+8]
   mov edx, eax
   mov eax, __NR_WRITE
   int 0x80

   mov esp, ebp
   pop ebp
   ret

   ; sub_PrintRaw(data_ptr, size)
sub_PrintRaw:
   push ebp,
   mov ebp, esp

   mov ebx, FD_STDOUT
   mov ecx, [ebp+8]
   mov edx, [ebp+12]
   mov eax, __NR_WRITE
   int 0x80

   mov esp, ebp
   pop ebp
   ret

   ; sub_ReadDword() 
sub_ReadDword:
   push ebp
   mov ebp, esp

   sub esp, 16
   
   mov ebx, FD_STDIN
   lea ecx, [ebp - 16]
   mov edx, 16
   mov eax, __NR_READ
   int 0x80
   
   xor ecx, ecx
   lea esi, [ebp - 16]
   
endFinderLoop:
   cmp byte [esi + ecx], 0x0a
   je endFinderLoopEnd
   inc ecx
   jmp endFinderLoop

endFinderLoopEnd:
   mov byte [esi + ecx], 0x00

   dec ecx

   xor eax, eax
   xor edx, edx
atoiLoop:
   xor ebx, ebx
   add bl, byte [esi + edx]
   sub bl, 0x30

   push edx

   push 10
   mul dword [esp]
   add eax, ebx

   add esp, 4

   pop edx
   
   cmp edx, ecx
   je atoiLoopOut
   
   inc edx
   jmp atoiLoop

atoiLoopOut:
  
   mov esp, ebp
   pop ebp
   ret

sub_Exit:
   mov eax, __NR_EXIT
   xor ebx, ebx
   int 0x80

Thank You and bye bye World for today

posted at: 00:00 | path: / | permanent link to this entry

Wed, 24 May 2006 00:00:00 IST

Hello World

This is my first blog entry. Just want to say Hello World.

BITS 32

GLOBAL _start

_start:
   call getString
   db "Hello World",0x0a,0x00
   
getString:
   pop ecx

   mov ebx, 1
   mov edx, 12
   mov eax, 4
   int 0x80

   xor eax, eax
   xor ebx, ebx
   inc eax
   int 0x80

I never felt like blogging any thoughts/ideas/codes/evil plans to take over the world etc, but why blogging now? Well I think the inspiration for this blog is undoubtably t3min4t0r's blog . Apart from that, I really think I should keep aside other stuff and workout some of my ideas seriously now.

Bye Bye World for now.. I'll be back

posted at: 00:00 | path: / | permanent link to this entry

Made with PyBlosxom