問題
解いてみた
バッファオーバーフローの問題です。
ソースとプログラムが配布されているのでダウンロードします。
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <signal.h>
# define FLAGSIZE_MAX 64
char flag[FLAGSIZE_MAX];
void sigsegv_handler(int sig) {
fprintf(stderr, "%s\n", flag);
fflush(stderr);
exit(1);
}
void vuln(char *input){
char buf[16];
strcpy(buf, input);
}
int main(int argc, char **argv){
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
exit(0);
}
fgets(flag,FLAGSIZE_MAX,f);
signal(SIGSEGV, sigsegv_handler);
gid_t gid = getegid();
setresgid(gid, gid, gid);
if (argc > 1) {
vuln(argv[1]);
printf("Thanks! Received: %s", argv[1]);
}
else
printf("This program takes 1 argument.\n");
return 0;
}
flag.txtが置かれていてそれを頑張って表示する問題ということをとりあえず理解しました。
サーバにアクセスしてみます。
該当のflag.txtあったので一応catしてみましたが、ダメでした。
引数がなければ何もせずに終了。
引数があればそれを表示して終了。
ということが分かりました。
ソースを見てみるとsigsegv_handlerを呼び出せばflagが表示されそうな雰囲気です。
これがどこから呼ばれるかというとmain内にあります。
C言語は基本構文くらいはわかりますが、そんなに詳しくないです。
ということでsignalが何かわからなかったので検索しました。
C言語関数辞典 - signal
非同期で動く関数で第1引数のイベントが発生したときに第2引数の処理を行うものらしいです。
第1引数を見てみるとSIGSEGVと書いていました。
調べます。
SIGSEGV | Programming Place Plus C言語編 標準ライブラリのリファレンス
例えば、ヌルポインタを使ったアクセスや、配列の範囲外をアクセスすることなど。
だそうです。
入力した文字列がどのように処理されるか確認します。
配列16にコピーしているので16文字より長い文字を入力したら配列の範囲外にいけそうです。
んー、ダメでした。
もっと長い文字列を入れてみます。
できた。
ちょっと謎が残るので何文字あればflagがでるのか検証してみます。
まとめると
文字数 | 結果 |
---|---|
1文字~23文字 | そのまま表示される。 |
24文字~27文字 | Segmentation fault (core dumped) |
28文字~ | flag |
となります。
数字ではなくアルファベットでもやってみます。
同じですね。。。
Segmentation fault (core dumped)っていうのも範囲外のメモリを見たときに発生するそうです。
SIGSEGVと意味的には一緒な気がします。違いはよく分かりませんでした。。。
せめて17文字からSegmentation fault (core dumped)が発生するなら意味わかりますが、17文字から23文字までは配列超えてるのになんで許される?
そしてSegmentation fault (core dumped)とSIGSEGVは何が違う?
この謎わかる人いたら教えてください。