1.解决缓冲区溢出攻击的必要性
缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统瘫痪、重新启动等后果。更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。第一个缓冲区溢出攻击--Morris蠕虫,发生在1988年,由罗伯特,莫里斯制造,它曾造成全世界6000多台网络服务器瘫痪。这种漏洞具有严重的安全风险,因此,了解和防范缓冲区溢出攻击对于确保计算机系统和网络的安全至关重要。
2.. 缓冲区溢出攻击原理分析
1.缓冲区溢出通常发生在程序中使用固定大小的缓冲区来存储用户输入时。攻击者利用这个缓冲区大小不足的情况,向其输入超过缓冲区大小的数据,导致溢出。
2.攻击者利用溢出,可以覆盖程序内存中的关键数据,如返回地址、函数指针等,从而改变程序的执行流程。
3.通过改变程序的执行流程,攻击者可以执行恶意代码,如注入和执行恶意软件、提权等。
2.1缓冲区溢出攻击示例
下面是一个典型的缓冲区溢出攻击示例,用来理解该攻击的工作原理:
假设有以下简单的C语言代码,用于接收用户输入的用户名并将其复制到固定大小的缓冲区中:
图表 2‑1攻击原理代码
在这个示例中,login()函数使用gets()函数接收用户输入的用户名并将其存储在名为buffer的10字节缓冲区中。然而,该代码存在一个严重的安全漏洞。如果用户输入的用户名超过10个字符,gets()函数将无法检查并停止复制,导致缓冲区溢出。
攻击者可以利用这个漏洞,输入超过10个字符的恶意数据,来改变程序的行为。例如,攻击者可能构造一个恶意输入,包括额外的代码,以实现执行任意指令的攻击。
2.2缓冲区溢出攻击修改程序示例
以下是一个简单的示例,用于利用缓冲区溢出攻击修改程序的行为:
图表 2‑2修改程序代码
在上面的示例中,攻击者输入超过10个字符的恶意输入,使得溢出的数据覆盖了函数返回地址。然后,程序执行完login()函数后,将跳转到攻击者构造的malicious_code()函数,执行其中的恶意操作。
这个示例展示了缓冲区溢出攻击的一种常见形式。攻击者利用输入超出缓冲区边界的漏洞,改变程序的执行流程,从而执行任意代码。这种攻击可导致严重的安全问题,包括系统崩溃、远程代码执行、提权等。
为了防范这类攻击,必须在编程中采取安全的实践,如使用安全的输入函数(如fgets()代替gets())并对输入进行长度检查,以确保缓冲区不会溢出。
4. 施赋值大小超出了数组的长度限制
以下是一个简单的示例,是可能赋值大小超出了数组的长度限制
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void StringCopy(char *str){
char p[10];
strcpy(p,str);
}
void hacked(){
while(1){
printf("you are hacked!!!");
}
}
int main()
{
char str[] = "0123456789012345678901234567891111";
unsigned long long *p = (unsigned long long*)&str[18];
(*p) = (unsigned long long)hacked;
//用hack函数的地址覆盖字符串str中的部分内容
//这里的18是在ubuntu64位下测试得到,其他系统可能会出现问题,不能正常运行
StringCopy(str);
return 0;
}
运行结果:
我们只需要覆盖这个返回地址,让它变成我们hack()程序的地址,那么程序就会执行hack程序了。