实验目的与要求
1. 强化机器级表示、汇编语言、调试器和逆向工程等方面基础知识,并结合栈帧工作原理实现简单的栈溢出攻击,掌握其基本攻击基本方式和原理,进一步为编程过程中应对栈溢出攻击打下一定的基础。
2. 理解缓冲区的工作原理和字符填充过程及其特点。对于无边界检测的语言及其工作方式所造成的缓冲区漏洞加深理解。
3. 通过字符串填充的方式,完成5各阶段的缓冲区攻击。分别基于基本返回地址填充、攻击代码填充、ROP等实现这5个难度递增的阶段的缓冲区溢出攻击。
实验原理与内容
“AttackLab”是一个Linux下的可执行C程序,包含了5个阶段(phase1~phase5)的不同内容。程序运行过程中,要求学生能够根据缓冲区的工作方式和程序的反汇编代码来确定攻击字符串长度和字符串中的关键内容。每次成功实现缓冲区溢出攻击时都会有提示相应内容,如果攻击失败则单纯的提示segmentation fault相关信息。
要求攻击字符串的执行不许绕开代码中的validate函数,缓冲区溢出之后对应ret的返回地址可以是以下类型:
1.函数touch1、touch2、touch3的首地址;
2.自行注入的攻击的首地址;
3.在后两个阶段中(ROP攻击),与farm.c的对应的可利用的gadget的起始地址,farm.c对应的机器码已经包含在可执行文件中。可以使用的gadget首地址需处于start_farm和end_farm之间的部分。
注意:前三个阶段使用ctarget作为攻击目标文件,后两个阶段中使用rtarget作为攻击目标文件。
每个阶段考察一个缓冲区溢出方式,难度逐级递增:
阶段1:使用非ROP方式对ctarget进行攻击,调用touch1,且成功输出Touch1!: You called touch1。若不完全满足题目要求,则会提示“Misfire”和FAIL相关字段。
阶段2:使用非ROP方式对ctarget进行攻击,调用touch2,且成功输出Touch2!: You called touch2。攻击过程中需要改写cookie变量的值。若不完全满足题目要求,则会提示“Misfire” 和FAIL相关字段。
阶段3:使用非ROP方式对ctarget进行攻击,调用touch3,且成功输出Touch3!: You called touch3。攻击过程中需要使hexmatch的返回值能够正确引导validate函数。若不完全满足题目要求,则会提示“Misfire” 和FAIL相关字段。
阶段4:使用ROP方式对rtarget进行攻击,调用touch2,且成功输出Touch2!: You called touch2。若不完全满足题目要求,则会提示“Misfire” 和FAIL相关字段。
阶段5:使用ROP方式对rtarget进行攻击,调用touch3,且成功输出Touch3!: You called touch3。若不完全满足题目要求,则会提示“Misfire” 和FAIL相关字段。
ctarget和rtarget都从standard input读入数据,可以以重定向文件的形式进行输入。实验利用getbuf函数中的缓冲区。getbuf函数的结构如下:
unsigned getbuf()
{
char buf[BUFFER_SIZE];
Gets(buf);
return 1;
}
函数中的Gets函数与标准库中的gets函数类似,它从standard input中读取字符(以\n或者EOF结尾)并将它们添加字符串结尾符\0后存入缓冲区中。学生需要根据ctarget和rtarget文件及其反汇编代码来确定缓冲区位置及大小,并想办法构建出攻击字符串。
实验设备与软件环境
1.Linux操作系统—64位Ubuntu 18.04
2. gdb调试器和objdump反汇编指令
3. 笔记本
实验过程与结果
Phase_1:
首先根据汇编得到touch1的地址是0x4018b9,然后查看getbuf函数中发现开辟了56个字节的栈空间,即57字节开始的test函数的返回地址更改为touch1函数的首地址
验证通过
Phase_2:
首先得到查看反汇编得到touch2的地址值,然后伪造文件进行代码注入,将cookie值压入栈中,因为touch2传了一个参数,这个参数值如果等于cookie的话就成功,将正常的返回地址设置成为注入代码的地址,这次注入直接在栈顶注入,即设置为%rsp。
将伪造的文件汇编得到二进制文件:
查看getbuf函数中rsp的值
将得到的底层二进制编码进行二进制文件编写
验证通过
Phase_3:
touch3
中调用了hexmatch,
也就是说需要将cookie转换成对应的字符串传进去,所以,首先对cookie进行as码16进制转换:
计算栈顶的位置:先查看汇编文件中getbuf函数rsp的值,然后将该值+0x38+8,也就是得到0x556243f8
进行伪造文件编写,因为要调用touch3函数,所以pushq (touch3的地址)
汇编得到底层字节码:
验证正确
Phase_4:
这一关需要用到指令编码表。
本题的任务与Phase_2
相同,也是要求返回到touch2
函数,phase_2
中用到的注入代码为:
首先,要把cookie赋值给参数寄存器%rdi,因为要将cookie放在栈中,所以需要用到指令:pop %rdi,这里因为在汇编中找不到这条指令的gedget,所以将其分开用两个gadget实现,即:retq movq %rax,%rdi retq popq %rax,getbuf执行ret,从栈中弹出返回地址,跳转到我们的gadget01;gadget01执行,将cookie弹出,赋值给%rax,然后执行ret,继续弹出返回地址,跳转到gadget2
gadget2执行,将cookie值成功赋值给参数寄存器%rdi,然后执行ret,继续弹出返回地址,跳转到touch2。
经过查表可得,pop %rax用58表示,movq %rax,%rdi用48 89 c7表示
movq %rax,%rdi这条指令在汇编文件中找到的地址是0x401aca。
Popq %rax这条指令在汇编文件中找到的地址是0x401abd
然后根据上面的地址值以及栈帧就能得到输入序列:
验证攻击成功!