From be9d5a7ae8e31090dd2ed4f2522c7f202489b1dc Mon Sep 17 00:00:00 2001 From: CPol Date: Thu, 13 Jun 2024 21:46:34 +0000 Subject: [PATCH] GITBOOK-4359: No subject --- binary-exploitation/heap/house-of-orange.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/binary-exploitation/heap/house-of-orange.md b/binary-exploitation/heap/house-of-orange.md index c077bff71..0eee78d5c 100644 --- a/binary-exploitation/heap/house-of-orange.md +++ b/binary-exploitation/heap/house-of-orange.md @@ -19,7 +19,8 @@ Other ways to support HackTricks: ### Code * Find an example in [https://github.com/shellphish/how2heap/blob/master/glibc\_2.23/house\_of\_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc\_2.23/house\_of\_orange.c) - * The exploitation technique was fixed in this [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) so this is no longer working + * The exploitation technique was fixed in this [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) so this is no longer working (working in earlier than 2.26) +* Same example **with more comments** in [https://guyinatuxedo.github.io/43-house\_of\_orange/house\_orange\_exp/index.html](https://guyinatuxedo.github.io/43-house\_of\_orange/house\_orange\_exp/index.html) ### Goal @@ -30,19 +31,27 @@ Other ways to support HackTricks: * Overwrite the top chunk size * Libc and heap leaks +### Background + +Some needed background from the comments from [**this example**](https://guyinatuxedo.github.io/43-house\_of\_orange/house\_orange\_exp/index.html)**:** + +Thing is, in older versions of libc, when the `malloc_printerr` function was called it would **iterate through a list of `_IO_FILE` structs stored in `_IO_list_all`**, and actually **execute** an instruction pointer in that struct.\ +This attack will forge a **fake `_IO_FILE` struct** that we will write to **`_IO_list_all`**, and cause `malloc_printerr` to run.\ +Then it will **execute whatever address** we have stored in the **`_IO_FILE`** structs jump table, and we will get code execution + ### Attack The attack starts by managing to get the **top chunk** inside the **unsorted bin**. This is achieved by calling `malloc` with a size greater than the current top chunk size but smaller than **`mmp_.mmap_threshold`** (default is 128K), which would otherwise trigger `mmap` allocation. Whenever the top chunk size is modified, it's important to ensure that the **top chunk + its size** is page-aligned and that the **prev\_inuse** bit of the top chunk is always set. -To get the top chunk inside the unsorted bin, allocate a chunk to create the top chunk, change the top chunk size so that **top chunk + size** is page-aligned with the **prev\_inuse** bit set. Then allocate a chunk larger than the new top chunk size. Note that `free` is never called to get the top chunk into the unsorted bin. +To get the top chunk inside the unsorted bin, allocate a chunk to create the top chunk, change the top chunk size (with an overflow in the allocated chunk) so that **top chunk + size** is page-aligned with the **prev\_inuse** bit set. Then allocate a chunk larger than the new top chunk size. Note that `free` is never called to get the top chunk into the unsorted bin. The old top chunk is now in the unsorted bin. Assuming we can read data inside it (possibly due to a vulnerability that also caused the overflow), it’s possible to leak libc addresses from it and get the address of **\_IO\_list\_all**. -An unsorted bin attack is performed by abusing the overflow to write `topChunk->bk->fwd = _IO_list_all - 0x10`. When a new chunk is allocated, the old top chunk will be split, and a pointer to the unsorted bin will be written into **\_IO\_list\_all**. +An unsorted bin attack is performed by abusing the overflow to write `topChunk->bk->fwd = _IO_list_all - 0x10`. When a new chunk is allocated, the old top chunk will be split, and a pointer to the unsorted bin will be written into **`_IO_list_all`**. The next step involves shrinking the size of the old top chunk to fit into a small bin, specifically setting its size to **0x61**. This serves two purposes: -1. **Insertion into Small Bin 4**: When `malloc` scans through the unsorted bin and sees this chunk, it will try to insert it into small bin 4 due to its small size. This makes the chunk end up at the head of the small bin 4 list, facilitating the manipulation of the forward and backward pointers. +1. **Insertion into Small Bin 4**: When `malloc` scans through the unsorted bin and sees this chunk, it will try to insert it into small bin 4 due to its small size. This makes the chunk end up at the head of the small bin 4 list which is the location of the FD pointer of the chunk of **`_IO_list_all`** as we wrote a close address in **`_IO_list_all`** via the unsorted bin attack. 2. **Triggering a Malloc Check**: This chunk size manipulation will cause `malloc` to perform internal checks. When it checks the size of the false forward chunk, which will be zero, it triggers an error and calls `malloc_printerr`. The manipulation of the small bin will allow you to control the forward pointer of the chunk. The overlap with **\_IO\_list\_all** is used to forge a fake **\_IO\_FILE** structure. The structure is carefully crafted to include key fields like `_IO_write_base` and `_IO_write_ptr` set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code (e.g., the `system` function) can be executed. @@ -50,7 +59,7 @@ The manipulation of the small bin will allow you to control the forward pointer To summarize the remaining part of the technique: * **Shrink the Old Top Chunk**: Adjust the size of the old top chunk to **0x61** to fit it into a small bin. -* **Set Up the Fake \_IO\_FILE Structure**: Overlap the old top chunk with the fake **\_IO\_FILE** structure and set fields appropriately to hijack execution flow. +* **Set Up the Fake `_IO_FILE` Structure**: Overlap the old top chunk with the fake **\_IO\_FILE** structure and set fields appropriately to hijack execution flow. The next step involves forging a fake **\_IO\_FILE** structure that overlaps with the old top chunk currently in the unsorted bin. The first bytes of this structure are crafted carefully to include a pointer to a command (e.g., "/bin/sh") that will be executed.