守田向輝です。
Full Weak Engineer CTFにご参加いただきありがとうございます!この記事では私が作問を担当した以下の4つの問題のwriteupを書かせていただきます!
- strings jacking [rev]
- I_HATE_DEBUGGING [rev]
- QR [Forensic/OSINT]
- git predator [Forensic/OSINT]
strings jacking [rev]
この問題は初心者向けのrev問となっています。いたってシンプルな問題となっており、問題名の通りstringsコマンドを使えば解決できる問題です。また、grepコマンドも活用して、flagフォーマットを検索すると見つけることが出来ます!
strings strings_jacking | grep fwectf{
#実行結果
**fwectf{5tr1n65_30F_p4ss937_0011}**
I_HATE_DEBUGGING [rev]
この問題は中級者向けのrev問となっています。解法の手がかりとして、問題文にもI hate debugging! Breakpoints, hooks - what are those, I don't get it! Can you help me out with some tech stuff?と書いてある通り、デバッグ(動的解析) と Hookがカギを握る問題となっています。
今回は、最も解きやすい(あくまで個人の感想)解法を記述します。この問題はかなり別解が多い問題だと思うので、そちらの方も自分で試してみるのをお勧めします。
配布ファイルを解凍すると
- whatisthis.dll
- antidebugtest.exe
これらのdllとexeファイルがあることを確認できるかと思います。
それぞれidaで開き、デコンパイルをすると以下のことが分かるかと思います。
whatisthis.dllの中身

whatisthis.dllのiathook関数の中身は上の画像のような構造となっており、ここで最も注目するべき点は関数の引数についてです。
ここに提示されている通り、引数はconst char*が3つ、__int64が1つ、FARPROCが1つとなっています。
この引数がどういった役目を果たしているかのために、先程のコードを見直すと以下のことが分かるかと思います。
- a1が読み込むmoduleの名前
- a2が対象関数のあるdllの名前
- a3が対象関数の名前
- a4が呼び出し先の関数
IAT Hookとは - Import Address Tableに格納されている特定の関数のアドレスを別の関数のアドレスに書き換えて、その関数が呼び出されたら別の関数が呼び出される技術。
antidebug.exeの中身
これらを一旦メモして起き、次にantidebug.exeのmain関数をデコンパイルしていきます。

すると、まず真っ先に呼ばれるIsDebuggerPresent関数が、デバッガーを検知して強制終了させてくることが分かります。
ここの部分をアセンブリの方でbreakpointを設置して、回避できるようにしておきます。

次にHook関数のデコンパイルが以下の通りです。
多くの変数が暗号化されたあと、iathook関数を呼び出しすのをtrueの返り値が出るまで繰り返していることがわかります。
iathook関数がtrueを渡すということは、さっきのwhatisthis.dllから、iathookが正しく行われた時のみとわかるので、このhook関数は、pdir3(関数名)をfb1にiathookで置き換えている動作を行っているということが分かります。
fb1の追跡
次に、このfb1の関数を探します。
fb1をダブルクリックすると以下の情報が得られるのでnewopen関数ということが分かります。

newopen関数の解析
newopen関数をデコンパイルすると以下のようになると思います。

まずmain関数と同じようにIsDebuggerPresent関数が先に呼び出されるので、先程と同じ手段でbreakpointを設置します。また更に解析を行うと
int a = 1;
if (a==1) return original(...);
というコードも見つけられるので、そこもbreakpointを設置します。
その後、aの値を書き換え、returnを解除すると、この後に続く変数の複合化コードが正しく読み込まれます。
流れを理解する
今までの事から、main関数の流れをまとめると以下の順序で行われることが分かります
- hook関数(iathook)が呼び出される
- fopen関数が呼び出される※iathookによりnewopenも開かれる
- decodeflag関数が呼び出される
- fopen関数が呼び出される※iathookによりnewopenも開かれる
- flag.txtが生成される
デバッグを実行する。
あとはデバッグを実行するだけです!
まずはmain関数のIsDebuggerPresent関数を回避します。

その後、newopenが呼ばれるのでそれのbreakpointも正しく処理をしていきます。

次にif(a==1) return original(...);のところで止まりますが、今回は無視します。
最後に、2回目のnewopenの時にif(a==1) return original(...);のアセンブリを変更して、デバッグを続行すると

ディレクトリ内にflag.txtが生成され、ゲットできます!
QR [Forensic/OSINT]
この問題は問題名のQRと、問題文に書かれているRGBが重要になってきます!

ファイルを開くと上の画像が出てきて、実際に読み込んでみると
3 6 7
2 9 4
8 1 5
となります!これを、qrのそれぞれの箇所のRGBを取得し、上の数字順に並び替えると
66 77 65 63 74 66 7b 51 52 5f 61 6e 64 5f 63 6f 6c 6f 75 72 5f 39 38 37 36 65 7d
となり、
fwectf{QR_and_colour_9876e}
と複合できることが分かります!
git predator
この問題は、問題文を参考にして2つに分れているflagを見つける必要がありました。
1つが捨てられていないflag、もう1つが捨てられたflagです。
捨てられていないflagはgithubのcommit履歴をさかのぼれば見つけることが出来ます。

こんな風にcommit履歴をさかのぼり、適当に全部見つけるとImprove UIで出てくることが分かります。


もう1つは、「捨てられている」に着目して、Forceでcommitを消されているという事を考えます。
その結果、add flagとかいうあからさまにflagがあるcommitを見つけられるので
flagが2つ入手出来て、fwectf{y0u_ar3_g1t_pr3da70r!_78e0}
最後に
自分自身初のCTF運営で、これまであまりCTF経験もなかったのですが、メンバーの方々が手厚い支援をしていただいたのでスムーズに問題を作成、検証することが出来ました!本当に心から感謝します。
また、I_HATE_DEBUGGINGに関しては静的解析でも実は解けたり、メモリを解析するだけなどかなり別解が多かったのでそちらでもぜひ解いてみてください!ありがとうございました!
次こそはマジのアンチデバッグとHookの作ります!!!
