ソロチーム /dev/null で参加して 859 point 24 位でした。 どれも難しかったですがやらせようとしている事は理解できる良問が多かったと思います。 Webはもう少し時間があれば行けたかもしれず悔しい思いをしました。
Reversing: ffi
TrueTypeフォントが渡されるのでインストールする。
指示された通りフォントプレビューで適当なフラグを入力するとincorrect表示になる。
いくつかパターンを試す。
末尾}
を入力した時点でフラグ判定されている。
フラグ文字列に大文字アルファベット等が含まれるとフラグ判定が行われない。
これらの挙動から}
が入力された事をトリガーにして文字列判定を行うスクリプトのようなものがフォントファイルに同梱されていると推測できる。
フォントの内容を確認できるツールを探すとFontForgeが見つかった。 ffi.ttfを開いてみると定義された文字(グリフと呼ぶらしい)が見える。 テーブル末尾にフラグに関係しそうなグリフがある。 正解フラグはグリフ346だ。
次にフラグ判定のトリガーである}
を調べる。
それっぽいキーワード置換
を眺めていくと一つだけ周囲と異なる行が見つかる。
条件がSubstitution lookup 51に該当した場合に}
をグリフ346に置き換えると推測できる。
置換の詳細な挙動を調べるためにATT(Advanced Typographic Tables)を確認する。
Substitution lookup 51を読む。
逆引き範囲 -1: glyph140
braceright -> glyph346
ひとつ前の文字がグリフ140ならば入力された}
(braceright)をグリフ346に置き換えると読み取れる。
ちなみにグリフ140はSubstitution lookup 130に定義されており、ひとつ前の文字がグリフ219の場合にeを入力したものが該当する。
後は同じ要領でひとつ前のグリフに置き換えられるSubstitution lookupを辿っていく。
このツリーは右クリックからテキストにエクスポートできるのでgrepで探せば良い。
・・・ただし、私はこれらのツリーを一括で開く方法が分からなかった。 哀れ合計250×4個のツリー開示ボタン(+)をひたすらクリックし続けるマシーンと化したのであった。 すごく頑張ってポチポチした成果はこちらです。
TSGCTF{ligature_state_machine}
Forensics: Obliterated File / Obliterated File Again
間違ってgitに上げてしまったフラグを探す問題。 想定されていない解法が見つかったとかで2問に分割された。 おそらく私が辿り着いたのは想定解なのでどちらも同じ解法でフラグを入手できた。
フラグを削除するためにfilter-branchを使っておりファイルを復旧するのは容易ではないように見える。
$ git filter-branch --index-filter "git rm -f --ignore-unmatch problem/flag" --prune-empty -- --all
$ git reflog expire --expire=now --all
$ git gc --aggressive --prune=now
確かに/problem/flagが存在した形跡はあるのだがファイル自体はログから確認できなかった。
# git log --pretty=oneline | head -4
266f4148e4cf37bdbfb57da379ea49b2f106e6b2 delete .travis.yml
cd50304fc39f8c0fbc7ad062ecb9a940f3baed29 fix the way of posessing the flag
ba46709ec62fd916b29f17c5e9fd2fa99b71027c fix .gitignore
d516014b8de3f20d473f2adca1713337095c7873 enable production mode
# git show cd50304fc39f8c0fbc7ad062ecb9a940f3baed29
commit cd50304fc39f8c0fbc7ad062ecb9a940f3baed29
Author: tsgctf <info@tsg.ne.jp>
Date: Thu May 2 19:02:33 2019 +0900
fix the way of posessing the flag
diff --git a/problem/main.cr b/problem/main.cr
index 02d3653..8e49798 100644
--- a/problem/main.cr
+++ b/problem/main.cr
@@ -1,12 +1,12 @@
require "./src/*"
require "sqlite3"
-require "zlib"
-
-flag = File.open("./flag", "r") do |f|
- Zlib::Reader.open(f) do |inflate|
- inflate.gets_to_end
- end
-end
+#require "zlib"
+#flag = File.open("./flag", "r") do |f|
+# Zlib::Reader.open(f) do |inflate|
+# inflate.gets_to_end
+# end
+#end
+flag = ENV["flag"]
`rm -rf data.db`
DB.open "sqlite3://./data.db" do |db|
しかし、いろいろ調べてみると実際に過去のコミットの中身を見るとファイルが取り戻せるという情報が散見される。
git rev-list --all
を使えば良いらしい。
# git rev-list --all | head -4
266f4148e4cf37bdbfb57da379ea49b2f106e6b2
cd50304fc39f8c0fbc7ad062ecb9a940f3baed29
ba46709ec62fd916b29f17c5e9fd2fa99b71027c
f1d1f81fb5444ec4d40736104d682b43611c66f5
先ほどは見えなかったf1d1...
が見つかる。
git resetすると歴史から抹消されたはずのflagファイルが入手できた。
# git reset --hard f1d1f81fb5444ec4d40736104d682b43611c66f5
HEAD is now at f1d1f81 enable production mode
# ls -la problem/
total 52
drwxr-xr-x 4 root root 4096 5月 5 17:07 .
drwxr-xr-x 4 root root 4096 5月 5 17:07 ..
-rw-r--r-- 1 root root 12288 5月 4 17:35 data.db
-rw-r--r-- 1 root root 62 5月 5 17:07 flag
-rw-r--r-- 1 root root 46 5月 5 17:07 .gitignore
drwxr-xr-x 9 root root 4096 4月 30 20:55 lib
-rw-r--r-- 1 root root 458 5月 5 17:07 main.cr
-rw-r--r-- 1 root root 134 5月 5 17:07 README.md
-rw-r--r-- 1 root root 507 5月 5 17:07 shard.lock
-rw-r--r-- 1 root root 297 5月 5 17:07 shard.yml
drwxr-xr-x 4 root root 4096 5月 5 17:07 src
deflateしてフラグを入手する。
# python -c "import zlib; f=open('/tmp/easy_web/problem/flag', 'rb'); r=zlib.decompress(f.read()); print(r); f.close();"
TSGCTF{$_git_update-ref_-d_refs/original/refs/heads/master}