实验报告
计算机科学与技术学院
目 录
2.1 请按照入栈顺序,写出C语言32位环境下的栈帧结构(5分)
2.2 请按照入栈顺序,写出C语言64位环境下的栈帧结构(5分)
第1章 实验基本信息
1.1 实验目的
理解C语言函数的汇编级实现及缓冲器溢出原理
掌握栈帧结构与缓冲器溢出漏洞的攻击设计方法
进一步熟练使用Linux下的调试工具完成机器语言的跟踪调试
1.2 实验环境与工具
1.2.1 硬件环境
X64 CPU;2GHz;2G RAM;256GHD Disk 以上
1.2.2 软件环境
Windows7 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位
1.2.3 开发工具
Visual Studio 2010 64位以上;GDB/OBJDUMP;DDD/EDB等
1.3 实验预习
上实验课前,必须认真预习实验指导书(PPT或PDF)
了解实验的目的、实验环境与软硬件工具、实验操作步骤,复习与实验有关的理论知识。
按照入栈顺序,写出Linux平台C语言32位程序的栈帧结构
按照入栈顺序,写出Linux平台C语言64位程序的栈帧结构
简述缓冲区溢出的原理及危害
简述缓冲器溢出漏洞的攻击方法
简述缓冲器溢出漏洞的防范方法
第2章 实验预习
2.1 请按照入栈顺序,写出Linux平台C语言32位程序的栈帧结构(5分)
2.2 请按照入栈顺序,写出Linux平台C语言64位程序的栈帧结构(5分)
2.3 请简述缓冲区溢出的原理及危害(5分)
原理:计算机向缓冲区内写数据时超过了缓冲区本身的容量,而导致数据溢出到被分配空间之外的内存空间,使得溢出的数据覆盖了其他内存空间的数据,从而破坏程序的堆栈,造成程序崩溃或使程序转而执行其他指令,进而被攻击。造成缓冲区溢出一般是因为计算机对接收的输入数据没有进行有效的检测。
危害:对越界的数组元素的写操作会破坏存储在栈的状态信息,当程序使用这个被破坏的状态,试图重新加载寄存器或执行ret指令时,就会出现严重的错误,缓冲区溢出的一个更加致命的使用就是让程序执行它本来不执行的函数,这是一种常见的网络攻击系统安全的方法。
2.4 请简述缓冲器溢出漏洞的攻击方法(5分)
例如向输入程序输入一个字符串,这个字符串包含一些可执行代码的字节编码(攻击代码),另外还有一些字节会用一个指向攻击代码的指针来覆盖返回地址,那么执行ret指令的效果就是跳转到攻击代码。
2.5 请简述缓冲器溢出漏洞的防范方法(5分)
栈随机化:栈随机化的思想使得栈的位置在程序每次运行时都有变化。所以即使许多机器都运行相同的代码,他们的栈地址都是不同的。实现的方式为程序开始时,在栈上分配一段0-n字节之间的随机大小的空间,n必须足够大,才能获得足够多的栈地址变化,但是也不能太大,因为会浪费程序太多的空间。
栈破坏检测:通过栈保护者机制,来检测缓冲区越界。栈破坏检测的思想为在栈中任何局部缓冲区与栈状态之间存储一个特殊的金丝雀值,是在程序每次运行时随机产生的,攻击者不容易知道其值。在恢复寄存器状态和从函数返回之前,程序通过检测这个金丝雀值是否被函数的某个操作改变了,如果是,那么终止程序。
限制可执行代码区域:一种方法是限制哪些内存区域能够存放可执行代码,在典型的程序中,只有保护编码器产生的代码那部分内存才需要是可执行的,其他部分可以被限制为只读只写。
第3章 各阶段漏洞攻击原理与方法
每阶段40分(文本20分,分析20分),总分不超过80分
3.1 Smoke阶段1的攻击与分析
文本如下:
分析过程:
先查看smoke的起始地址为08048bbb。
再看getbuf的反汇编代码,可知输入字符串的位置为%ebp-0x28,其中四十个字节是放正常输入的内容,如果再输入四个字节,就会覆盖旧的%ebp,而再输入四个字节,就会覆盖getbuf保存的返回地址。所以只要最后四个字节为smoke的起始地址就可以,注意一下小端序即可。
3.2 Fizz的攻击与分析
文本如下:
分析过程:
先查看fizz的起始地址为08048be8,再考虑怎么传参,发现第四行把%ebp+0x8的值传给了%edx,要注意的是,此时fizz是直接执行的,不是call调用的,所以不用把返回地址压入栈,因为原来的%esp指向getbuf的返回地址,那么与第一问不同的是把getbuf的返回地址改成fizz的起始地址,还要继续任意输入四个字节,最后输入要传的cookie为0x1a07b746。运行成功。
3.3 Bang的攻击与分析
文本如下:
分析过程:
先查看bang的初始地址为08048c39,考虑怎么找到全局变量,发现0x804e160地址的值传给了%eax,可能这就是全局变量的地址,那么想要修改全局变量的值,需要编写一段代码来修改,写如下汇编代码。
因为输入字符,所以要转化为机器码。
这样的话,这段机器码的作用就是修改全局变量并进入bang函数,现在要将这段恶意代码写到buf的起始地址,查看getbuf反汇编代码可知,%ebp-0x28传给了%eax,刚开辟栈帧这一步得到的%eax其实就是Get函数存放数据的首地址,所以程序要到0x556833a8去执行恶意代码。
所以将机器码放在文本最前面,四十个字节输入后,再输入四个字节覆盖旧的%ebp,再输入0x556833a8去覆盖返回地址。运行成功。
3.4 Boom的攻击与分析
文本如下:
分析过程:
根据题意,要在getbuf结束之后回到test原本的位置,并将返回值设为cookie,同时需要恢复原本%ebp的值,返回test中继续执行。现在看一下test中调用完getbuf的下一条指令地址,发现为0x8048ca7。
此外还需要确定旧%ebp的值,可以发现%ebp中存的是0x556833f0。
编写如下汇编代码并转为机器码。
同第三问将机器码放在最前面,将buf首地址放在最后面即可,运行成功。
3.5 Nitro的攻击与分析
文本如下:(不理解为什么结果不对)
分析过程:与第四问不同的在于流程会执行五次,其中修改部分每次都是一样的,但是每一次分配给testn函数的%ebp是不同的,所以不可以用一个确定的地址去还原%ebp了,而且Get函数存储字符的首地址也在改变。
观察testn反汇编代码,发现调用getbufn之前除了保存旧%ebp之外,还开辟了0x18个空间,故有%ebp=%esp+0x18,而当getbufn结束后,%esp会回到原处,所以我们可以通过%ebp=%esp+0x18这个关系来将%ebp还原。
接下来查看getbufn反汇编代码来确定Get函数保存输入的字符的首地址。
发现调用Get之前开辟了0x208(520)个字节来正常输入字符,发现字符串区域变大了很多,而且这次实验不同之处在于栈的位置不确定,显然不可能完全不确定,应该是一定范围内的不确定,仔细思考发现这个区域应该比0x208小,所以可以在攻击字符串中插入适量的nop指令来达到顺利的执行攻击代码。接下来再分析五次读入数据的首地址,分别得到五个首地址。
取最大的地址为返回地址,这样就能确保每次程序无论怎么跳都能跳进输入的内容里面。编写汇编代码并转换为机器码。
所以我认为答案是509个90再加上b8 46 b7 07 1a 8d 6c 24 18 68 21 8d 04 08 c3 f8 31 68 55,但是运行不正确,想了很久也不理解为什么不对。
第4章 总结
4.1 请总结本次实验的收获
本次实验如此多的攻击类型都是基于 Get() 函数输入的字符没有限制而导致的溢出并覆盖原来的栈帧,这是危险的一件事。通过这次实验,我对程序运行时栈帧结构的变化有了一个更深入的了解,我也掌握了这个比较基础的缓冲区溢出攻击的方法,为将来的漏洞攻击以及安全维护相关知识的进一步学习打好基础,初步了解到一些黑客是如何进行攻击的,也思考了怎样去避免这种攻击。
4.2 请给出对本次实验内容的建议
暂无,感觉收获满满。
注:本章为酌情加分项。
参考文献
为完成本次实验你翻阅的书籍与网站等
[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.