CTF Zone Quals 2019 Writeup

TSG Advent Calendarの5日目の記事です。昨日は、うらさんの JavaScript じゃなくても GitHub Pages で動かしたい - Qiita でした

adventar.org

開催一ヶ月くらい前につばめくんが海外オンサイト行きてえし、これ行けるんちゃう?みたいな話をした結果、真面目に参加しようという話になりました。開催数日前にDEFCON Quals Qualsであることが発表されたのでどうなんやろなーと思っていましたが、ギリギリ10位に入ったので良かったです。

TSG Advent Calendarを埋めるために、ブログにするほど特筆するべきことがあるわけではないんですが、writeupを書きます(一部僕が解いたわけではないが、楽しかった話をコメント)

Agents

AES OFBで暗号化した何かしらの文が渡されて、HQにその暗号文を持っていくとありがとうと言われる。それだけ。OFB(Output Feedback Mode)ということは、暗号化された状態で平文の各ビットを適当に反転することができる。

暗号文は全体で2650ビットくらいあったので、とりあえず、各ビットを反転していくと、JSON corrupsedと言われる場合、errorでそもそも落ちる場合、特に何も言われない場合、そして、なんか信じてもらえて謎の文を返してもらえる場合に行き着く。

Thank you. HQ said that I can rely on you. Here is top secret message. It is encrypted with public RSA key contained in message that you gave me. Please deliver it to HQ as soon as posible.  90f21501ac7329ae0dd3002c81970b0971ea880669fb1557dbde34d25894352d969f45a295c54a3f3bb3f7ff0a1b47b80c1972aac9597d662c85914a40cd60d5eea0f3859a1d0d2832fe8adcd53e2d8134da0f858a022b5a6cba45b785e526927c84273b74449bd467f2ea1e72f1ca6d9543fe02f33df1d7e1fda346ae8c6a92

これは答えじゃないらしい。どうも、中身をよくしらないが、HQに送りつけているのはRSAの鍵と自分が信じていい人間かという情報らしい。またJSON corrupsedといわれている以上JSON形式なんだろう。errorが起こるのは、辞書型キーを破壊した場合かななどのことが考えられ、以上からどういう構造をしているJSONであるかも想定がつくので(数字が並んでいるところは上位ビットを破壊すると、JSON corrupsedになるが、下位ビットを壊しても怒られはしない)、RSA公開鍵のeを1に書き換えてやればいい

Easy VM

MS-DOS executable, MZ for MS-DOSなバイナリ、dosboxとかいうエミュレータで動く。動かすと、ファイルを受け取って正しいかどうか判定するらしい。

適当にリバーシングすると、判定関数っぽいものがたくさんあることが分かる。また、GHIDRAではうまくback referenceできなかったが、flagかどうかの判定したら、出力するようなので、とりあえずflag判定関数を満たすようなファイルを作る。

判定関数とは言っても、よく見てみると全部各バイト=で判定しているだけなので、objdumpの出力を雑にパースして比較先の値をとってくればいい

Learning The Ropes(& fixed)

わけわからんマシン(IBM S/390)の上でLinuxが動いていて、その中のユーザーモードで、問題のバイナリが動いている。JP3BGYがgdbLinuxに入れてくれたのでその上で解析した。

バイナリ自体は、読めないが大して大きくない。頑張って解析していると、baなんとかが、branchであったり、stmtがstore multipleで、関数のプロローグとして使われることだったり、lmgがl系がロード命令だったりすることが分かる。また、r14がlink用アドレスで、br %r14が、多くの場合retであることや、r2...r5の順に関数の引数が前から入っていることもわかる。大体これくらいで十分だった。

それらをもとに、バイナリを解析すると、

  • まず名前を受け取る(snprintf_chkだが、リークさせることができる)
  • 次に謎に文字列を受け取る(ここでHELL YEAHと入力すると先にすすめる、これは文字列同士の比較命令clstとかいう謎命令で行われる)
  • 数字を受け取って、その分だけ文字を入力できる(はず)(ここでバッファーオーバーフローできる)
  • また、別途、libc_csu_initっぽい場所も見つけることができる。
  • canary, RELRO, PIEだが、とりあえずsnprintfで各種アドレスとcanaryがリークできる。あとはどうやって、シェルをとるかだが、今回のアーキテクチャに関連して少し面白いのはこの部分である。

main関数の関数エピローグが、

272      d3c:   eb 6f f2 00 00 04   lmg %r6,%r15,512(%r15)
273      d42:   07 fe               br  %r14

であることを考える。lmgはload multipleで、メモリの上の$r15 + 512の位置を前から8バイトずつr6からr15まで(一命令で)入れていく。そしてbr %r14 でr14レジスタの中に入るアドレスにbranchする(つまり、r14にload multipleで入る値がある場所が所謂return addressの格納されている場所ということになる)。

つまり、このload multipleの範囲にあるメモリを適当にいじることで、r6-r15のレジスタまで好きに設定できる。つまり、libc_csu_initを使えば(各種アドレスたちがリークされているので)、system("/bin/sh") ができる。

まあ問題は、デバッグがしんどいことなんですけどね。x86でないアーキ問、多少読みにくいのは別に良いとしても、デバッグがとってもしんどい、gdbもところどころバグってない?(step実行だとbranchがうまくいかなかったんだけど)という。終わり

その他

Tic Tac Toe

もう一個のpwnの問題。kirbyさんと雑に会話したりしてスマブラをしていたら、kirbyさんが解いてくれました。去年から伏線があったんですが、成長著しいですね

Memology

Recon(は?)をする問題。貢献しようという気力はあったのに、無貢献だった(dostoevskyは許さん)。いやこれの特筆するべき事項は、そこではなくて、hideo54とhakatashiはreconの天才であることで(なお、hakatashiはinstagramのストーリーがどこから見れるかを知らなかった)、これをネットの片隅に書いておきたかった。

Welcome to CTFZone!

hakatashiにボタン連打で負けました。ちなみに、TSGはこの問題のfirst blood(ぇ

まとめ

集まってやったのでわいわいできてよかった。わいわいしていると、ようわからんくてしんどくなってきたときにもモチベが続くので良い。多分10位以内なので、オンサイトいけると思うんですけどどうなんですかね〜

明日は、taiyoslimeさんで「たぶんライブコードゴルフの諸々について(実用言語編)」らしいです