mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-24 21:53:54 +00:00
GITBOOK-4359: No subject
This commit is contained in:
parent
c0343aa3d5
commit
be9d5a7ae8
1 changed files with 14 additions and 5 deletions
|
@ -19,7 +19,8 @@ Other ways to support HackTricks:
|
||||||
### Code
|
### 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)
|
* 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
|
### Goal
|
||||||
|
|
||||||
|
@ -30,19 +31,27 @@ Other ways to support HackTricks:
|
||||||
* Overwrite the top chunk size
|
* Overwrite the top chunk size
|
||||||
* Libc and heap leaks
|
* 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
|
### 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.
|
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**.
|
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:
|
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`.
|
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.
|
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:
|
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.
|
* **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.
|
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.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue