Dailydave mailing list archives

Re: re: PaX PoC-exploit.


From: Joel Eriksson <je-dailydave () bitnux com>
Date: Fri, 7 May 2004 04:21:14 +0200

On Thu, May 06, 2004 at 01:42:32PM -0400, Sinan Eren wrote:

i am happy that Joel came up with that unnecessary and much pointless poc  
code, here you GO! we end up learning something of this novel and smart:

Ouch, that hurt. :) It wasn't meant to be revolutionary though, just a PoC
implementation of something that has been known but ignored for years. Btw,
everyone already knows you have godlike skills, noir. You don't have to put
down us lesser beings to prove it. :)

"""
pageexec () freemail hu wrote:

as i said, only for the trivial case (/lib/ld-linux.so.2 /mnt/nonexec/app),
you can still construct a special ELF without executable PT_LOAD segments
that would overlap the stack and do a ret2libc to mprotect then execute
itself - that was the PoC i was referring to (and that's what won't work
under PaX).
"""

this is a real cool technique!

Indeed. So I spent some time discussing it with pipacs (the PaX-developer
that replied to my PaX-PoC mail) and decided to implement it myself.

First I made a statically compiled executable that simply did "Hello World".

Then I made another program that:

1. Read the elf header of the statically compiled executable
2. Read the program headers
3. Removed the executable-flag from the PT_LOAD-segments
4. Wrote the altered program header table to the end of the file
5. Appended a new PT_LOAD-segment with:
      p_*addr = 0xbfff0000
      p_*sz = 0xffff
      p_align = 0x1000 (runtime-linker will complain if this is less than a page)
      p_offset = file offset to filepos after this segment, rounded up to page size
6. Wrote the payload to perform a return-into-mprotect() and do:
      mprotect(0x8048000, <size-of-textsegment>, PF_R|PF_W)
   and then return into the original entry-point of the program
7. Updated the elf header with the new program header offset and number (phoff/phnum)

I got the address to mprotect() by searching the output of
"objdump -d /lib/ld-linux.so.2" for movl $0x7d,%eax followed
by an int $0x80 (0x7d = the syscall number of mprotect()).
The runtime-linker is statically compiled of course, so I
could not literally return into mprotect() in libc.

I did get it to return where I wanted it to, but it crashed
for some unknown reason. :P I returned into a piece of code
that looked like this:

    8b 54 24 10             mov    0x10(%esp,1),%edx
    8b 4c 24 0c             mov    0xc(%esp,1),%ecx
    8b 5c 24 08             mov    0x8(%esp,1),%ebx
    b8 7d 00 00 00          mov    $0x7d,%eax
    cd 80                   int    $0x80

It crashed on the first of those instructions. According to gdb the
stack pointer pointed into valid data so I actually have no idea why
it caused a crash.

However.. Since readable pages are executable on x86 (when PaX or
similar patches does not work around it) I don't really have to
mprotect() the pages. So, I modified my PoC to simply remove the
executable-flag (PF_X) from all program headers (including PT_PHDR,
why is that executable at all btw, it's just a string?).

The segments are mmap()'ed without PROT_EXEC, but since it's x86 it
doesn't matter. Nice and simple. I have verified that this technique
works in practice for bypassing noexec-mounts with at least kernel 2.4.26.

Summary. When doing this:

   /lib/ld-linux.so.2 /path/to/file/on/noexec/fs

The linux-kernel disallows the mmap() of the executable textsegment:

   mmap2(0x8048000, 16384, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = -1 EPERM (Operation not permitted)

But when trying it after doing nothing but removing the PF_X-flag from all segments:

   mmap2(0x8048000, 16384, PROT_READ, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x8048000

   (The program executes normally after this despite the missing PROT_EXEC-flag)

The best way to deal with this would probably be to patch ld.so so it enforces
the executable-bit by itself.

Hmm, can't believe I just spent that much time on bypassing noexec. :P

thanks,
-sinan

-- 
Best Regards,
   Joel Eriksson
-------------------------------------------------
Cellphone: +46-70 228 64 16 Home: +46-26-10 23 37
Security Research & Systems Development at Bitnux
PGP Key Server pgp.mit.edu, PGP Key ID 0x529FDBD1
A615 A1E1 3CA2 D7C2 CFEA 47B4 7EF7 E6B2 529F DBD1
-------------------------------------------------
_______________________________________________
Dailydave mailing list
Dailydave () lists immunitysec com
http://www.immunitysec.com/mailman/listinfo/dailydave


Current thread: