| 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
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
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