在经典的栈溢出模型中,通过覆盖函数的返回地址来达到控制程序执行流程(EIP寄存器),通常将返回地址覆盖为0x7FFA4512,这个地址是一条JMP ESP指令,在函数返回时就会跳转到这个地址去执行,也就是执行JMP ESP,而此时ESP刚好指向我们在栈上布置的Shellcode,于是就执行了Shellcode。

之所以栈上的数据能被执行,是因为早期操作系统没有区分数据和代码,EIP指向哪里就去哪里执行。

当引入DEP(Data Execution Prevention 数据执行保护)之后,堆、栈上的内存页属性默认不再具有可执行属性,此时如果想直接在栈上执行数据,就会发生错误:


         常用的绕过DEP的技术室ROP(Return Oriented Programming,早期也叫Ret2Libc),ROP由一系列的 Gadget组成。所谓ROP Gadget,就是一系列以retn结尾的指令,所有的这些Gadget组合起来就能完成特定的任务,比如调用VirtualProtect给指定的内存块添加可执行属性。

为了达到稳定利用的目的,要求选取的Gadget的地址是固定的,无论是什么时候,其指向的都是我们想要的指令。这里引入了ASLR的概念。

ASLR全称Address Space Layout Randomization,即地址空间格局随机化。ASLR使得加载程序时不再使用固定的加载基地址加载。该技术需要操作系统以及应用程序的双重支持,ASLR才能发挥正常的作用。支持ASLR的程序在PE头中会设置IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE标识表明其支持ASLR。

通过Visual Studio对项目属性的配置,可以使二进制文件支持ASLR:

ASLR主要影响一下几个部分,分别为:

1. 模块随机化

系统将PE文件映射到内存时,对其加载基地址进行随机化处理,这个地址在系统启动时确定,系统重启后会变化。如图所示,用Ollydbg加载一个应用程序,查看模块列表:

重启操作系统后再次查看,发现基地址全改变了:

2. 堆栈随机化

每次程序加载后,其内存空间中堆、栈的基址都会发生变化。于是内存中的变量所在的地址也会发生变化。

3. PEB/TEB随机化

从Windows XP SP2开始,PEB、TEB的地址不再固定不变。

不过,几乎很少简单有人用固定的地址去获取PEB、TEB指针,而是通过fs寄存器进行定位。

TEB可以用FS : [18h]获取

PEB可以从TEB偏移30h处获取

常用的绕过ASLR的方法有:

1. 攻击未启用ASLR的模块

虽然有映像随机化,但有可能进程中存在未启用ASLR的模块。 前面提到的ROP技术要求从一个固定的地址获取Gadget,如果进程中存在未启用ASLR的模块,那么就可以从那个模块获取Gadget了。 使用OD的OllyFindAddr插件可以快速找到进程空间中未启用ASLR的模块。

2. 堆喷射(HeapSpray)技术

虽然有堆栈随机化,不过HeapSpray技术将ShellCode布局到0x0C0C0C0C(或者其他指定的地址上,通常这个地址要比较大),并不会受堆栈随机化的影响。 其实,HeapSpray中使用ROP绕过DEP的时候,就使用了前面提到的“攻击未启用ASLR的模块”。 只是,HeapSpray把ShellCode布局在堆上。

3. 覆盖部分返回地址

映像随机化中,虽然模块的加载基地址发生变化,但是各模块的入口点地址的低位字不变,只有高位字进行了随机化处理。

对于地址0×12345678,其中5678部分是固定的,如果存在缓冲区溢出,可以通过memcpy对后两个字节进行覆盖,可以将其设置为0×12340000 ~ 0x1234FFFF中的任意一个值。

如果通过strcpy进行覆盖,因为strcpy会复制末尾的结束符0×00,那么可以将0×12345678覆盖为0×12345600,或者0×12340001 ~ 0x123400FF。

部分返回地址覆盖,可以使得覆盖后的地址相对于基地址的距离是固定的,可以从基地址附近找可以利用的跳转指令。

这种方法的通用性不是很强,因为覆盖返回地址时栈上的Cookie会被破坏。不过具体问题具体分析,为了绕过操作系统的安全保护机制需要考虑各种各样的情况。

4. Java Applet Spray

Java Applet中动态申请的内存空间具有可执行属性(PAGE_EXECUTE_READWRITE),类似HeapSpray技术,可以在固定的地址上分配滑板指令(如NOP)和ShellCode,然后跳转到那个地址上面去执行。 和常规的HeapSpray不同,Applet申请空间的上限为100MB,而常规的HeapSpray可以达到1GB。

5. JIT Spray

JIT (Just In Time Compilation) 即时编译,也就是解释器(比如Python解释器)。

主要思想是将 ActionScript代码中进行大量的XOR操作。然后编译成字节码,并且多次更新到Flash VM中,这样它会建立很多带有恶意Xor操作的内存块。例如,一个序列为:

var y=(0×11223344^0×44332211^0×4433221);

正常情况下被解释器解释为:

如果非常规的跳转到中间某一个字节开始执行代码,结果就是另一番景象了:

关于JIT的详细介绍,可以参考Pointer Inference and JIT Spraying以及Writing JIT-Spray shellcode for fun and profit,文章末尾会给出链接。

6. Tombkeeper在CanSecWest 2013上提出的基于SharedUserData的方法

从Windows NT 4到Windows 8,SharedUserData的位置一直固定在地址0x7ffe0000上。 从WRK源代码中nti386.h以及ntamd64.h可以看出:

#define MM_SHARED_USER_DATA_VA  0x7FFE0000

在x86 Windows上,通过Windbg,可以看到:

0:001> dt _KUSER_SHARED_DATA SystemCall 0x7ffe0000

ntdll!_KUSER_SHARED_DATA

+0×300 SystemCall : 0x774364f0

0x7ffe0300总是指向KiFastSystemCall

0:001> uf poi(0x7ffe0300)

ntdll!KiFastSystemCall:

774364f0 8bd4            mov     edx,esp

774364f2 0f34            sysenter

774364f4 c3              ret

反汇编NtUserLockWorkStation函数,发现其就是通过7ffe0300进入内核的:

0:001> uf USER32!NtUserLockWorkStation

USER32!NtUserLockWorkStation:

75f70fad b8e6110000      mov     eax,11E6h

75f70fb2 ba0003fe7f      mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)

75f70fb7 ff12            call    dword ptr [edx]

75f70fb9 c3              ret

其中11E6是NtUserLockWorkStation的服务号(ShadowSSDT中0x01E6的服务),通过Xuetr可以看到:

这样,在触发漏洞前合理布局寄存器内容,用函数在系统服务(SSDT / Shadow SSDT)中服务号填充EAX寄存器,然后让EIP跳转到对应的地方去执行,就可以调用指定的函数了。但是也存在很大的局限性:仅仅工作于x86 Windows上;几乎无法调用有参数的函数。

64位Windows系统上0x7ffe0350总是指向函数ntdll!LdrHotPatchRoutine。

HotPatchBuffer结构体的定义如下:

struct HotPatchBuffer {

ULONG   NotSoSure01; // & 0×20000000  != 0

ULONG   NotSoSure02;

USHORT  PatcherNameOffset;   // 结构体相对偏移地址

USHORT  PatcherNameLen;

USHORT  PatcheeNameOffset;

USHORT  PatcheeNameLen;

USHORT  UnknownNameOffset;

USHORT  UnknownNameLen

};

LdrHotPatchRoutine调用方式:

void LdrHotPatchRoutine (struct  *HotPatchBuffer);

在触发漏洞前合理布局寄存器内容,合理填充HotPatchBuffer 结构体的内容,然后调用LdrHotPatchRoutine。

如果是网页挂马,可以指定从远程地址加载一个DLL文件;

如果已经经过其他方法把DLL打包发送给受害者,执行本地加载DLL即可。

此方法通常需要HeapSpray协助布局内存数据;且需要文件共享服务器存放恶意DLL;只工作于64位系统上的32位应用程序;不适用于Windows 8(已经被修补)。

ASLR/DEP绕过技术概览的更多相关文章

  1. Linux_x86下NX与ASLR绕过技术

    本文介绍Linux_x86下NX与ASLR绕过技术,并对GCC的Stack Canaries保护技术进行原理分析. 本文使用存在漏洞代码如下: /* filename : sof.c */ #incl ...

  2. SafeSEH原理及绕过技术浅析

    SafeSEH原理及绕过技术浅析 作者:magictong 时间:2012年3月16日星期五 摘要:主要介绍SafeSEH的基本原理和SafeSEH的绕过技术,重点在原理介绍. 关键词:SafeSEH ...

  3. Windows Phone 8.1 开发技术概览 (Universal APP)

    前一阵真的比较懒 WP8.1 已经出来这么长时间了现在才更新BLOG让大家久等了,今天我先为大家介绍下 WP 8.1的开发框架,什么是微软所推崇的 Universal APP,以及我们要开发 Univ ...

  4. 【转】Intel RealSense(实感技术)概览

    Intel RealSense(实感技术)概览 1 Reply 版权声明:本文系本站作者自己翻译整理,欢迎转载,但转载请以超链接形式注明文章来源(planckscale.info).作者信息和本声明, ...

  5. BizTalk 开发系列(三十九) BizTalk Server 2009技术概览

    BizTalk Server 2009已经发布一段时间了,之前Beta版发布的时候也写过一篇文章<BizTalk Server 2009 Beta初体验>, 当时比较了2006 R2与20 ...

  6. Web安全--XSS现代WAF规则探测及绕过技术

    XSS现代WAF规则探测及绕过技术初始测试 1.使用无害的payload,类似<b>,<i>,<u>观察响应,判断应用程序是否被HTML编码,是否标签被过滤,是否过 ...

  7. Java SE技术概览 - Jave SE Platform at a Glance

    从学习到工作,使用Java有几年时间,一直没有好好端详一下她的“内涵”.无意中看到一个关于Java SE的概览图,发现Java中提供的API还挺系统全面,把她放到博客中,相信对于想系统了解Java技术 ...

  8. 转:Linux网络IO并行化技术概览

    转:http://codinginet.com/articles/view/201605-linux_net_parallel?simple=1&from=timeline&isapp ...

  9. 前端可视化建模技术概览,包括:GoJS

    我推荐使用的: 库 网址 备注 GoJS https://gojs.net/latest/samples/flowchart.html 推荐使用 相关文章: 前端可视化建模技术概览:http://le ...

随机推荐

  1. exynos4412—CMU裸板复习

    本章描述了Exynos 4412 SCP的时钟管理单元(CMUs).在Exynos 4412 SCP中,CMUs控制相位锁相环(PLLs),并为CPU.总线和单个ip的功能时钟生成系统时钟.它们还与电 ...

  2. x01.gamelab: An Tank 3D Model

    准备 1. 安装 OpenGL 及添加 python 引用参见我的置顶随笔. 2. 下载源代码: http://download.csdn.net/download/china_x01/1013310 ...

  3. Java编码算法和摘要算法

    编码算法 编码算法是将一种形式转换成等价的另外一种形式.主要是为了方便某种特定场景的处理. 字母如何在计算机中表示呢? 用ASCII编码 那中文字符如何在计算机中表示呢? 用Unicode编码 如何同 ...

  4. go VS NET 字符串操作能力

    今天拿golang 与 NET4.0 做了在字符串方面的性能比较,看看谁牛! 一.读取txt文本文件 GO的代码: readbuf, _ := ioutil.ReadFile(userFile) st ...

  5. 20155315实验四 Android程序设计

    实验内容 安装 Android Stuidio 学习Android Stuidio调试应用程序 实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim ...

  6. 20155322 2017-2018-1《信息安全系统设计》第九周 Linux命令:pwd命令学习与简单实现

    pwd命令学习 功能 Linux中用 pwd 命令来查看"当前工作目录"的完整路径. 格式 pwd [选项] 实例 用 pwd 命令查看默认工作目录的完整路径: 用 pwd 命令查 ...

  7. 2016-2017-2 20155322 实验三 敏捷开发与XP实践

    2016-2017-2 20155322 实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 实验知识点 敏捷开发(Agile Development)是一种以人为核心.迭代.循序 ...

  8. 【LOJ4632】[PKUSC2018]真实排名

    [LOJ4632][PKUSC2018]真实排名 题面 终于有题面啦!!! 题目描述 小 C 是某知名比赛的组织者,该比赛一共有 \(n\) 名选手参加,每个选手的成绩是一个非负整数,定义一个选手的排 ...

  9. Nginx入门篇(三)之虚拟主机配置

    一.虚拟主机概念 所谓虚拟主机,在Web服务当中就是一个独立的网站站点,这个站点对应独立的域名(也有可能是IP或者端口),具有独立的程序和资源目录,可以独立地对外提供服务供用户访问. 这个独立的站点在 ...

  10. AngularJS中Directive指令系列 - 基本用法

    参考: https://docs.angularjs.org/api/ng/service/$compile http://www.zouyesheng.com/angular.html Direct ...