Buffer Overflow Vulnerability Lab
Lab Tasks
Turning Off Countermeasures
Address Space Randomization(堆栈地址随机化):主要是基于Linux操作系统的机器,通过将heap和stack的起始地址随机化来防止缓存区溢出攻击
sudo sysctl -w kernel.randomize_va_space=0
stackGuard:gcc提供的一种安全机制,当其存在时,无法进行buffer overflow攻击,但是可以在编译文件的时候选择禁用这个安全机制
不可执行化堆栈:需要在program头来设置堆栈是否是可执行性的
Task 1: Running Shellcode
shellcode的原型
#include <stdio.h>
int main() {
char *name[2];
name[0] = "/bin/sh";
name[1] = NULL;
execve(name[0], name, NULL);
}
execve(执行文件)在父进程中fork一个子进程,在子进程中调用exec函数启动新的程序。execve()用来执行第一参数字符串所代表的文件路径,第二个参数是利用指针数组来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。从图中可以,如果通过C语言调用execve来返回shell的话,首先需要引入相应的头文件,然后在主函数中调用系统调用函数execve;同时传入三个参数
这里只是通过C语言来进行调用bin/sh文件并且将对应的参数传入其中,但是我们要将shellcode放入到内存中,这样在进行buffer overflow攻击的时候才能够执行
当我们编译并且运行call_shellcode.c的时候,还会看到出现一个shell,并且在其中输入相应命令可以得到执行后的结果
Task 2: Exploiting the Vulnerability、
分析:在这一步中,关键的是修改buffer里面的内容,它的逻辑是这样的:首先exploit.c先将buffer[517]进行构造,填充好其中的内容,使得在stack.c中调用bof()来进行strcpy的时候,能够将return address覆盖掉
增加代码:
strcpy(buffer+80,shellcode);
strcpy(buffer + 0x24, "\xE7\xEB\xFF\xBF");
在这里我们将对应的shellcode放置在buffer + 80(0x50)的地方,这个地方可以随便更改,但是值得注意的是不能覆盖掉return address对应的位置
确定shellcode的存放地址是哪里
首先,exploit.c里面的buffer最终是要写入到badfile文件中的,而badfile文件又会被读入到str字符数组中去,所以相应的buffer里面的内容也就相当于是str里面的内容,所以我们先要确定str的地址(gdb调试),之后通过在buffer里面shellcode的偏移地址来确定shellcode在内存中的相应地址
gdb stack r//看寄存器内容 p /x &str//查找str对应的地址
所以shellcode的代码在stack.c的stack中的位置是0xbfffeb97 + 0x50 = 0xbfffebe7;
确定return address的位置
当我们确定了shellcode的起始位置之后,我们就需要确定return address的位置,这样让shellcode的起始位置覆盖掉return address就可以了
先查看bof的地址以及反汇编内容
disas bof
对应分析反汇编代码发现,其中
lea eax, [ebp-0x20]
是将buffer入栈,参考lea与mov的区别,而上面一行的push是将str入栈(变量从右至左入栈)
之后查看寄存器
所以确定ebp和buffer之间的距离是0x20,同时由于是32位的,所以return address的栈中地址为0x20+0x04 = 0x24
成功!!!
Task 3: Defeating dash’s Countermeasure
dash是在Ubuntu中的防止栈溢出的策略,会去检测effective UID,下面是mian.c的一些变化
defeat的策略:在execve()之前调用setuid(0)
未取消注释的时候:
此时获得的是用户权限的shell
取消注释:
此时获得的是用户权限的shell
更新shellcode
char shellcode[] = "\x31\xc0" /* Line 1: xorl %eax,%eax */ "\x31\xdb" /* Line 2: xorl %ebx,%ebx */ "\xb0\xd5" /* Line 3: movb $0xd5,%al */ "\xcd\x80" /* Line 4: int $0x80 */ // ---- The code below is the same as the one in Task 2 --- "\x31\xc0" "\x50" "\x68""//sh" "\x68""/bin" "\x89\xe3" "\x50" "\x53" "\x89\xe1" "\x99" "\xb0\x0b" "\xcd\x80";
4条指令对应的作用:
(1) set ebx to zero in Line 2
(2) set eax to 0xd5 via Line 1 and 3 (0xd5 is setuid()’s system call number)
(3) execute the system call in Line 4.
此时defeat dash成功,得到root权限的shell
并且如果不加入这四行,即不进行setuid()的话,运行后只能得到用户权限的shell
Task 4: Defeating Address Randomization
打开站地址随机化策略后直接运行
此时会发生segmentation fault,说明在虚拟地址转化为实际的物理地址的时候发生了意外,说明之前计算的地址与现在的是不一样的
在循环的过程中,如果地址不匹配,一直显示segmentation fault,知道匹配,之后则会发生攻击
Task 5: Turn on the StackGuard Protection
当打开栈边界保护的时候,重新编译并运行
发现检测到堆栈破坏,运行的易受程序的程序被终止并且放弃
是由于分配的空间不足以及设置的数值发生了变化,stack.c里面的buffer与要写入的str相比空间太少,所以引起边界保护的报错,同时再修改return address的时候可能会有边界的数值的变化
Task 6: Turn on the Non-executable Stack Protection
不能得到一个shell,发生了段错误(segmentation fault),其原因是:我们将对应的shellcode放在了Buffer中,而这一局部变量是位于stack上的,所以对应的逻辑地址无法转化为实际的物理地址,进而更不可能执行,发生segmentation fault
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!