ソロ。30位。今回はちゃんと点数集める方向でやってみよう…と途中まで思ってやってる感じだったので、ちょっとそれにしては、なイマイチ感。
なんかエスパー力検定みたいなオーラがそこらじゅうから流れてたなあ感。
Easy Cipher / Welcome to SECCON / Get the key.txt
なんか簡単だった。
SECCON Wars
いきなりヘンな問題をやる。動画の中に QR コードが大部分隠されて流れている。人力とコードをほどほどに組み合わせてこんな画像を作って、あとは手でテキストファイルして、コードで綺麗な画像にして、 Android で読んだ。
Shuffle / Choose the number / Reverse it
覚えてないけど簡単。
Holy shellcode
UTF-16LE で表現したヘブライ語で shellcode 作れと。大変時間かかったけど、面白かった。ヘブライ語はなんかこの文字の後にはこの文字が来れないとかあるみたいで、そのへんのヒントが
http://hebrew.pwn.seccon.jp/nikud/hebrew-utf16le.html
にあった。詳細は覚えてないし、そのへんの仕様をきちんと把握していたかは謎。
8年前くらいに作った
http://shinh.skr.jp/binary/x86_ops.txt
を適当に参照しながらやる。ちょっと悲しくなるくらいまともに使える命令がない。 xchg %eax, %XXX が全て使えるのでどう見ても役に立つんだけど、これをするとヘブライ語的な理由で後に add $XXXXXXXX, %eax がついてくるので、 EAX がぶっこわれる。まあでも EAX を好きなレジスタに送ることは…できる。一度だけ。
では EAX に好きな値を作れないとキツいぞ…ということで色々やってると、 0 で初期化できる命令列を作れた。なんと 22 byte 5 命令で、やっと AL 以外をクリアできる。
and bl, bh mov eax, 0xd4fb2f05 add eax, 0xfb3005d0 sub eax, 0xd5fb39fb add eax, 0x05d005d0
AL はまあ操作するオペレーションが十分にあるので、 0-255 は作れるぽかった。メモリ書き込みは stos しか見つからなかったが、 EDI から EBX を引くことはできるので、 EDI をポインタにして書いてくことはできそうだー。
というわけで shell code 作成。なのにそこからが動かないcodered動かない… /bin/sh は動いてるのに、 cat したら fork できんと言って切られる。たぶんリソース制限かなんかが厳しいのかなぁと。 python とか perl 動かしてみたり、色々試して、 open とかする shellcode 書くのは面倒だなぁと思いつつ、 /bin/cat keyword.txt を試すと動いた。
うーんなんのための制約だったのかな。これを含めて exploit は全て相手の環境を推し量る時間がふんだんに必要だったのが残念。あとこの問題はヘブライ語の仕様とか、表が色わけしてあってヒントになってくれてるんだけど、しかし明確に教えてくれない理由はなんなんだろうか…とか。
とはいえこの問題は他と比べて、出題者技術的にがんばったなー感がして、大変良かった。
jspuzzle / REA-JUU WATCH
jspuzzle はこんなの楽勝…と思ってたがなぜかはまっていた。 Holy shellcode 終わって、寝る前にメシ喰ってる間に、アホな見落しに気付いて、頭の中で解ける。
REA-JUU はこういうのやる気おきないなあとポチポチやってたら解けた。
全体的に眠くてしょうがない日だった。
Advanced RISC Machine
ARM 。うーんこのバイナリなんだろうなあ…と思いつつ、環境がわからんので、 Linux でロードするプログラムを作って qemu で動かす。 SVC の付近のレジスタ操作から、 SVC の規約が微妙に Linux と違うなーと思ってたので、そのへんはローダで命令書き換えて対処。
exploit はまあつまんないくらいすぐ見つかるので、 shellcode を書く。できたなーと思って動かすも向こうでは動かない。うーん qemu+オレオレローダとはページの設定とか色々違っても不思議はないなあ…とか思いつつ、元々コードがあるところじゃないところにコードを置いてみたりすると、なんか少し動いてる。
うーんまあ instruction cache フラッシュしてないしなあ…とか思いつつも、あれやこれや。なんか open と write ははっきり動いてて、 open が -1 でない値 (そしてその値は 3 ではない) を返してるのははっきりしてるのに、 read が全然動かない。しょうがないから…と、元々あるコードの getchar を使って読んでやると flag が読めた。なんじゃらほい。。
途中で、 SVC の引数いじったりして syscall の種類を調べてる時のエラーメッセージから、 GDB 付属の simulator だと気付く。 instruction cache とかは実装してないとかコメントで書いてあるけど、どうなってたんだろうな… FD が 3 以外返してたから、なんか改造はされてたんだろうけど。
Decrypt it (Easy)
mtime 見ると srand に渡す引数がわかるという話。
と思ったら2面があった。なにやら数学的に意味がありそうな話だ!でもどうせ平文の最初は SECCON{ だろう、うん3つある暗号文の最初は SECCO だ。あとは N{ と } を固定して全探索…数学はどこへ。
Japanese super micro-controller
SH 。ということは、どうせこれもシミュレータだろう、あたりー。今回はラクちんだなーしかもまたつまんないくらい exploit 自明だなーと shellcode 作る、手元で動く、向こうで動かない。
またかー。
なんか SH の方は、どうもコード空間にコピーしたコードが一切動いてないような感じ。謎だなぁ困ったなぁと思うが、困っててもしょうがないので、自分で一切コード書かず、 ROP だけで処理する感じで対処。なんか ROP に便利な感じのものがいろいろあったので、まぁそういう意図だったのかな…しかしわざわざシミュレータのコードに手を入れるとか、そういうとこだけ工夫するような運営かな…不明。
あと ARM 同様 FD が乱数になってた。かえり値をちゃんと持ちまわるのはちょっと面倒だったので、単に適当な数字をたくさん試すコードを何度かサブミットしてるうちに通った。
まぁ GDB のシミュレータだとわかれば楽勝ですよ。
Let's disassemble
エスパー。エスパーだなぁ、 x86 じゃないなぁ、 CISC だけどさすがに英語圏の人が参加してるから z80 とかそういうのじゃないよねえ。と思いつつ、色んな CISC を試し、 Java bytecode とかも検討したあと、 z80 だと判明する。がー。
だいたい objdump が前提だよなあこれ。あと、 00 が来ると何かえせばいいのかわからなかったんだけど、まぁ 100 回のうちに来ない時にクリアできた。意味不明だ…
ROP: Impossible
頑張ってみたけど解けなかった問題も書いてみよう。これが筆頭、というかこれは解きたかったんだけど、時間勘違いしてて、どう考えても解けない時間しか残らなかったので、 Let's disassemble 見てたのだった。
jmp/call で chain を作るーて趣旨だと思うんだけど、そうだとすると一度やってみたかったんだよな。結構時間をかけてバイナリ内を調べて、使えそうな材料は色々あるんだけど、 call で飛んだ先で、余計なものがスタックにつまれすぎてて、大変むずかしそうに見えた。