セキュリティ・キャンプ全国大会2021(https://www.ipa.go.jp/jinzai/camp/2021/zenkoku2021_index.html )に参加しました。
そこでFlare-On Challengeを教えてもらい、色々と面白いので記事を書きます。
CTFのrevが大好きな人におすすめです。
とりあえず、解けた分のwriteupを書いていきます。
Flare-On Challengeとは
紹介している日本語の記事がすでにあるので、詳しく知りたい方はこちらを参照してください。
日本語の紹介記事(https://developer.ntt.com/ja/blog/5d8c011e-e3fd-4084-aeb3-7cba21cfd0d1 )
こちらが公式サイトです。
第8回Flare-On Challengeのアナウンス(https://www.fireeye.com/blog/threat-research/2021/08/announcing-the-eighth-annual-flare-on-challenge.html )
Flare-On website(http://flare-on.com/ )
githubで過去問が公開されています。
過去問(https://github.com/fareedfauzi/Flare-On-Challenges )
writeup
解けたものから随時書いていきます。
2016
公開されているwriteup
- https://github.com/fareedfauzi/Flare-On-Challenges/tree/master/Write-ups/2016
- https://0xec.blogspot.com/2016/11/flare-on-challenge-2016-write-up.html
- http://mislusnys.github.io/post/flareon3/
Challenge1
新たに得た知識
- Base64系のアルゴリズム
使ったもの
- Ghidra
- Python
最初の問題なので、ウォームアップ的な難易度でした。
Challenge1.exeを実行すると、パスワードを求められます。
解析するとわかりますが、そのパスワードがflagです。
静的解析すると、ハードコードされた2つの文字列を発見でき、片方がエンコードされた正解のパスワードであり、もう片方がそのエンコードアルゴリズムにおけるキーのような役割を持っていることがわかります。
ですので、この問題を解く方法は、エンコードされた正解のパスワードをデコードするスクリプトを作成することでした。
エンコード処理では、最後に”=”をエンコード文字列に付け足していたため、Base64であることが直感でわかります。
しかし、普通のBase64ではデコードできませんでした。
ここで、前述したエンコードにおけるキーのような役割を持った文字列がBase64の変換表(https://ja.wikipedia.org/wiki/Base64#%E5%A4%89%E6%8F%9B%E8%A1%A8 )の役割を持っていることに気がつきます。
そのため、その文字列をBase64の変換表として用いてデコードすることでflagを獲得できました。
Challenge2
新たに得た知識
- (疑似)ランサムウェアの解析
- WinAPIのCrypt系関数
- IATの仕組み
使ったもの
- Ghidra
- x32dbg
DudeLocker.exeとBusinessPapers.docという2つのファイルが渡されます。
BusinessPapers.docは正常に開くことができず、暗号化されているような感じがします。
DudeLocker.exeを解析した結果、実行すると以下の処理を行うことがわかりました。
- C:¥Users¥[UserName]¥Desktop¥Briefcaseの存在確認
- 存在する場合は、CドライブのVolumeSerialNumberがハードコードされた値と一致するかどうか確認
- 一致する場合は、C:¥Users¥[UserName]¥Desktop¥Briefcase内のファイルをAESで暗号化
- その後、存在しない場合は脅迫文を¥Briefcase内にpng形式で生成し、同様のpng画像を背景として設定する。
このような動作から、BusinessPapers.docはDudeLocker.exeによって暗号化されており、復号することでFlagを取得できそうなことがわかります。
暗号化方式は共通鍵暗号方式であるAESであるため、暗号化の過程と復号化の過程は同様です。
この記事を見ると(https://www.hiramine.com/programming/windows/encryptdecryptstring_aes128ecb.html )データの暗号化を行うCryptEncrypt関数とデータの複号化をするCryptDecrypt関数を呼び出すまでの処理は全く同じであることがわかります。
そのため、プログラム内で呼び出されているCryptEncrypt関数をCryptDecrypt関数に書き換えれば、DudeLocker.exeを復号プログラムに変換することができます。
呼び出される関数の書き換えはIATを書き換えることで達成します。
x32dbgでIATを書き換える場合、Scyllaを使います。(参考記事:https://mymanfile.com/?p=1321 )
書き換え後、CドライブのVolumeSerialNumberをハードコードされた値に変更させるか、デバッガで該当箇所を書き換えてプログラムを実行するとBusinessPapers.docが復号されます。(VolumeSerialNumberが複合鍵の生成に使われる)
しかし、復号後のBusinessPapers.docも正常に開くことはできません。
そこで16進ダンプを確認すると、png形式のマジックナンバーが含まれていることがわかります。
よって、BusinessPapers.docをBusinessPapers.pngに変換し、開くとflagが書かれています。
Challenge3
新たに得た知識
- pdbファイル
使ったもの
- Ghidra
- Python
- x32dbg
とりあえず知見のみ
- 拡張子がpdbのファイルは、ビルドして生成されるexeファイルと同時に作成される同名のデバッグファイルであるらしいため、pdbファイル名から正しいファイル名に復元できる。
- プログラム名やコマンドライン引数で指定した文字列の長さが、エンコードされたデータをデコードする鍵となる場合がある
- 総当たりは可能であれば行う
Challenge4
新たに得た知識
- DLLファイルの解析方法
- エクスポート序数
使ったもの
- Ghidra
- C言語(Pythonでもいけるかも)
- x32dbg
とりあえず知見のみ
・GetProcAddress(hLib, "DLLFunc1")のように、関数名を指定してエクスポートできない場合、GetProcAddress(hLib, MAKEINTRESOURCE(51))のように、エクスポート序数というものを指定してエクスポートする。
余談ですが、ギミックが面白かったです。
2017
公開されているwriteup
- https://github.com/fareedfauzi/Flare-On-Challenges/tree/master/Write-ups/2017
- https://lifeinhex.com/about-flare-2017/
- https://blog.attify.com/
Challenge1
新たに得た知識
- 特になし
使ったもの
- Chrome
- Python
デコードスクリプトを作れば良いだけ
Challenge2
新たに得た知識
- 特になし
使ったもの
- Ghidra
- Python
埋め込まれているデータをxorでデコードすればFlagが得られる単純な問題。
特に得られた知見はなし。
Challenge3
新たに得た知識
- ソケット通信
- 自己改変型の知見
使ったもの
- Ghidra
- C言語(Pythonでもいける)
とりあえず知見のみ
- ソケット通信と自己改変に関する問題
- プログラム側が3バイトのデータ受信し、先頭1バイトを復号鍵として利用する
- 実行される部分が難読化されていると、静的解析のみでの解析は不可能
- 0x80 ~ 0xffあたりのバイト列は"A"や"b"のような文字と対応していないため、バイト列を送信するスクリプトを作成する場合は注意が必要。
このプログラムには存在しませんでしたが、第3引数がPAGE_EXECUTE_READWRITE(0x40)のVirtualProtect関数(https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect )の呼び出しは、自己改変型によく見られるそうです。
現在の状況
今年のFlare-On Challengeに取り組み中です。
終了したらwriteupをここに追記します。