SECCON Beginners 2022 writeup
昨年までKUDoSで参加してましたが、
今年はソロ参加してました。(team:Shinra Company)
結果は19位で普段やらないジャンルも挑戦できてとても良かった。
目次
misc
phisher
打ち込んだ文字列をとあるフォントで画像出力し、それを再度画像から文字列として認識させる。
この時に’www[.]example[.]com’に出てくる文字列を使用せずに’www[.]example[.]com’として解釈させる問題。
答えとしては’ωωω․ехамрІе․сом’とかで通る。
バイト列で言うと以下
‘\xcf\x89\xcf\x89\xcf\x89\xe2\x80\xa4\xd0\xb5\xd1\x85\xd0\xb0\xd0\xbc\xd1\x80\xd0\x86\xd0\xb5\xe2\x80\xa4\xd1\x81\xd0\xbe\xd0\xbc’
(上のやつコンテスト中はなぜか通らずに発狂していた、その時はωを色々変えてみたら通った。why)
1 | #!/usr/bin/python3 |
生成される画像
H2
pcapファイルが配布される。
HTTP2の大量の通信のどこかに出力されてるx-flagヘッダにflagがあるらしい。
5億年ぶりにwiresharkを起動した。
大体のレスポンスがLength:49なので、フィルタに”http2.length > 49”を入力
ultra_super_miracle_validator
cソースコードを渡したらそれをコンパイルして実行してくれる。
ただyaraでいくつかのルールが定義されていて、それをパスしないと実行してくれない。
最初見た時なんかの命令が禁止されているのかと思ったが、ルールをよく見ると定義された文字列を含めたらパスできる感じだった。
charの配列としてそれらの文字列を定義しておけば、コンパイル後もその文字列が出てくるはずなので適当に定義した後、system(“/bin/sh”)を実行するcコードを送信する
1 | #!/usr/bin/python3 |
hitchhike4b
SECCON 2021で苦しめられたhitchhike
一応リベンジはできた。。。
端的に言うと1つ目は__main__,2つ目は一つ目で得られたpythonファイル名を入力すると変数が得られる。
以下コンソールの対話
1 | help> __main__ |
web
Util
OS Command Injection
ブラウザからは直接打てないのでBurpなり、curlなりを使って直接送信する。
1 | POST /util/ping HTTP/1.1 |
flagのファイル名が’flag_A74FIBkN9sELAjOc.txt’とわかるので上のコマンドをcat flag_xxx.txtにしてflagげと
textex
texのテキストを渡すとそれをpdfに変換してくれる。
‘flag’の文字列があると弾かれるので、
ファイルを埋め込む構文と変数を使ってpdfに埋め込む
1 | \documentclass{article} |
gallery
ファイルの閲覧サービス
拡張子で検索する機能でflagのファイル名を特定
https://gallery.quals.beginners.seccon.jp/?file_extension=fl
普通にflagを取得しようとすると?だけのテキストが返ってくる。
サーバ側で10240を超えるファイルだと変換されてしまうみたいなのでRangeヘッダを使用する。
1 | GET /images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf HTTP/1.1 |
serial
html/database.phpにあからさまなSQL injectionがある。
1 | public function findUserByName($user = null) |
認証を検証する関数loginとかで呼ばれており、cookieの__CREDにセットされたPHPオブジェクトを
unseriarizeしてsql文に挿入される。
以下はtime basedでflagテーブルからflagを抜き取るコード
別にtime basedである必要はない
1 | #!/usr/bin/python3 |
reversing
Quiz
コマンドstrings
1 | $ strings quiz |grep ctf4b |
WinTLS
EXEファイルが配られる。
idaで見るとcheck関数という怪しい関数がある。
strcmpでブレークポイント張って見るとflagが2回にわたってチェックされている。
チェックされている文字列は以下に格納されてた
愚直にctf4b{ABCDE…}みたいに入力をして、比較対象の文字列中のAがどこに現れるか、を一つずつ確認してflagを復元した。
Recursive
名前の通り再起的に関数が呼ばれている。
flagを2分割して前半と後半を再度関数の引数にしている。
再起的に呼ばれる関数の疑似コード
1 | void check(char* ptr, int off) |
復号するsolver
1 |
|
Ransom
暗号化されたflagとRC4の暗号鍵が送信されているpcapファイルが渡される。
これはもうやるだけとしか言いようがない。
以下ソルバ
1 |
|
please_not_debug_me
配布されたバイナリの中にさらにエンコードされたELFが埋め込まれている。
デコードは全体を0x16するだけ、バイナリ中ではELF全体をデコードしないのでgdbでループの回数をいじって全体をデコードさせた後
memorydumpとかでELFを抽出する。
抽出されたELFはptraceを検知するようになっていてgdbとかで開くと正常な処理フローを通らない。
バイナリエディタなどでexit@pltをret(0xc3)に書き換えれば普通にデバッグできる。
あとはRC4をやっていることがわかるので、内部状態、暗号文、鍵をこれまたgdbで取得してソルバを書く。
1 | import base64 |
pwn
BeginnersBof
単純なBOF
stackのアラインメントの関係でwin+1に飛ばす
1 | #!/usr/bin/python3 |
raindrop
単純なROP
1 | #!/usr/bin/python3 |
simplelist
heap上にoverflowがあるので、単方向リストを書き換えることができる。
EIPがdisableなのでAAR,AAWも簡単に作れる。
1 | #!/usr/bin/python3 |
snowdrop
static linkなのでraindropのようにROPはできない。
スタックのアドレスは教えてくれる。
NXがdisableなのでstackにシェルコードを仕込んで,nopスレッドでアドレスを誤魔化す。
1 | #!/usr/bin/python3 |
crypto
CoughingFox
1文字ずつ暗号化して、それをシャッフルしている。
1 | from random import shuffle |
ソルバを書くだけ。
一意にも止まらなかった書き直すつもりだったけど、愚直なコードでも復号できたのでヨシ!
1 | import math |
Command
平文のコマンドからivと暗号文が渡される。
渡されたivと暗号文を再度渡すと復号した平文のコマンドを実行してくれる。
実行したいgetflagは本来実行できないが、復号時に改変したivを渡せばよい。
1 |
|
終わりに
ソロ参加でこんなりがっつり頑張ったの久しぶりだった。
とても面白かった。