CTFが12月30日から1月4日まで開催され、zer0ptsで参加しました。全体で4786点を獲得して1位でした。解いた問題のwriteupを簡単に書きます。welcomechain64-bitのELFとlibc-2.27が渡されます。leakしてシェルを取るだけです。payload)sock.interactive()やるだけ。instant_httpserver64-bitのELFとlibc-2.27が渡されます。instant_httpserver簡易的なHTTPサーバーで、リクエスト用のバッファに単純なスタックオーバーフローがあります。接続ごとにforkしており、BOFがnull終端でなくて良いのでcanaryをリークできます。writeに飛ばして出力を見ることでリークしました。4445)sock.send(payload)sock.interactive()やるだけ。babyheap64-bitのELFとlibc-2.27が渡されます。malloc+writeにあたる操作を4回すると即座にプログラムが終了してしまいます。leakとシェル取得をする必要があります。leakのためにaddは使いたくないので、stdinを使います。scanfでデータを読み込むのでGOTのアドレスが書き込めないのですが、stdinのバッファには残るので、それをOOBで読みます。poisoningしました。one_gadget))sock.interactive()これ書きながら思ったけどscanf使って直接/bin/sh起動した方が楽そう。想定解が気になるところ。pokebattle64-bitのELFとlibc-2.27が渡されます。leakして/bin/shを起動するだけです。payload)fight()sock.interactive()やるだけ。DownloaderLogpcapファイルが渡されます。HTTPでELFを落としているのでIDAで解析すると、特定の機械語領域を0x19でXORしています。unpackスクリプトを書いて展開後のELFを保存します。f.write(binary)これをIDAで解析すると普通にフラグを出力している処理がありました。once_againWin7SP1x64のメモリダンプが渡されます。registry?としか書いておらず何をすれば良いのか分かりません。レジストリだし問題タイトルにonceとか入ってるし自動起動のRunOnceかなーとなんとなくおもってprintkeyしたら、フラグがrot13されて書かれていました。pgspgs{i0yng1y1gl_1f_hf3shy_zrz0elnanylf1f}rot13を戻すとフラグっぽくなるのですが、よく見るとprefixが間違っているので直して送ったら受理されました。passwordWin7SP1x64のメモリダンプが渡されます。password)とあったのでとりあえずユーザーaliceのパスワードを調べます。普通にhivelist+hashdumpで取ったハッシュをcrackstationに投げたらパスワードが平文で降ってきました。それのmd5を取って後から配布されたzipファイルを展開するとフラグが出てきます。passwordと同じメモリダンプです。catz...とあったのでieの履歴や自動補完で保存されたパスワードなどを調べましたが何も出ませんでした。なんやかんやを試してるうちに突然頭の中でcatz-->mimikatzという謎変換がされてmimikatzを使ってみることにしました。WORKGROUPメモリ・ディスクダンプ系は個人的に好きなのでいっぱいあって楽しいです。0.elfARM何も分からん。ghidraで読むとgetsでBOFがあります。getsでシェルコード書き込んでmprotectで実行可能にしようと思ったのですが、私のカニ味噌以下の脳味噌ではgetsが終わった後に別のgadgetに移れませんでした。gadgetをたくさん探してつなぎ合わせて誤魔化します。gadgetは下のやつらです。NULL);ですが、getsが動かせないので/bin/shをスタックに置きます。r1の2つのgadgetでr0にspを入れます。r6;で取り出される部分に当たります。gadgetが実行されます。p32(rop_swi_0)sock.recvline()sock.sendline(payload)sock.recvline()sock.interactive()黒魔術してしまいましたが、勉強になりました。ScrambleMeBackgo製のバイナリが渡されます。ただでさえgoは書かないのにgo製のバイナリとか渡されても意味分からんのですが、筋肉で解析しました。IDAで見るとScrambleMeと同様に何かしら処理をした結果がg0l4n6_15_g00dかを調べているのですが、それを出力する代わりにフラグファイルを読み込んで出力するようになっていました。したがって鍵を解析する必要があります。IDAで読みつつgdbで止めて、各変数や関数の意味を調べたところ、次のような処理をしていることが分かりました。outputこのoutputがg0l4n6_15_g00dになれば良いです。tableはバイナリ中に書かれています。いい感じに鍵を探索するスクリプトを書いて、結果をサーバーに送ればフラグが降ってきます。exit()勉強になりますね。goバイナリの解析手法を知らないのですが、どうやって解くのが想定だったのでしょうか。MyInstructionsC++製で最適化されたバイナリが渡されます。VMの構造は割と単純なので、目力で読んで逆アセンブラを書きます。print('\n'.join(disasm(code)))機械語はハードコーディングされてるので逆アセンブラに投げます。0x42007332入力したフラグがそのままレジスタ(reg0〜reg7)の初期状態になります。reg0からreg6は単純なxor等を使っているのでそのままz3の式に落とせます。reg7はループを使ってい生成しているのでそのままz3の式には変換しにくいです。読むとreg7はループ回数に影響しないので、pythonでエミュレートして操作前後での差分を取ります。passあとはz3にぶち込むだけ。breakちゃんと解が一意に定まりました。できたVM問という感じで面白かったです。EasyShellcodex64のシェルコード問です。20バイトだけシェルコードを読んだあとレジスタを0にし、raxを使ってジャンプします。20バイトもあれば大して工夫せずにシェルが起動できるので起動します。sc)sock.send(payload)sock.interactive()終わり。全体的に良問が多くて新年早々楽しめました。CTF初開催&4日間の運営ということで大変だったと思います。運営の皆さん、ありがとうございました。Writeup月別アーカイブはてなブログをはじめよう!ptr-yudaiさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。