A[脆弱性・マルウェア解析トラック]の選考を通過しました。セキュリティ・キャンプについては昨年知り、応募課題を見て実力不足を感じたため応募を諦めました。(応募課題だけでも取り組むべきだったと今は思っています)私がReversing/Forensicsを学び始めたのは最近のことであり、以下に晒す応募課題は間違っている可能性が非常に高いです。(間違っている場所について教えていただけると助かります)セキュリティ・キャンプ2019の応募問題は以下のURLから見ることができます。それらはどんな言語やライブラリを使って作ったのか、どこにこだわって作ったのか、たくさん自慢してください。高校の時に作成したAndroidアプリを2つ、高校の課題研究での成果物、大学で開催した学内CTFの各問題について概要と意図をまとめました。問2今までに解析したことのあるソフトウェアやハードウェアにはどのようなものがありますか?また、その解析目的や解析方法、工夫した点があればそれらも教えてください。大和セキュリティ勉強会:マルウェア解析入門での話と、その時紹介して頂いたSECCON2016のAnti-debugging問題について書きました。以下はAnti-debuggingについて課題で記述した内容です。CTFの問題で印象に残っている問題はSECCON2016のAnti-debuggingの問題である。この問題はアンチデバッギングの例題として”大和セキュリティ勉強会”で紹介してもらった。Port)があり、そのまま実行するとIN命令で処理が止まるためCALL命令をNOPで埋めたこれまでの解析結果を反映して実行するとIDIV命令を実行しているところで終了するようになったIDIVのオペランドを見るとIDIV命令の直前でMOVした値(0)が利用されていることがわかる(0除算が原因でプログラムが正常に動作しない)IDIV命令をNOPで埋めIDIV以降のデバッガ検知処理をJMPで回避することでFlagが表示された問3ブログやGitHubなど技術情報を公開しているURLがあれば教えてください。その内容についてアピールすべきポイントがあれば記載してください。[プロフィール]https://profile.narupi.net[ブログ]https://www.narupi.net[GitHub]https://github.com/narupi[CTFtime]https://ctftime.org/user/41462問4あなたが今年のセキュリティ・キャンプで受講したいと思っている講義は何ですか?(複数可)またそれらを受講したい理由を教えてください。A6について各5行程度でまとめました。各講義について思っていることを素直に書きました。)について分かったことや思ったこと、調査の過程で工夫したこと等を報告してください。その際、書籍やウェブサイトを調べて分かったことはその情報源を明記し、自分が独自に気付いたことや思ったことはそれと分かる形で報告してください。脆弱性の攻略方法を試す際は、他者に迷惑を掛けないように万全の措置をとってください。1.0.1~1.0.1fの拡張機能Heartbeatに含まれる脆弱性によって発生する。Heartbeatとは一定時間ごとにクライアントがHeartbeatRequestを送信し、サーバはクライアントから送られてきたHeartbeatRequestのデータをコピーし返信する仕組みである。脆弱性が含まれるバージョンのOpenSSLのソースコードを見ると、クライアントから送られてきたpayload(サイズ長)をmemcpy関数でそのまま利用している。実際に送信するデータサイズと異なるpayloadに書き換えたHeartbeatRequestを送信することで差分のバイト数分ホスト側のメモリの内容を読み取ることができる。多くのサイトでHeartbeatRequest一回につき取得できる最大のデータサイズは64KBとなっていた。最大64KBなのかについては書かれていなかったため、これについて実装をもとに考察した。4294967295payloadが渡されているmemcpy関数の第三引数はコピーバイト数を表すpayloadが最大値の場合65535バイトを指定することとなる65535バイトは64Kバイトなので実際に送信するデータサイズを0バイトとしてpayloadに65535を渡すと、コピーできる最大バイト数は64Kバイトとなる環境構築:はじめにHeartbleedの脆弱性があるOpenSSLを利用したwebサーバの作成を行った。LTSの仮想マシンを建てた。行った設定は以下の通りである。攻略方法:対象のサーバは10.0.0.103であるとする。対象のwebサーバが脆弱なOpenSSLを利用しているか確かめるためにnmapの調査スクリプトを利用した。Highであり、Heartbleedの脆弱性が利用できることがわかる。次にmetasploitフレームワークでheartbleedのペイロードを検索し利用した。responseとしてサーバのメモリ内容を読み取ることができた。Lengthが65535でありPayloadは0byteであることが確認できた。ResponseのPayloadは16381byteとなっていた。日の時点で発生し2014年4月までパッチが当てられなかった。そのため、この期間に既に脆弱性が悪用されていた可能性がある。この脆弱性を悪用することでサーバ上メモリにロードしたIDやPasswordなどの個人情報、サーバの証明書の情報などを取得できる。主な対策方法としてクライアント側はIDやPasswordの変更、サーバ側は証明書の再発行、Heartbeatの無効化、OpenSSLのバージョンアップなどが考えられる。その他の対策方法として私が考えたのは、iptablesなどのパケットフィルタリングを利用して攻撃を検知する方法である。IPヘッダのパケットサイズは固定であるため、先頭からのバイト数を指定してHeartbeatRequestをブラックリストに登録できるのではないかと考えた。実際にこの方法は考えられたのか調べてみるといくつか記事が見つかった。[7][8]これらの記事を見るとIPヘッダから52バイト目の4バイトが0x18030000:0x1803FFFFに入っているならDROPするというルールを設定することでフィルタリングできることがわかる。iptablesのログ機能を利用すれば検知しづらいHeartbleedの攻撃を検知することが可能であることがわかった。これらの点を踏まえると基本的にはOpenSSLのバージョンアップを行い、どうしてもアップデートできない場合はiptablesなどでパケットフィルタリングを行うことで対策できる。後者の方法は意図的にパケットを改変したHeartbeatRequestは検知できないため、あくまで応急処置である。9.8(amd64)上で動作するプログラムflatteningのmain関数の逆アセンブル結果(*1)とmain関数で使われているデータ領域のダンプ結果(*2)があります。このプログラムは、コマンドライン引数としてある特定の文字列を指定されたときのみ実行結果が0となり、それ以外の場合は実行結果が1となります。この実行結果が0となる特定の文字列を探し、その文字列を得るまでに考えたことや試したこと、使ったツール、抱いた感想等について詳細に報告してください。flattening”の出力結果のうち、main関数の箇所を抜粋しました。与えられるデータはmain関数の逆アセンブル結果とmain関数で使われているデータ領域のダンプ結果だけである。私がこれまでに行ってきたリバースエンジニアリングは、実際の実行ファイルを解析するツールで解析するものがほとんどだった。実際に実行ファイルを動かすことでデバッガによる動的解析が可能であり、ELFフォーマットとして完成しているためIDAやGhidraなどで解析に便利な機能が利用できた。今回の場合は基本的にはツール等に頼れず、自力で逆アセンブル結果を読み解く必要があり非常に勉強になった。ret命令に注目した。ret命令は581と6f0に存在している。581のret命令に注目すると直前の57cでmov命令によりeaxに0x1を代入していることがわかる。同様に6f0のret命令を見ると直前でxor命令を利用してeaxに0を格納していることがわかる。一般にeaxは関数の返り値として利用されることから、これらのret命令がflatteningの実行結果を表していると仮定した。次にジャンプ命令に注目した。この逆アセンブル結果には24個ものジャンプ命令が存在する。先程のret命令の仮定が正しいとすれば、アドレス6ee(0を返すret命令の直前)にジャンプする場所を探せば良いとわかる。6eeにジャンプする命令を探すと6c5に1つだけ見つかる。je命令はゼロフラグがONのときにジャンプする命令であり、直前のcmp命令でフラグをセットしている。r10が成り立つ場合が正しいコマンドライン引数であるとわかる。これを回避しcmp命令を実行するためには6b6/6bd/6c0のいずれかのアドレスにジャンプしてくる必要がある。先程までの解析を踏まえて6b6/6bd/6c0のいずれかにジャンプする命令を探した。直接アドレスを指定してジャンプしている部分は存在しなかった。raxが存在していた。このraxに先程の3つのアドレスのいずれかを指定できれば0を返すretに繋げることができると考えた。550について考えた。[rsp-0xc]を代入し、cmp命令でeaxと0xdを比較している。0xdのとき57cにジャンプする(57cは最終的に1をリターンする)。0xdとなる必要があるとわかる。PTR[rsp-0xc]に0x0~eのいずれかを代入していることがわかる。1をリターンさせないために0xd,0xeを代入している5c9と6c7にはジャンプしてはならない。550ブロックでは次のような処理によってraxを求めジャンプしている。rax大まかに部分ごとの処理がわかったので全体の処理を1行ずつ追うことにした。530のlea命令では[rip+0x37d]が示すアドレスをrdxにロードしている。ここでコメントされている#8b4という数字が何を指しているのか考えた。rip+0x37d=8b4が成り立っているのだろうと仮定し、それを検証するべく以下のコードを作成した。1;}このコードをobjdumpでダンプした結果、今回の課題と同じようにlea命令によるアドレスのロードが確認できた。lea命令からripを計算するとどちらもlea命令の次のアドレスを指していることが確認できた(ripはプログラムカウンタとして利用されるはずなのでこの結果は正しいと言える)。gdbを用いてlea命令後にブレークポイントを設定しlea命令で読み込まれたアドレスが指す内容を表示して確認した。結果、.rodataセクションの内容(上記のコード中の”Z”)のアスキーコードが格納されていることが確認できた。課題で与えられたコードでも同じことが言えると仮定し、lea命令でrdxに読み込まれるデータは0xecであるとわかった。順に処理を見ていくと次に重要になるのは、559~560行の処理である。559では、最初に読み込んだrdxの値を利用してデータをraxに代入する処理を行っている。PTR[8b4+0*4]である。0xfdecである(リトルエンディアン)。0x8b4をraxに代入している。660からの処理を見てみるとrdiが0x2出ない場合は1をリターンするようになっている。0x2という数値から引数の個数をチェックしていると仮定し、gdbでarg.cに対していくつか引数を渡して仮定が正しいか確認した。結果、引数の数に合わせてrdiの値が変化し0x2は引数が1つのときの値であることがわかった。プログラムに与えるコマンドライン引数の数は1つであることがわかった(実行ファイル名を含めず)。その後は[esp-0x3c]のアドレスから4バイトまでのデータに0x1を代入し550へジャンプしている。以後550に飛びアドレスを求めてジャンプする処理を繰り返す。PTR[rdx+rax*4]をSRCと表記する)。r10なら0をリターンする2~5はループになっている。コマンドライン引数を1文字ずつメモリに格納している。r11bは今見ている一文字でこれが0の場合(文字列の終端の場合)はループを抜ける。6で文字数による判定を行っている。文字数が8文字でない場合は1をリターンする。このプログラムで重要な処理はa~cである。2~5で入力したデータに対してr11bでxorを取っている。r11bと最終的な比較で利用されるr10がわかっていれば入力する値を求めることができる。以下はxorを利用し複号した手順である。0x38これらをASCiiコードとして文字に起こすと”Rdoz}sr8”となった。解析に間違いがなければ”Rdoz}sr8”が0を返すコマンドライン引数である。正しい解答は”Reiwa0x1′′となるみたいです。最終的な比較の際にoffsetの更新をしていなかったため一文字目以降がずれていました。Workstationでfuse-apfsを利用して実施することを想定しています。次のリンクからOVA形式の仮想マシンイメージをダウンロードして調査環境を構築してください。ファイルsample.rawおよびchallenge.rawは暗号化されていないAPFSパーティションをDDでダンプしたイメージデータです。それぞれ1つのAPFSボリュームを含んでおり、3種類の異なるPDFファイルが双方のボリュームに一つずつ保存されています。一部のデータが改ざんされており、このままではイメージに含まれるボリュームをマウントしたり、全てのファイルを正しく取り出したりすることができません。資料apfs101.pdfを参考に、以下の問いに答えてください。簡潔に記述してください。参考までに、APFSパーティションイメージをapfs-fuseでマウント/アンマウントする場合は、以下のオプションを利用します。challenge.rawをfuse-apfsでマウントできるようにするために修正し、以下の内容を答えてください。修正箇所のオフセットと修正内容。そのように修正するとマウントできるようになる理由。challenge.rawに含まれるボリュームには、sample.rawに含まれるものと同じPDFファイルが保存されています。問1の問題を解決してマウントしても、そのままでは開くことができないファイルが1つあります。当該ファイルを開けるようにchallenge.rawのデータを修正し、以下の内容を答えてください。修正箇所のオフセットと修正内容。そのように修正するとファイルを開くことができるようになる理由。回答に至る調査の過程(簡潔に)。問7については提出期限までに答えが求まりませんでした。そのため課題解決までに考えたこと・試したことをまとめて提出しました。一致させる手法を考えた[1]https://blog.cugu.eu/post/apfs/まとめ学内CTFを行ったり勉強会に参加したりしていて、課題に割ける時間がなく問7に関しては提出期限前日に取り組む事になりました。(解決できませんでしたが)問5~7の技術的課題は取り組むだけでも非常に成長できます。昨年も合否に関係なく事前課題だけでも取り組むべきだったと感じました。結果論になりますが、熱意だけで私のようなnewbieでも拾ってもらえたので自信がなくても応募してみるべきだと思います。この記事を誰が見てるかわかりませんが、2019年以降のセキュリティ・キャンプに応募しようと考えてる方の参考になれば良いと思います。narupiSecurityとProgramming。IT初心者なので高い確率で間違った情報が含まれています。