实验报告
实 验(四)
题 目 Buflab
缓冲器漏洞攻击
专 业 计算机科学与技术
目 录
第1章 实验基本信息... - 3 -
1.1 实验目的... - 3 -
1.2 实验环境与工具... - 3 -
1.2.1 硬件环境... - 3 -
1.2.2 软件环境... - 3 -
1.2.3 开发工具... - 3 -
1.3 实验预习... - 3 -
第2章 实验预习... - 4 -
2.1 请按照入栈顺序,写出C语言32位环境下的栈帧结构(5分)... - 4 -
2.2请按照入栈顺序,写出C语言62位环境下的栈帧结构(5分)... - 4 -
2.3请简述缓冲区溢出的原理及危害(5分)... - 4 -
2.4请简述缓冲器溢出漏洞的攻击方法(5分)... - 4 -
2.5请简述缓冲器溢出漏洞的防范方法(5分)... - 5 -
第3章 各阶段漏洞攻击原理与方法... - 6 -
3.1 Smoke阶段1的攻击与分析... - 6 -
3.2 Fizz的攻击与分析... - 7 -
3.3 Bang的攻击与分析... - 8 -
3.4 Boom的攻击与分析... - 8 -
3.5 Nitro的攻击与分析... - 9 -
第4章 总结... - 10 -
4.1 请总结本次实验的收获... - 10 -
4.2 请给出对本次实验内容的建议... - 10 -
参考文献... - 11 -
上实验课前,必须认真预习实验指导书(PPT或PDF)
了解实验的目的、实验环境与软硬件工具、实验操作步骤,复习与实验有关的理论知识。
原理:通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,造成程序崩溃或使程序转而执行其它指令,以达到攻击的目的。造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数。
危害:对越界的数组元素的写操作会破坏储存在栈中的状态信息,当程序使用这个被破坏的状态,试图重新加载寄存器或执行ret指令时,就会出现很严重的错误。缓冲区溢出的一个更加致命的使用就是让程序执行它本来不愿意执行的函数,这是一种最常见的网络攻击系统安全的方法。
通常,输入给程序一个字符串,这个字符串包含一些可执行代码的字节编码,称为攻击代码,另外,还有一些字节会用一个指向攻击代码的指针覆盖返回地址。那么,执行ret指令的效果就是跳转到攻击代码。在一种攻击形式中,攻击代码会使用系统调用启动一个shell程序,给攻击者提供一组操作系统函数。在另一种攻击形式中,攻击代码会执行一些未授权的任务,修复对栈的破坏,然后第二次执行ret指令,(表面上)正常返回到调用者。
1.栈随机化
栈随机化的思想使得栈的位置在程序每次运行时都有变化。因此,即使许多机器都运行相同的代码,它们的栈地址都是不同的。实现的方式是:程序开始时,在栈上分配一段0~n字节之间的随机大小的空间。
2.栈破坏检测
栈破坏检测的思想是在栈中任何局部缓冲区与栈状态之间存储一个特殊的金丝雀值,也称哨兵值,是在程序每次运行时随机产生的。在回复寄存器状态和从函数返回之前,程序检查这个金丝雀值是否被该函数的某个操作改变了。如果是的,那么程序异常终止。
3.限制可执行代码区域
这个方法是消除攻击者向系统插入可执行代码的能力。一种方法是限制哪些内存区域能够存放可执行代码。在典型的程序中,只有保护编译器产生的代码的那部分内存才需要是可执行的。其他部分可以被限制为只允许读和写。
每阶段25分,文本10分,分析15分,总分不超过80分
bufbomb:文件格式 elf32-i386
文本如下:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 bb 8b 04 08
分析过程:
目标是构造一个攻击字符串作为bufbomb的输入,在getbuf()中造成缓冲区溢出,使得getbuf()返回时不是返回到test函数,而是转到smoke函数处执行。
观察getbuf函数,getbuf的栈帧是0x38+4个字节,而buf缓冲区的大小时0x28(40个字节)。字符串在栈帧中向上扩展,当扩展到一定值时会覆盖返回地址。
攻击字符串的大小应该是0x28+4+4=48个字节。攻击字符串的最后4字节应是smoke函数的地址。前44字节可为任意值,最后4字节为smoke地址,并且根据小端格式,最后四个字节为bb 8b 04 08.
文本如下:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 e8 8b 04 08 00 00 00 00 81 f7 d4 16
分析过程:
第一步:根据getbuf函数,前面的字符串与smoke的攻击一致,都是输入44个任意的字节,第45~48个字节位fizz函数的地址,并且由小端序,为e8 8b 04 08。
第二步:观察fizz函数可知,fizz函数中将0x8(%ebp)与0x804e158处的值进行比较,如果相等,则继续往下执行validate,否则向下执行exit(0).
此时gdb查看0x804e158。
可知该处的值为cookie,并且我们可以知道出0x8(%ebp)处即为fizz函数的参数。
由于getbuf函数返回时,%ebp会指向返回地址处,因此我们只需要使0x8(%ebp)处为cookie的值即可(注意小端排序),为81 f7 d4 16,而0x4(%ebp)处只需要输入任意值即可。
为了更好地说明此题,附上函数返回到fizz函数时栈结构示意图:
文本如下:c7 05 60 e1 04 08 81 f7 d4 16 68 39 8c 04 08 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c8 30 68 55
分析过程:bang要求构造攻击字串,使目标程序调用bang函数,要将函数中全局变量global_value篡改为cookie值,使相应判断成功,需要在缓冲区中注入恶意代码篡改全局变量。
由于全局变量并不存在栈中,于是只能考虑在栈中够到全局变量,并将其修改。
思路是:将getbuf返回地址覆盖为 (%ebp-0x28) ,即字符串的首地址,并在字符串的首地址处插入恶意代码,而恶意代码负责篡改全局变量,并且跳转到bang函数。
第一步. 先用gdb调试可知,0x804e160地址处为全局变量,而0x804e158处为cookie。
第二步. gdb查看字符串首地址值: 0x556830c8.
第三步.编写恶意汇编代码
解释如下:先将cookie以立即数的形式存入global_value地址;再将bang函数的首地址压入栈中,目的是使global_value被修改后,调用bang函数。
下面将asmbang.s文件编译再反编译之后,即可得到恶意代码的字节序列,
c7 05 60 e1 04 08 81 f7 d4 16 68 39 8c 04 08 c3,并将其插入字符串开头处即可。
综上可得,字符串为:c7 05 60 e1 04 08 81 f7 d4 16 68 39 8c 04 08 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c8 30 68 55
文本如下:b8 81 f7 d4 16 68 a7 8c 04 08 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 31 68 55 c8 30 68 55
分析过程:从ppt可以总结出boom攻击的两个任务:一. 构造攻击字符串,使得getbuf都能将正确的cookie值返回给test函数,要求被攻击程序能返回到原调用函数test继续执行——即调用函数感觉不到攻击行为。二.还原对栈帧结构的任何破坏。
思路是:和bang的攻击类似,将getbuf的返回地址赋值为字符串的首地址,也就是 (%ebp-0x28),并且在字符串首地址处插入恶意代码,而本题恶意代码要求将cookie的值赋给返回值,也就是%eax,同时继续返回test函数。另外,为了还原对栈结构的任何破坏,不同于之前缓冲区溢出时以00 00 00 00覆盖old %ebp ,本次需要gdb调试出%ebp的值,并保留在原处。
首先,gdb查看字符串首地址值: 0x556830c8.
第二步,gdb查看调用getbuf时%ebp的值:0x55683110
第三步,查看test函数执行完call 8049378
第四步. 编写恶意汇编代码
先将cookie以立即数的形式赋值给%eax,也就是返回值 ;再将上一步得到的getbuf返回地址压入栈中。
最后将asmboom.s文件编译再反编译之后,即可得到恶意代码的字节序列: b8 81 f7 d4 16 68 a7 8c 04 08 c3,并将其插入字符串开头处即可。
综上可得字符串为:b8 81 f7 d4 16 68 a7 8c 04 08 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 31 68 55 c8 30 68 55
文本如下:
分析过程:
本次攻击的主要任务是:构造攻击字符串使getbufn函数,返回cookie值至testn函数,而不是返回值1;需要将cookie值设为函数返回值,复原被破坏的栈帧结构,并正确地返回到testn函数;保证每次都能够正确复原栈帧被破坏的状态,并使程序能够正确返回到test。
首先分析,虽然五次执行栈,%ebp的值都不同,但是根据testn函数可知,%ebp相对%esp是绝对的,二者满足关系:%ebp = %esp+0x18 。因此,还原栈帧被破坏的状态,只需要执行语句leal 0x18(%esp),%ebp即可,另外同上题一致,将cookie的值给%eax ,可以返回cookie的值至testn函数,将call 8049394
下面转化为机器码:
再分析getbufn函数:
根据之前对栈的分析,可以知道,这次要输入的字节数为:
0x208+0x4+0x4 = 528
将返回地址覆盖为字符串的首地址,但由于buf缓冲区的首地址不确定,所以我们此时用gdb调试,追踪call 8048e28
取最高地址0x55682ee8作为返回地址,这样就会一路滑行到恶意代码并执行恶意代码。
最后回到buf首地址,因为随机,不知道程序会跳到哪儿 ,所以把恶意代码放在最后,并且用nop滑行,其中nop不会执行任何操作,只有pc加一,机器码是90。
综上所述,构成字符串的组成部分有:509个字节的90 + 15个字节的恶意代码 + 4个字节的buf首地址最大值,一共恰好是528个字节。
更好地理解了C语言函数的汇编级,和缓冲区溢出的原理
更好地理解了栈帧结构
掌握缓冲区溢出攻击的设计方法
进一步理解gdb的调试
前面几个攻击较为简单,最后一个难度过大,感觉题目难度设置有些不合理。
注:本章为酌情加分项。
为完成本次实验你翻阅的书籍与网站等
[1] 林来兴. 空间控制技术[M]. 北京:中国宇航出版社,1992:25-42.
[2] 辛希孟. 信息技术与信息服务国际研讨会论文集:A集[C]. 北京:中国科学出版社,1999.
[3] 赵耀东. 新时代的工业工程师[M/OL]. 台北:天下文化出版社,1998 [1998-09-26]. http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).
[4] 谌颖. 空间交会控制理论与方法研究[D]. 哈尔滨:哈尔滨工业大学,1992:8-13.
[5] KANAMORI H. Shaking Without Quaking[J]. Science,1998,279(5359):2063-2064.
[6] CHRISTINE M. Plant Physiology: Plant Biology in the Genome Era[J/OL]. Science,1998,281:331-332[1998-09-23]. http://www.sciencemag.org/cgi/ collection/anatmorp.