1

Are heap spray exploits possible, if the process we're attacking is a 64-bit process?

Naively, it seems like the 64-bit address makes it difficult to mount a heap spray: to fill all (or a significant fraction) of virtual memory, you'd need to spray an absolutely ridiculous amount of data into the heap. I realize that on 64-bit platforms, the virtual memory address space is really 48 bits, not 64 bits, but that still seems to be more than enough to make filling the entire virtual address space unlikely.

Therefore, naively, it seems like we might not need to worry about heap spray attacks against 64-bit processes. But is this conclusion correct? Are there clever ways of doing a heap spray even against a 64-bit process?

(Assume that the target process is using ASLR, as is standard these days.)

D.W.
  • 98,420
  • 30
  • 267
  • 572

2 Answers2

3

First, a small clarification: Classic heap sprays never needed to fill the entire virtual address anyway. They only needed to fill enough of memory to cover the range of uncertainty you have for the address of whether the shellcode will be. Thus, 100MB or so were enough.

The picture changed a lot with the advent of DEP, because one can no longer spray shellcode; now one must spray a ROP stack (for instance). You might think that ASLR also made heap spraying harder, but VirtualAlloc allocates at deterministic addresses even if ASLR is enabled (maybe it still does), which made predicting the address a lot easier. Finally, the 64-bit address space increased the amount of variability available to ASLR, which has the potential to make some heap spray attacks harder.

The biggest change is found in Windows 8, which made two major changes that will likely make heap sprays more challenging. First, HiASLR enables greater entropy for ASLR. On 64-bit platforms, HiASLR introduces a 1TB range of possibilities for the base of the heap. This makes it harder to predict the address of something on the heap. Second, Windows 8 makes allocations non-deterministic: when you allocate a object using the default allocator, the position that is used is randomized (it is no longer deterministic), introducing fine-grained randomization at the individual object level. Object-by-object randomization is not used for everything (only for the LFH allocator, which I think is only used for heap objects that are at most 16KB in size), but it will add an additional challenge.

That said, heap spraying may still be possible in some cases. The situation where heap spraying becomes useful is where we have partial knowledge of a pointer value (or where some object will be in memory), but not exact knowledge. In that situation, a heap spray can still be a useful technique to make the exploit reliable despite the lack of perfect predictability in that address.

For instance, one example is Ivan Fratric's exploit of 64-bit IE11, where he used a heap spray to make the exploit reliable. In that vulnerability, the attacker could trigger a write to address A+256MB, where A is the address of some heap object. Due to ASLR, we can't predict the value of A, and due to the 64-bit heap, we can't spray enough to fill all of the heap -- but Ivan noticed that in this case it is enough to spray around 256MB of data into the heap. This makes it likely that the address of a random heap object, plus 256MB, will land into the sprayed region.

So, as Ivan Frartic explains, heap spraying can still be useful for the attacker if "we can make a vulnerable application dereference memory at a valid heap address + a large offset" (for instance, imagine the buggy code do_something_with(a[i]), where i might be a offset that points past the end of the array). He gives another example of an earlier vulnerability that also had this form, to illustrate that this case is common enough.

Finally, 32-bit processes might be used in cases you wouldn't expect. For instance, even 64-bit IE on 64-bit platforms will use 32-bit child processes for each new tab, on Windows 8.1. Who knew?

Bottom line: No, we can't say that there's no need to worry about heap sprays against 64-bit processes. That was indeed too naive.

D.W.
  • 98,420
  • 30
  • 267
  • 572
0

As the post you linked nicely points out, heap spraying is a payload delivery technique. It is a method used to achieve reliable software exploitation, but it is useless without a vulnerability that can take advantage of it.

If you read your link carefully (or any other resource on heap exploitation), it doesn't say anywhere that you have to fill all (impossible) or a significant fraction of the virtual memory address.

What you need to be able to do in order to utilize this technique, is to be able to write data to a predictable address range on the heap. It can be few KB, it can be few MB, it can even be few GB.

Usually these predictable locations are acquired through other security issues that leak information about the process memory addresses.

Every software vulnerability is very unique. There are no one-size-fits-all exploitation techniques and nowdays in most cases you need to take advantage of multiple security issues in order to craft a reliable exploit.

That being said, the feasibility of heap spraying depends only on the level of the control you have over the process heap and it has nothing to do with the size of the process virtual address space.

So yes, given the right conditions, you can use heap spraying as payload delivery method during the exploitation of a particular vulnerability on a 64-bit architecture.

dkaragasidis
  • 241
  • 1
  • 7