mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
131 lines
5.7 KiB
Markdown
131 lines
5.7 KiB
Markdown
# ダブルフリー
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## 基本情報
|
||
|
||
メモリのブロックを複数回解放すると、アロケータのデータが混乱し、攻撃の扉が開かれる可能性があります。これは次のように発生します:メモリのブロックを解放すると、それはフリーチャンクのリスト(例:「ファストビン」)に戻ります。同じブロックを連続して2回解放すると、アロケータはこれを検出し、エラーをスローします。しかし、**その間に別のチャンクを解放すると、ダブルフリーのチェックがバイパスされ**、破損が発生します。
|
||
|
||
今、新しいメモリを要求すると(`malloc`を使用)、アロケータは**2回解放されたブロック**を返す可能性があります。これにより、2つの異なるポインタが同じメモリ位置を指すことになります。攻撃者がそのポインタの1つを制御している場合、彼らはそのメモリの内容を変更でき、これがセキュリティ問題を引き起こしたり、コードを実行させたりする可能性があります。
|
||
|
||
例:
|
||
```c
|
||
#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`を解放することでダブルフリーを引き起こします**(ファストビンの重複とも呼ばれます)。これにより、再割り当て時に重複したメモリアドレスを受け取る可能性が生じ、2つ以上のポインタが同じメモリ位置を指すことができます。1つのポインタを通じてデータを操作すると、他のポインタにも影響を与え、重大なセキュリティリスクと悪用の可能性を生み出します。
|
||
|
||
実行すると、**`i1`と`i2`が同じアドレスを取得したことに注意してください**:
|
||
|
||
<pre><code>初期割り当て:
|
||
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
|
||
<strong>i1: 0xaaab0f0c23a0
|
||
</strong><strong>i2: 0xaaab0f0c23a0
|
||
</strong></code></pre>
|
||
|
||
## 例
|
||
|
||
- [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)
|
||
- サイズ`0x70`を除いて、ファストビンサイズのチャンクしか割り当てられず、通常の`__malloc_hook`の上書きを防ぎます。
|
||
- 代わりに、`0x56`で始まるPIEアドレスをファストビンの重複のターゲットとして使用します(1/2の確率)。
|
||
- PIEアドレスが保存される場所の1つは`main_arena`で、これはGlibc内にあり、`__malloc_hook`の近くにあります。
|
||
- 特定のオフセットの`main_arena`をターゲットにして、そこにチャンクを割り当て、`__malloc_hook`に到達するまでチャンクを割り当て続けてコード実行を取得します。
|
||
- [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)
|
||
- Tcacheビンとヌルバイトオーバーフローを使用して、ダブルフリーの状況を達成できます:
|
||
- サイズ`0x110`のチャンクを3つ(`A`、`B`、`C`)割り当てます。
|
||
- `B`を解放します。
|
||
- `A`を解放し、ヌルバイトオーバーフローを使用するために再度割り当てます。
|
||
- 現在、`B`のサイズフィールドは`0x100`であり、`0x111`ではないため、再度解放できます。
|
||
- サイズ`0x110`のTcacheビンとサイズ`0x100`のTcacheビンが同じアドレスを指しているため、ダブルフリーが発生します。
|
||
- [Tcache poisoning](tcache-bin-attack.md)を使用してダブルフリーを利用します。
|
||
|
||
## 参考文献
|
||
|
||
- [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free)
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|