Windows下DEP保护机制详解及其绕过

写在前面:

本篇博客为本人原创,但非首发,首发在先知社区
原文链接:

https://xz.aliyun.com/t/13855?time__1311=mqmxnQG%3DKDu7D%2F7iiQGkAmpoxIEVmYD&alichlgref=https%3A%2F%2Fxz.aliyun.com%2Fu%2F74789

各位师傅有兴趣的话也可以去先知社区个人主页逛逛(个人昵称:Shad0w_2023)。
在开始DEP保护机制的介绍之前,想一想没有开保护时我们的攻击过程,以及开了我们前面介绍的GS和SafeSEH保护的攻击过程,相信大家都能发现一个问题:就是我们本来写入数据区的数据被当作代码执行了,那么站在一个开发者的角度,我们该如何避免这种问题?

一.DEP保护机制详解

我们溢出攻击的根源就是现代计算机对代码和数据没有做明确的区分导致存储在数据区的数据被当作代码执行,而DEP保护机制,就是来弥补计算机这个缺陷的。
DEP将内存中的代码区和数据区明确区分开来,阻止数据页(如默认的堆页,各种堆栈页以及内存池页)执行代码,当指令指针指向数据区的时候,就会抛出异常。微软从Windows XP SP2就开始支持这种技术了。
关于段页保护机制,可以看看大佬写的这篇文章:操作系统学习 — 启动操作系统:进入保护模式
而根据实现的机制不同,可以分为软件DEP和硬件DEP。

  • 软件DEP
    软件DEP实际上就是我们前面介绍的SafeSEH,大家回想一下,是不是阻止数据区代码执行?它的目的是阻止利用SEH的攻击。
  • 硬件DEP
    可以说硬件DEP才是真正的DEP,硬件DEP需要CPU的支持,AMD和Intel都为此做了设计,AMD称之为No-Execute Page-Protection(NX),Intel称之为Execute Disable Bit(XD),两者的工作原理实际上都在本质上相同。

由于软件DEP我们前面已经介绍过了,在这篇文章中我们就来着重介绍一下硬件DEP。
我们先来检查一下我们的CPU是否支持硬件DEP:
在这里插入图片描述
可以看到这里有两个选项:

  1. 仅为基本Windows程序和服务启用(Option):
    这也就是DEP的Option模式,只对Windows系统组件和服务启用保护,这种模式可以被应用程序动态关闭
  2. 为除下列选定的程序之外的所有程序和服务启用(Optout):
    这也就是白名单机制,对于很多应用程序都提供了保护,这种模式可以被应用程序动态关闭
    除此之外,实际上还有两种模式:
  3. AlwaysOn:
    对所有的进程启用DEP保护,不存在排序列表,在这种模式下,DEP不可以被关闭,且目前只能在64位操作系统上才能启用
  4. AlwaysOff:
    对所有进程禁止使用DEP,DEP也能被动态开启,这种模式一般只有在极少的特定情况下才使用,比如DEP干扰应用程序的运行。

我们可以通过修改C:\boot.ini中的/noexecute启动项来控制DEP的模式。

二.DEP的绕过方式分析

我们看起来这种保护机制无懈可击,但是天才“黑客”们总会想出办法来突破的。我们来分析一下绕过方式:

  1. 首先,如果要让DEP发挥出真正的作用,就要硬件的支持,如果说硬件不支持DEP的话,DEP保护机制根本就发挥不了作用,我们就很容易攻击
  2. 其次,处于兼容性考虑,肯定在某些情况下是不会开启DEP的,比如说加载一个dll,而这个dll没有启用DEP,那么对涉及到这个dll的程序就不敢贸然开启DEP,因为可能影响到程序的正常执行。我们可以让程序加载不启用DEP的dll,然后去攻击
  3. 大家有没有发现,操作系统给我们设置到DEP模式只有两种,而且默认的还是Option模式,而这两种模式,DEP是可以动态关闭的!那我们劫持程序流程,让程序去把DEP关掉,然后我们在数据区的shellcode就可以正常执行了
  4. 页可否执行,也是有一些标记的,我们使用Windows API,将我们存储shellcode的那一页标记为可执行,我们的shellcode也可以正常执行
  5. 我们可以使用Windows API,申请一段可以执行的内存,然后将我们的shellcode放到该内存,我们的shellcode也可以正常执行。

三.DEP的突破方式详解

1.攻击未启用DEP的程序

这种方法不能称之为“绕过”,因为应用程序压根就没开启DEP,DEP保护机制固然很安全,但是我们前面也分析了,有很多应用程序根本就没打开,因为DEP保护是进程级别的,只要该进程中加载了一个没有开启DEP的DLL,它就不敢贸然开启DEP。
攻击这种应用程序想必大家都很熟悉了,这里就不再多赘述了。

2.利用Ret2Libc绕过DEP

<1>.Ret2Libc利用之ZwSetInformationProcess

一个进程的DEP设置保存在KPROCESS结构体中的_KEXECUTE_OPTION上,这个标识我们可以通过ZwSetInformationProcess修改,进而关闭DEP。
我们先来到微软官方文档看看这个函数:

BOOL SetProcessInformation(
  [in] HANDLE                    hProcess,
  [in] PROCESS_INFORMATION_CLASS ProcessInformationClass,
       LPVOID                    ProcessInformation,
  [in] DWORD                     ProcessInformationSize
);

MSDN:setProcessInformation 函数 (processthreadsapi.h)
这样看来,只要我们构造一个合理的栈帧,劫持程序流程,先让程序关闭DEP,然后再调回来执行我们的shellcode,就可以成功绕过DEP。

<2>.Ret2Libc利用之VirualProtect

通过这个API,我们可以修改指定地址上的属性,我们来到微软的官方文档看看该函数:

函数功能:更改调用进程的虚拟地址空间中已提交页面区域的保护。

BOOL VirtualProtect(
  [in]  LPVOID lpAddress,
  [in]  SIZE_T dwSize,
  [in]  DWORD  flNewProtect,
  [out] PDWORD lpflOldProtect
);

MSDN:VirtualProtect 函数
使用这个绕过方法,构造栈帧的时候比较困难,shellcode大小,修改的内存属性我们都可以构造,但是shellcode起始地址需要动态确定,而且函数参数中含有\x00,进行strcpy等函数溢出的时候,会遭到截断。
具体的攻击过程这里不再演示,如果自己构造不出来ROP链,可以参考这篇文章:
Windows Shellcode学习笔记——通过VirtualProtect绕过DEP

<3>.Ret2Libc利用之VirtualAlloc

通过这个API,我们可以申请一段可以执行的内存空间,然后将我们的shellcode复制到这一段空间内,然后我们就可以正常执行shellcode了,我们还是来到微软官方文档看看这个函数:

函数功能:保留、提交或更改调用进程的虚拟地址空间中页面区域的状态。 此函数分配的内存会自动初始化为零。

LPVOID VirtualAlloc(
  [in, optional] LPVOID lpAddress,
  [in]           SIZE_T dwSize,
  [in]           DWORD  flAllocationType,
  [in]           DWORD  flProtect
);

MSDN:VirtualAlloc函数
这里还是需要我们巧妙地构造栈帧,劫持程序流程,跳转到该函数,然后将shellcode复制,然后再拿到程序的控制权,进而执行我们的shellcode。
具体的攻击过程这里不再演示,如果自己构造不出来ROP链,可以参考这篇文章:Windows Shellcode学习笔记——利用VirtualAlloc绕过DEP

3.利用可执行内存绕过DEP

有时候,在程序内存中,会存在一段可读可写可执行的内存,我们如果能够将shellcode复制到这一段内存中的话,就可以完美执行。
这种绕过方式比前面的Ret2Libc简单很多,但是需要一点运气,因为有些应用程序中是没有这样一段内存的。
我们来讲讲这种绕过方式的具体思路:

  1. 找到溢出点,溢出缓冲区后,覆盖返回地址
  2. 构造合理的栈帧,跳转到memcpy函数,将shellcode复制到可读可写可执行的内存中
  3. 返回后拿到程序控制权,跳转到我们的shellcode执行。

具体的攻击过程这里就不再演示了,主要就是巧妙地构造ROP链。

  • 28
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shad0w-2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值