笔记 | 计算机系统基础:09-不得不防的缓冲区溢出攻击!

零. 课程要点:
  • 缓冲区溢出
  • 缓冲区溢出攻击
  • 缓冲区溢出防范

学完了数据的内存结构,以及函数调用的底层过程,我们就来看一下在各种操作系统和应用软件中广泛存在的漏洞:缓冲区溢出。

一. 缓冲区溢出

首先,缓冲区是什么?

缓冲区是一块连续的计算机内存区域,可以是堆栈(自动变量)、堆(动态内存)和静态数据区(全局或静态)。在C语言中,通常使用字符数组和内存分配函数实现缓冲区。如下图所示:

可执行文件的存储器映像

那么什么是缓冲区溢出?

缓冲区溢出就是指当计算机程序向缓冲区内填充的数据位数超过了缓冲区本身的容量,溢出的数据覆盖在其它的数据或受保护空间中。

由于C语言没有数组越界检查机制,当向局部数组缓冲区里写入的数据超过为其分配的大小时,就会发生缓冲区溢出。举个例子:

double fun(int i)
{
    volatile double d[1] = {3.14};
    volatile long int a[2];
    a[i] = 1073741824;
    return d[0];
}

当调用这个函数时,我们发现结果如下:

fun(0) = 3.14
fun(1) = 3.14
fun(2) = 3.1399998664856
fun(3) = 2.00000061035156
fun(4):Segmentation fault

上面就是一个典型的对数组的越界访问,为什么会出现上面的结果?只需要看一下栈中的数据内容就能明白:

栈中的数据

i=0i=1时,1073741824存储于正确的位置,但是当i=2时,a[2] = 1073741824,虽然我们认为没有定义a[2],但是根据前面的知识,我们知道数组元素可以使用指针来访问,因此对数组的引用没有边界约束,因此数据覆盖了d[0]的地方,造成了错误。如果i更大,那就有可能在受保护的地方写入了数据,造成程序崩溃甚至被劫持。

二. 缓冲区溢出攻击

造成缓冲区溢出的原因是没有对栈中作为缓冲区的数组的访问进行越界检查。缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可导致程序运行失败、系统关机、重新启动等后果。

在前面的学习中我们知道在函数调用过程中,会把返回地址入栈,并在函数调用结束后取出并跳转。如果利用缓冲区溢出将函数返回地址修改为指向一段精心安排的恶意代码,从而改变程序正常流向,则可达到危害系统安全的目的。最常见的手段是通过制造缓冲区溢出使程序运行一个用户shell,再通过shell执行其它命令。若该程序有root或suid执行权限,则攻击者就获得一个有root权限的shell,进而可对系统进行任意操作。

举个例子:

缓冲区溢出攻击

上面的代码原意是想打印出第一个参数,但是只分配了16个字节的大小。当main函数调用outputs时,会先保存返回地址,然后保存EBP旧值,重新形成栈底。然后分配16个字节的变量,并将参数入栈,准备调用strcpy函数。

若strcpy复制了25个字符到buffer中,并将hacker首址置于结束符‘\0’前4个字节,则在执行strcpy后,hacker代码首址被置于main栈帧返回地址处,当执行outputs代码的ret指令时,便会转到hacker函数实施攻击。

即假定hacker首址为0x08048411,那么我们构造一个字符串作为参数传入:

char code[]=
"0123456789ABCDEFXXXX"
"\x11\x84\x04\x08"
"\x00";

int main(void) {
    char *argv[3];
    argv[0]="./test";
    argv[1]=code;
    argv[2]=NULL;
    execve(argv[0],argv,NULL);
    return 0;
}

就可以转到hacker函数实施攻击。

三. 缓冲区溢出防范
函数 危险性 解决方案
gets 最高 禁用gets(buf),改用fgets(buf, size, stdin)
strcpy 检查目标缓冲区大小,或改用strncpy,或动态分配目标缓冲区
strcat 改用strncat
sprintf 改用snprintf,或使用精度说明符
scanf 使用精度说明符,或自己进行解析
sscanf 使用精度说明符,或自己进行解析
fscanf 使用精度说明符,或自己进行解析
vfscanf 使用精度说明符,或自己进行解析
vsprintf 改为使用vsnprintf,或使用精度说明符
vscanf 使用精度说明符,或自己进行解析
vsscanf 使用精度说明符,或自己进行解析
streadd 确保分配的目标参数缓冲区大小是源参数大小的四倍
strecpy 确保分配的目标参数缓冲区大小是源参数大小的四倍
strtrns 手工检查目标缓冲区大小是否至少与源字符串相等
getenv 不可假定特殊环境变量的长度
realpath 高(或稍低,实现依赖) 分配缓冲区大小为PATH_MAX字节,并手工检查参数以确保输入参数和输出参数均不超过PATH_MAX
syslog 高(或稍低,实现依赖) 将字符串输入传递给该函数之前,将所有字符串输入截成合理大小
getopt 高(或稍低,实现依赖) 将字符串输入传递给该函数之前,将所有字符串输入截成合理大小
getopt_long 高(或稍低,实现依赖) 将字符串输入传递给该函数之前,将所有字符串输入截成合理大小
getpass 高(或稍低,实现依赖) 将字符串输入传递给该函数之前,将所有字符串输入截成合理大小
getchar 若在循环中使用该函数,确保检查缓冲区边界
fgetc 若在循环中使用该函数,确保检查缓冲区边界
getc 若在循环中使用该函数,确保检查缓冲区边界
read 若在循环中使用该函数,确保检查缓冲区边界
bcopy 确保目标缓冲区不小于指定长度
fgets 确保目标缓冲区不小于指定长度
memcpy 确保目标缓冲区不小于指定长度
snprintf 确保目标缓冲区不小于指定长度
strccpy 确保目标缓冲区不小于指定长度
strcadd 确保目标缓冲区不小于指定长度
strncpy 确保目标缓冲区不小于指定长度
vsnprintf 确保目标缓冲区不小于指定长度
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,367评论 0 5
  • 缓冲区溢出(Buffer Overflow)是计算机安全领域内既经典而又古老的话题。随着计算机系统安全性的加强,传...
    Chivalrous阅读 1,327评论 0 5
  • 原文地址:https://github.com/JuanitoFatas/slime-user-manual#24...
    四月不见阅读 3,104评论 0 2
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,212评论 0 4
  • 计算机系统漫游 代码从文本到可执行文件的过程(c语言示例):预处理阶段,处理 #inlcude , #defin...
    willdimagine阅读 3,560评论 0 5