Closed gfelber closed 6 months ago
So, the high-level idea of how the technique works is (more like how the PoC works):
The fantastic thing about this technique is that it requires no free at all (just like the original house-of-orange technique). And I really like the idea of combining tcache-poisoning and sysmalloc free chunk creation idea.
I'd love to merge the technique. But before I merge it, can you please make the following changes?
And all the users will appreciate it if you could explain a bit more about why this technique works (either in the comment or in prints) :D
- what are the checks/constraints, ...
Understandable i will try to make the main concept behind this technique easier to understand (and link/explain relevant checks in glibc).
- For the arbitrary allocation to work, the first largebin (unsortedbin) is not needed. ....
So the largebin (unsortedbin) actually serves three purposes:
If the largebin (unsortedbin) is removed a negative and positive OOB (or an unsafe edit) would be required to recreate this technique.
If this is desired i would like to know your opinion what Vulnerability the PoC should focus on:
So the largebin (unsortedbin) actually serves three purposes
Yeah, I understand that the first unsortedbin allocation is needed and also good to have in many cases (e.g. heap fengshui, info leak). But in my personal opinion, it is not the main point of the technique but an add-on. Depending on one more primitive for an add-on does not quite follow how2heap's philosophy of teaching one technique at a time. So yeah, I still prefer the minimalist approach if you are also OK with it.
If the largebin (unsortedbin) is removed a negative and positive OOB (or an unsafe edit) would be required to recreate this technique.
May I ask why? I might be missing something, but I think it is still possible if you OOB from the chunk right above the second created tcachebin, right? (Assuming you know the heap address)
So, if it can be achieved with only overflow (positive OOB), I prefer the minimalist approach. If it cannot, please let me know, we can work on merging the current one.
May I ask why?
One interesting aspect about the current PoC is that it only requires a positive OOB on the newest initialized chunk. Generally speaking there is no (simple) way to allocate a chunk on a lower address than the newest initialized chunk (without using free).
This is how the technique would look like on a newly grown heap map:
-------------------------
| NEW | <- initial malloc
| |
-------------------------
| TOP | <- top chunk (wilderness)
| SIZE (0x2150) |
| ... |
------------------------- <- end of current heap page
-------------------------
| NEW |
| AAAAAAAAAAAAAAAAAAAAA | <- positive OOB (i.e. BOF)
-------------------------
| TOP | <- corrupt size of top chunk (wilderness)
| SIZE (0x150) |
------------------------- <- still page aligned
| ... |
------------------------- <- end of current heap page
-------------------------
| OLD |
| AAAAAAAAAAAAAAAAAAAAA |
-------------------------
| TCACHE | <- old top got freed because it couldn't be merged
| |
-------------------------
| FENCEPOST | <- just some architecture depending padding
------------------------- <- still page aligned
| ... |
------------------------- <- end of previous heap page
| NEW | <- new malloc
-------------------------
| TOP | <- top chunk (wilderness)
| ... |
------------------------- <- end of current heap page
There are two ways to trigger a UAF in the freed chunk we either need to be allowed to edit an old chunk (and also have an positive OOB in the edit function) or have a negative OOB in the new chunk.
I believe just being allowed to postive OOB in the newest chunk would be preferable (and more common), but I'm fine with both approaches.
Here is an overview table to compare the complexity between the current and minimal approach:
current | minimal | |
---|---|---|
mallocs | 7 | 6* (5) |
unqiue sizes | 3 | 3 |
*to make the PoC more reliable we need to malloc and probe the current top chunk size, this should be predictable in an actual exploit and therefore, can be removed to get 5 mallocs instead
WIP versions of both: current.c minimal.c
I hope this helps making a decision which option is preferred
It might also be sensible to add a PoC that simply demonstrates the sysmalloc _int_free trick, because it has potential to be combined with other techniques. If this is desirable i don't mind including an additional short PoC.
Thank you for crafting two versions of the technique. I think the minimal poc looks great and would love to merge it.
It might also be sensible to add a PoC that simply demonstrates the sysmalloc _int_free trick, because it has potential to be combined with other techniques. If this is desirable i don't mind including an additional short PoC.
I totally agree with this and would love to see such a PoC.
Exchanged house_of_tangerine.c with the minimal version.
Also added a nice showcase of the sysmalloc _int_free()
trick in sysmalloc_int_free.c.
Made a mistake with the fencepost location, it's acutally after the freed top_chunk (not before, as seen in the diagram before, fixed it now)
It seems you have been updating it constantly. Please let me know when you think it is ready to merge :D
Yeah should be ready to merge, the last changes were some minor stuff. If this version is good with you it's good with me
The current version looks good to me! Thank you for the effort!
sry to bump this put i saw you modified sysmalloc_int_free.c https://github.com/shellphish/how2heap/commit/ae4dbf558203d72296e443e326d885b0f7994e63 https://github.com/shellphish/how2heap/commit/4ed6f1954565ed12e23aa84931ed9c36d00a3d8b
<< #define MALLOC_ALIGN 0x10L
>> #define MALLOC_ALIGN (SIZE_SZ*2)
i believe this happened because you merged the 2.23 example with the others, but this breaks the showcase for x86 (32 bit), so maybe revert theses changes if possible? in some earlier heap version glibc changed their heap alignment on x86 (32bit) to always be 0x10 (and not SIZE_SZ*2) https://elixir.bootlin.com/glibc/glibc-2.39/source/sysdeps/i386/malloc-alignment.h#L22 this wasn't true for 2.23, that's why this version was slightly different https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/malloc.c#L353
https://github.com/gfelber/House_of_Tangerine