mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 06:30:37 +00:00
6.8 KiB
6.8 KiB
Double Free
{% hint style="success" %}
学习与实践 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE)
学习与实践 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 分享黑客技巧。
基本信息
如果你多次释放一块内存,它可能会破坏分配器的数据并打开攻击的门。事情是这样的:当你释放一块内存时,它会返回到一个空闲块的列表中(例如“快速 bin”)。如果你连续两次释放同一块内存,分配器会检测到这一点并抛出错误。但如果你在两次释放之间释放了另一块内存,双重释放检查就会被绕过,导致数据损坏。
现在,当你请求新的内存(使用 malloc
)时,分配器可能会给你一个已经被释放两次的块。这可能导致两个不同的指针指向同一内存位置。如果攻击者控制了其中一个指针,他们可以更改该内存的内容,这可能导致安全问题,甚至允许他们执行代码。
示例:
#include <stdio.h>
#include <stdlib.h>
int main() {
// Allocate memory for three chunks
char *a = (char *)malloc(10);
char *b = (char *)malloc(10);
char *c = (char *)malloc(10);
char *d = (char *)malloc(10);
char *e = (char *)malloc(10);
char *f = (char *)malloc(10);
char *g = (char *)malloc(10);
char *h = (char *)malloc(10);
char *i = (char *)malloc(10);
// Print initial memory addresses
printf("Initial allocations:\n");
printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i);
// Fill tcache
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);
// Introduce double-free vulnerability in fast bin
free(h);
free(i);
free(h);
// Reallocate memory and print the addresses
char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10);
// Print initial memory addresses
printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2);
return 0;
}
在这个例子中,填充 tcache 以包含多个已释放的块(7)后,代码 释放块 h
,然后释放块 i
,再释放 h
,导致双重释放(也称为 Fast Bin dup)。这打开了在重新分配时接收重叠内存地址的可能性,这意味着两个或多个指针可以指向同一内存位置。通过一个指针操纵数据可以影响另一个,造成严重的安全风险和潜在的利用。
执行时,请注意 i1
和 i2
得到了相同的地址:
初始分配:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
d: 0xaaab0f0c2300
e: 0xaaab0f0c2320
f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
重新分配后:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
d1: 0xaaab0f0c2300
e1: 0xaaab0f0c22e0
f1: 0xaaab0f0c22c0
g1: 0xaaab0f0c22a0
h1: 0xaaab0f0c2380
i1: 0xaaab0f0c23a0
i2: 0xaaab0f0c23a0
示例
- Dragon Army. Hack The Box
- 我们只能分配 Fast-Bin 大小的块,除了大小为
0x70
,这阻止了通常的__malloc_hook
覆盖。 - 相反,我们使用以
0x56
开头的 PIE 地址作为 Fast Bin dup 的目标(1/2 概率)。 - PIE 地址存储的一个地方是在
main_arena
中,它位于 Glibc 内部,并靠近__malloc_hook
- 我们针对
main_arena
的特定偏移量来分配一个块,并继续分配块,直到到达__malloc_hook
以获取代码执行。 - zero_to_hero. PicoCTF
- 使用 Tcache bins 和一个 null-byte 溢出,我们可以实现双重释放情况:
- 我们分配三个大小为
0x110
的块(A
,B
,C
) - 我们释放
B
- 我们释放
A
并重新分配以使用 null-byte 溢出 - 现在
B
的大小字段为0x100
,而不是0x111
,所以我们可以再次释放它 - 我们有一个大小为
0x110
的 Tcache-bin 和一个大小为0x100
的 Tcache-bin,它们指向相同的地址。因此我们有一个双重释放。 - 我们利用双重释放使用 Tcache poisoning
参考
{% hint style="success" %}
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 telegram 群组 或 在 Twitter 上关注 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库提交 PR 来分享黑客技巧。