So, there are some prerequisites that one needs to have in order to get this exploit. These are what are BootROM, NOR, malloc()
, NULL
and heap.
About BootROM you can read here. Briefly speaking, it’s a Read Only Memory (thus ROM, not to be confused with RAM which stands for Randomly Accessed Memory, i.e. RAM and refers to the chip that’s being freed of any charge when the power is off). ROM only means that this part of the device cannot be in any way modified once it was produced: neither by the user, not by the manufacturer himself. Mobile devices use ROM to store the first step of CPU launch.
Heap. This one word can describe two different notions. One, probably familiar to the most programmers, is the data structure that looks like this:
The second definition and the one relevant in this article is best described here. In short, each process is usually allocated some space in RAM (see above). Part of this RAM space is used for code instructions that are being sent to PC and part - for data that the program needs. For example, whenever a program needs to store a string or an integer, it’s requesting some space with malloc()
, alloc()
, realloc()
calls. Whenever it’s done with this data, it calls free()
function. The heap has its limits, it cannot store the data infinitely. Once the heap is written to to its full potential, any call to malloc()
will return NULL
. If we were to translate this to a human-digestible language, it would sound like this: “Hey, dude, have a heart! I am full! Go to the stack, it’s obviously doing nothing there”. Well, it’s what it usually would say when a healthy system is in question. But this is when alloc8 comes into play with iOS BootROM.
This one is about malloc()
. Looks like this function never returns NULL
, even when it should. In C language in the case when this function is unable to do its job, it returns NULL and the developer can handle that case properly [2]:
void *pointer = malloc(size);
if (pointer == NULL) {
// handle error
} else {
// pointer is valid, continue
}
But in S5L8920 BootROM (Read Only Memory) that was vulnerable to alloc8
, it returned 0x8
in these cases. So, if one knew about this tweak, one would alter the check above like that:
void *pointer = malloc(size);
if (pointer == 0x8) {
// handle error
} else {
// pointer is valid, continue
}
It’s not a proper way, of course, when malloc()
returns a real 0x8
address (if that’s even possible). On Windows machines (at least, a while ago) kernel space was shared between all the processes on the system and started from 0x0
address always, while user-space processes start from 0x4000000
(virtual address) usually. This was one of the reasons that those two famous exploits were making a fuss.
Let’s get back to our RAM. As the alloc8 exploit author states:
This is a bug in the implementation of the heap itself.
So, what’s the big deal? So, the malloc()
returns some garbage, big deal. How can this be useful for the attacker?
References
[1] Write-up for alloc8 by the author of the exploit.