缓冲区溢出攻击与防范
现在存在的主要的缓冲区溢出攻击有格式化串缓冲区溢出攻击,堆栈缓冲 区(Buffer)溢出攻击和 HEAP/BSS 的缓冲区溢出。
3
3 制造缓冲区溢出
缓冲区溢出攻击与防范
3.1 格式化字符串:
这种安全漏洞源自于 printf(),sprintf 等函数的参数格式, 以最简单的 printf()为例:
7
缓冲区溢出攻击与防范
造成 mount 程序的堆栈溢出,其缓冲区被暂存区字符串内容覆盖,而返回地址
将指向 NOP 指令。
当然,这个方法我在 Ubuntu 13.10 上已经不好用了,将代码在同学装
的”Ubuntu 6.06 整洁的公鸭”上运行据说可以使用。
3.3 HEAP/BSS 溢出攻击:
HEAP: 一般来说,在操作系统中,大部分的内存区实际上是在内核一级被动态分配
<bottom>
是右边参数更早压栈的,因此 num 值可以被修改。
代码改为如下: #include <stdio.h> main() {
int num=0x61616161; printf("Before: num = %#x \n", num); printf("%.20d%n\n" ,num);
4
缓冲区溢出攻击与防范
其输出结果为:
Before: num = 0x61616161
00000000001633771873
After: num = 0x14 第二个 printf 中,分析压栈过程:
<top>
address of "%.20d%n\n"
num
-------(arg1)
address of num -------(arg2)
6
缓冲区溢出攻击与防范 如减小到 20,发现在 Linux 下能运行了 (在 VS 下编译后运行,仍然报错,我认 为 Windows 的安全性并不比 Linux 低,只是 Linux 用的人少,开发病毒所带来的 收益低而已,所以看似更安全)。
我们知道在程序运行时,内存分配是由高到低的,如下图:
这样的话,当在 Buffer 部位存的数据长度超过 Buffer 的长度时,数据就会依 次覆盖 SFP,RET 以及后面的高位内存地址。(在 VS2013 中编译的程序超过长度 的部分编译后的程序已经已经不能运行了,在 GCC 下这是可行的)。
2
1 引言
缓冲区溢出攻击与防范
缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的 容量,使得溢出的数据覆盖在合法数据上。在当前网络与分布式系统安全中, 被广泛利用的 50%以上都是缓冲区溢出,而缓冲区溢出中,最为危险的是堆栈 溢出。(操作系统所使用的缓冲区又被称为"堆栈".。在各个操作进程之间,指令 会被临时储存在"堆栈"当中,"堆栈"也会出现缓冲区溢出。)本文详细分析了缓 冲区溢出的原理,描述了利用缓冲区溢出漏洞进行系统攻击的一般过程,最后 简单讨论了几种缓冲区溢出的保护方法。
3.1 格式化字符串:.......................................................................4 3.2 堆栈缓冲区(Buffer)溢出攻击:..........................................6 3.3 HEAP/BSS 溢出攻击:..............................................................8 4 预防缓冲区溢出攻击......................................................................10 4.1 强制写正确的代码.................................................................10 4.2 使缓冲区不可执行.................................................................10 4.3 利用编译器的边界检查来实现缓冲区的保护 ...................... 10 4.4 在程序指针失效前进行完整性检查......................................11 4.5 可不可以从根本上解决缓冲区溢出攻击..............................11 5 总结 ................................................................................................. 11 6 参考资料 ......................................................................................... 12
printf("软1116 刘毅超 201192057\n"); int num=0x61616161; printf("Before: num = %#x \n", num); printf("%.20d%n\n", num, &num); printf("After: num = %#x \n", num); return 0; } 这一步我做了 N 次,全部是程序终止~~先用的 Codeblocks,发现 num 根 本没有出现变化,之后用 VS,程序直接崩溃。。。于是装了 Linux 的虚拟 机。。。同样支持 C99,竟然%n 在 linux 下才能用。。。 在我们的期待中看到了如下现象:
/* 注意,我们没有压num的地址入栈 */ printf("After: num = %#x \n", num); } 这样,我看到查的课件上解释说会出现段错误,因为在第二个 printf 函
数上由于是从右到左匹配,所以与%n 相匹配的便是 num 存的数的作为地址。
而由于在 num 中存放的数太大,超过了访问位置,这个位置是访问不到的,
#include <string.h> void func1(char * input){
char buffer[16]; strcpy(buffer, input); } void main(){ char longstring[256]; int i; for( i = 0; i < 255; i++) longstring [i] = 'B'; func1(longstring); } 这段程序是无法运行的,是段错误,但是当我将新开数组的长度减小时,比
因此,一个缓冲区溢出程序使用这个溢出的数据将精心设计的汇编语言代码 放到机器的内存里,通常是产生 root 权限的地方。最常见的手段是通过制造缓 冲区溢出使程序运行一个用户 shell,再通过 shell 执行其他命令。如果该程序属 于 root 且有 suid 权限的话,攻击者就获得了一个有 root 权限的 shell,便可以对 系统进行任意操作了。
缓冲区溢出攻击与防范
目录
1 引言...................................................................................................3 2 基本原理分析 ...................................................................................3 3 制造缓冲区溢出 ...............................................................................4
int printf(const char *format, arg1,arg2,...); 这种函数由于不知道参数的个数,因此并不能确定参数什么时候结束。它便 只会根据 format 中的转义字符依次打印堆栈中参数地址对应的内容。 在 format 串中,主要利用%n 来实现攻击。 (%n 在格式化中的意思是将显示内容的长度输出到一个变量中去。) 参考如下代码: #include <stdio.h> int main() {
所以出现了段错误。
但是,我做这个过程时,并没有如愿出现段错误,只有编译时有个参数
不匹配的警告。。。
5
缓冲区溢出攻击与防范
运行正常:
这个问题,我思考了很久,突然发现新装的 Linux 系统是 64 位的,瞬间 豁然开朗,那样巨大的内存地址是完全访问的了的!!!
但是,这个代码还是给了我们很大的启示。如果我们可以控制 num 的内 容,我们就可以向任意内存地址写入数据(当然必须是可以访问的内存空间), 一旦我们得知程序返回地址存放在哪里,我们便可以覆盖这个位置,从而使 程序调到我们想要的任意地址。
这就是格式化字符串缓冲区溢出攻击。
3.2 堆栈缓冲区(Buffer)溢出攻击:
缓冲区是程序运行的时候机器内存中的一个连续块,它保存了给定类型的 数据,大多数情况下为了不占用太多的内存,一个有动态分配变量的程序在程 序运行时才决定给它们分配多少内存。如果程序在动态分配缓冲区放入超长的 数据,它就会溢出了。这就是堆栈缓冲区溢出。通常,缓冲区溢出只会产生过 段错误。如下面的程序。
计算机病毒和入侵检测大作业
缓冲区溢出攻击与防范
Buffer overflow attacking and prevention
学 院(系):
专
业:
学 生 姓 名:
学
号:
班
级:
完 成 日 期: