3 Things today — Pt. 12

1 thing: Compiling 64-bit GDB
2 : Analyzing how the heap could be brute-forced in this exploit.
3: Discovering that the address returned by malloc is consistent across runs, on different machines!! With different UTMPX file sizes!! AWESOME!! The stack doesn’t have to be brute-forced!!! I will over-write the LD linker thing to point to the UTMPX-Shellcode which is located in the heap offsetted by the recorded malloc return address entry and blam!! We are singing!! <3 3-2) in summary, if you have read access to the executable it can be copied and debugged to find the base malloc offset to aid in one-timing a heap-based overflow on a NX stack-based executable/OS. If the exe is not readable, but there is an executable stack, you're still in luck! And can execute directly into a giant NOP sled... Even if the exe is not readable, it can always become readable by installing an identical copy of the OS in your lab.. :) Another thing I double checked, ulab, blade72, blade60 all have the same exact copy of /usr/bin/sparcv7/w I expect the 64-bit version to be the same as well.. Solaris 10 doesn't seem to have the 32-bit W... Solaris 10 patch:

$NetBSD: patch-ob,v 1.1 2008/01/06 19:25:10 rillig Exp $

gcc4 complained:
gdbtypes.c:2961: error: invalid lvalue in increment

--- include/obstack.h.orig	2001-01-21 00:02:00.000000000 +0000
+++ include/obstack.h	2007-11-30 21:04:44.000000000 +0000
@@ -421,7 +421,7 @@ __extension__								\
 ({ struct obstack *__o = (OBSTACK);					\
    if (__o->next_free + sizeof (void *) > __o->chunk_limit)		\
      _obstack_newchunk (__o, sizeof (void *));				\
-   *((void **)__o->next_free)++ = ((void *)datum);			\
+   *((*(void ***)&(__o->next_free)))++ = ((void *)datum);		\
    (void) 0; })
 
 # define obstack_int_grow(OBSTACK,datum)				\
@@ -429,7 +429,7 @@ __extension__								\
 ({ struct obstack *__o = (OBSTACK);					\
    if (__o->next_free + sizeof (int) > __o->chunk_limit)		\
      _obstack_newchunk (__o, sizeof (int));				\
-   *((int *)__o->next_free)++ = ((int)datum);				\
+   *((*(int **)&(__o->next_free)))++ = ((int)datum);			\
    (void) 0; })
 
 # define obstack_ptr_grow_fast(h,aptr) (*((void **) (h)->next_free)++ = (void *)aptr)

1. Let’s compile GDB 5.3 (same as 32bit present on blade72) without intl errors:
export CC=”gcc -m64″
./configure –prefix=/home/bazz/tools –with-included-gettext –disable-nls
# on my Solaris 10 box:
ln -s /opt/csw/bin/gar /opt/csw/bin/ar

3: Analysis of Heap address space in 64-bit version vs. 32 bit.. and across machines…

64:

Mapped address spaces:

          Start Addr           End Addr       Size     Offset   Flags
         0x100000000        0x100003fff     0x4000          0 ----r-x
         0x100102000        0x100103fff     0x2000     0x2000 ----rwx
         0x100104000        0x10011bfff    0x18000          0 --b-rwx
  0xffffffff7ef00000 0xffffffff7ef01fff     0x2000          0 ----rwx
  0xffffffff7f000000 0xffffffff7f003fff     0x4000          0 ----r-x
  0xffffffff7f100000 0xffffffff7f101fff     0x2000          0 ----rwx
  0xffffffff7f200000 0xffffffff7f2b5fff    0xb6000          0 ----r-x
  0xffffffff7f3b6000 0xffffffff7f3c3fff     0xe000    0xb6000 ----rwx
  0xffffffff7f3c4000 0xffffffff7f3c5fff     0x2000          0 ----rwx
  0xffffffff7f500000 0xffffffff7f501fff     0x2000          0 ----rwx
  0xffffffff7f600000 0xffffffff7f62dfff    0x2e000          0 ----r-x
  0xffffffff7f72e000 0xffffffff7f731fff     0x4000    0x2e000 ----rwx
  0xffffffff7fffc000 0xffffffff7fffffff     0x4000 0xffffe000 -s--rw-

(gdb) p/x $o0
$1 = 0x100115c00
(gdb)

$o0 is malloc return pointer in heap space..

32

(gdb) p/x $o0
$4 = 0x30770
(gdb) info proc map
process 14893 flags:
PR_STOPPED Process (LWP) is stopped
PR_ISTOP Stopped on an event of interest
PR_RLC Run-on-last-close is in effect
PR_FAULTED : Incurred a traced hardware fault FLTBPT: Breakpoint trap

Mapped address spaces:

        Start Addr   End Addr       Size     Offset   Flags
           0x10000    0x13fff     0x4000          0 ----r-x
           0x22000    0x23fff     0x2000     0x2000 ----rwx
           0x24000    0x33fff    0x10000          0 --b-rwx
        0xff280000 0xff32bfff    0xac000          0 ----r-x
        0xff33c000 0xff343fff     0x8000    0xac000 ----rwx
        0xff370000 0xff371fff     0x2000          0 ----rwx
        0xff380000 0xff383fff     0x4000          0 ----r-x
        0xff390000 0xff391fff     0x2000          0 ----rwx
        0xff3b0000 0xff3dffff    0x30000          0 ----r-x
        0xff3e0000 0xff3e1fff     0x2000    0x30000 ----rwx
        0xff3e2000 0xff3e3fff     0x2000          0 ----rwx
        0xffbee000 0xffbeffff     0x2000          0 -s--rwx

(gdb)

I found that on 64 bit address, the offset returned by malloc from heap_start is 0x11C00.
Whereas on 32 bit, it was 0xC770.. No correlation there I don’t thnk..

BUT MOST IMPORTANTLY — will that offset ALWAYS be MAINTAINED???
If so, we can reliably predict where in the heap our SHELLCODE UTMPX ENTRY resides :D

I just tested on Blade72 vs. Blade71. Although they are very similar machines, they both start up the heap at the same spot!! <3 Ulab also does its heap at teh same spot.. So does blade60.. 0x30770 Of course, I am debugging these binaries without the SUID bit set.. I copied them into my home directory.. I wonder if the thing would stay the same with it set??? I also note that the Sparcv7 binary of W has it's stack space NX by default! regardless of system setting?? The 64bit malloc base address is the same on blade72 and ulab as well.. 0x100115c00 Geeze :D -- with this ability to debug the program being consistent across to the SUID execution (will be checked on LIFE).. then that means holy cow!! <3 We can have an NX heap-based execution of shellcode that is 100% reliable :D

Leave a Reply

Your email address will not be published. Required fields are marked *

*