セキュリティミニキャンプ in 北海道 ~ 参加レポート(2日目の部)

ものすごく間が開いてしまいましたが、ついにメインとなる二日目です。

こちらも私による独断と偏見で、一人称視点で書かせていただきます。かなりとりとめが無くなりますがご了承ください。

ハンズオンでした。タイトルは「ファイルシステムを理解する」。バイナリエディタを使ってNTFSを読み解いていく、自分にとっては初体験な事をやってきました。

先生からいただいた資料と直々の解説を元に、MBRからパーティションの先頭オフセット(VBR)を求め、VBRからMFTの位置を突き止め、MFTからCドライブ直下のあるファイルにアクセスするまでの手順を辿りました。仕様に沿って一つ一つアドレスやその意味を読み解いていけばちゃんとたどり着くことができて、大変興味深い演習でした。

あとHexEdit便利です。ブックマーク機能やジャンプ機能、また計算機能やハイライト機能には大変助けられました。今読んでいるバイナリをハイライトし、リトルエンディアンで引っ張ってきてジャンプするとかそんなことばっかりやってましたけど、これがなぜだか楽しいんですよね。

そしてここまで学んだことを応用して、解析しているシステムにいつマルウェアの感染が完了したのか突き止める作業を行いました。マルウェア自身が自分自身のタイムスタンプを書き換えているらしく、妙に古い日時になっているのですが、変更できない部分から元のタイムスタンプを読み取りって実際の感染日時を特定することができました。

ものすごくどうでもいいのですが、机の上にアパ水置いておいたら進捗が出なくて顔を上げる度にご対面して云々。

そういえばおやつが配られたのもこの時間でした。生八つ橋と「博多通りもん」です。やっぱり糖分必要ですよね。とても美味しかったです。ありがとうございました。

実は先ほどの作業、割と時間を掛けて熱心に取り組んでいたらお昼の時間になっちゃいまして。なんか早弁をしている方もいらっしゃったようですが、キャンプ生はむしろ遅弁でした。午後のコマに遅れが出ないよう説得され、渋々お昼を食べるという状況。私含め皆さん本当に熱心に取り組んでいました。

お昼は大人もキャンプ生も混ざってわいわいと。ちなみにメニューは唐揚げ弁当でした。

改めて名刺交換したり、大人の人から色々お話を聞かせて貰ったり、学生同士でもさらに交流が深まったりで素晴らしいひとときを過ごしました。そして午後のハンズオンへと引き戻されたわけです。

ここでは「ディスクフォレンジックツールを使う」と題して、午前中はバイナリエディタだけでNTFSを解析していたものを、今度はツール(The Sleuth Kit)を使って行おうというハンズオンをやりました。

先生の狙いとして「何かツールが誤作動した際にその動く仕組みがわかっていれば対処できる」ということで、最初からツールは使わずまずバイナリエディタで解析させたとのこと。確かに、先生の力を借りつつではありましたが自分で何とかツールのバックグラウンドと言いますか、NTFSの内部構造を理解することができましたので大変勉強になりました。さらにNTFSの内部構造なんて知る機会というのがこうでもしないと無いと思うのでこれまた大変貴重な経験ともなりました。

ここであるファイルを抽出して、その中身を覗いてみたりしました。攻撃者の行った動作がありありと示されていて大変興味深いファイルでしたよ!

そしてここからが課題。pytskを使って隠されたファイルを発見するものです。これが全く手が付けられなくて。サンプルとか骨組みとか見つつ、出力ともにらめっこしつつ、どれが隠しファイルなのか的確に判定しなければならないのでとても難しい。

あれこれと隠しファイルである条件を絞っているうちにあっという間に時間が来てしまいました。結局絞り込めた条件は2つだけ(答えでは3つ)でした。結果として私の見つけた条件だけでも出力されるものに大差は無いそうですが、時間内に終わらせることができなくてとても悔しい体験でした。

一応、自分がその条件を発見するに至った過程を記しておきますね。

# judge ADS
for attr in f:
    print "Attribute %s, type %s, id %s" % (attr.info.name,
                                            attr.info.type,
                                            attr.info.id)
print ""
# judge ADS
# tmpにattr.info.typeを入れて、同じだったときだけMFTエントリ番号とファイル名を表示
tmp = ""
for attr in f:
    if attr.info.type == tmp:
        print 'MFT entry {0}'.format(inode)
        args = ["/usr/bin/ffind", 
                "-o", str(part.start), 
                image_path, 
                str(inode)]
        p = Popen(args, stdout=PIPE)
        filename = p.stdout.read().rstrip()            
        print filename
    tmp = attr.info.type
# judge ADS
tmp = ""
for attr in f:
    # 条件に「attr.info.name is not None」を追加
    if attr.info.type == tmp and attr.info.name is not None:
        print 'MFT entry {0}'.format(inode)
        args = ["/usr/bin/ffind", 
                "-o", str(part.start), 
                image_path, 
                str(inode)]
        p = Popen(args, stdout=PIPE)
        filename = p.stdout.read().rstrip()            
        print filename
    tmp = attr.info.type

という感じで、少し自信なさげにできたプログラムです。興味がありましたら、お手持ちの「skelton.py」に組み込んでその結果を眺めてみてください。

そんなこんなで答え合わせも終わり、2日目のハンズオンはあっという間に終わってしまいました。

まず先生から種々の宿題が出されました。具体的には、この環境に於いてマルウェアがどう感染したのか、具体的にどういうものなのか調べてみようというものです。色々ヒントをいただきましたので、これでもって何とか解析を試みているのですがなかなか難しいです。精進します。

次にありがたいお言葉をいただきました。上にも挙げたのですが「ツールの結果に惑わされないようにデータ構造や解析手法の本質に精通しよう」という精神はこれからの技術者人生に於いて大切にしたいと思います。

また「『~エンジニア』という風に自分をラベル付けしない」と、幅広い知見を持つように諭していただきました。私はプログラミングだったりサーバー運営だったりセキュリティ方面だったりと、元々色々手を付けては中途半端な人なので、これまでに手を付けたものをもう少しずつでも深められたらこの精神を実行できるのかな、と思ったり。

そして参考文献を紹介していただきました。主に洋書が中心でなかなかハードルが高そうだと勝手に思ってましたが、先生は「ITに関わる限り、英語を勉強しよう」とおっしゃっていましたので、むしろこういう本の方が興味が湧いて英語でも割と読めてしまうんじゃないかと考えたりしてました。

最後に、MVPが発表されました。2人に授与されるらしい。そして参考文献「FILE SYSTEM FORENSIC ANALYSIS」がいただけるらしい。最初に貰ったのがつっつーさんで、私が見つけられなかった隠しファイルの条件を見事見つけ出したとのことで納得の受賞でした。

つっつ-さんは応募の時点からダンプした自分のNTFS環境をバイナリエディタで見て、それを報告していたとのことでなおも納得。目標の人物の一人です。私も積極的にならないと。

そして二人目の発表。先生が「じゃぁ、彼に」と指さしたのはなんと私でした。もうなんと申し上げて良いかわからないぐらい驚き。当時の気持ちを正直に振り返ると「最後の問題も解ききれなかったのにどうして僕に!」と思ってました(今でも少し思ってます…)。でも本を受け取ったらなんだかうれしさの方が前面に出てきちゃって…(あまりに単純)。

そんなこんなでつらかったり、楽しかったり、悔しかったり、でもうれしかったりした僕のセキュリティミニキャンプは幕を閉じました。で、みんなで机を元の場所に戻したりとかして後片付けを手早く行って、また参加者と雑談して。終わってからも楽しい時を過ごせました。

そして私はインタビューがあったので皆さんがお帰りになったあとも居残り。さっぱりと片付いた会場の隅に椅子を置いて7分ぐらい、緊張して変なことを口走ったりしましたが、インタビューを収録しました。

で、終わってから外に出たらまだスタッフの皆さんとか残って雑談してましたので、そこに混ざってまた雑談。「来年こそ本戦出場だ!」みたいなノリになってました。そして名残を惜しみながらお別れ。方向が同じ方々と地下鉄で移動。最初は4人だったのですが、1人別れ、2人別れ、そして最後に3人別れ。ちょっと寂しい。でも帰らなきゃ。

皆さんとお別れしたあとはお買い物したり、晩ご飯食べたりしてました。吉野家の牛丼ですけど。

そして電車に乗って帰宅。ただでさえ重たいThinkpadに例の本まで加えたらほんとに重くて重くてですね。家に着いたときにはもう肩が酷いことになってましたよ(笑)。

まず応募に至るまでにも紆余曲折あった僕のミニキャンプですが、こうして振り返ってみると僕の技術者人生において一生忘れられない、そして自分の糧になる体験ができたと感じています。

この連載の最初に言及した「ついて行けるかな、何の知識も無いのに場違いなんじゃないかな」から「もう終わっちゃうの!?」という心境の変化は、やっぱり事前課題を通じて一見困難かと思われたことについても否が応でも知る機会を作っていただき、結果的に本番に通じる知識が事前にある程度あったおかげなのかな、と思ったり。やっぱりきちんと(本人の感想です)取り組んでよかった、そう振り返ってます。

どんな作業もやってて楽しかったし、お話を聞くのも集中できたし。なんかまた、興味を引く分野を開拓できたかなと感じています。

とりあえず次のステップはここで勉強したことをまとめて発表することかなと思ってます。この連載もその一環ですけどね。とりあえずNTFS構造についてはどこかでアウトプットしたいと。具体的な構造となると割と日本語資料も少ないみたいですし、今回の資料と例の本を片手に踏ん張ってみるつもりです。

さて、ものすごく長くなってしまいました。この辺でおしまいにしましょう。

最後に。この素晴らしい企画を実施してくれた実施協議会の皆さん、お手伝いいただいたすべての皆さん、そして講師、参加者の皆さん、本当にありがとうございました。また機会があれば、一緒に学ばせていただきたいと思っています。その際はよろしくお願いします。

 Share!