読者です 読者をやめる 読者になる 読者になる

HappyNote3966’s blog

備忘録、作業記録的なことを書きます。低レベル注意。ご指摘等ございましたらやんわりとお願いします(´;ω;`)

セキュリティキャンプ2016の応募用紙を晒す(真似事)

注意事項

・技術的なことはそれほど難しいことを書いているわけではありません。
持てる知識をひねり出した結果、雑巾から汚水を絞った感じになりました。

・やたらと長いので読んでいると飽きるかもしれません。いや、絶対に飽きます。

・誤字脱字については直していません。

・一応合格を頂くことができました。来年の応募者様のご参考になれば幸いです。

 

共通問題1

(1)あなたが今までに作ってきたものにはどのようなものがありますか? いくつでもいいので、ありったけ自慢してください。

 1つ目は、高校の頃に課題研究としてゲームを作りました。作ったゲームは、自分の書いた小説を基にしたノベルゲームです。当時、課題研究という高校の卒業研究のようなものの一環として何か一つの成果物を作るという授業があり、そこでは私はゲームを作ることにしました。ゲームは小説の世界観を味わってもらうため、一人称視点としました。このゲームではゲーム開発に使われるようなUnityなどのゲーム開発に特化した環境は用いず、EclipseJava,そして標準のAPIとJMFのみで作りました。スクリプトを組むことができる吉里吉里などを用いずに作ったので見た目は綺麗とは言えませんが、ゲーム内に出てくるウィンドウやパネルなどのGUIパーツは全て自分でグラフィックを調整することで実現しました。また、ストーリーに合わせて音楽がやキャラクターの表情が変わるようになっています。加えて、操作をするごとに効果音を鳴らすことができ、文字列の動きなどをアニメーションで表現していたりもします。他にもセーブ機能や、ストーリーをじっくり読んでもらうため話を進めるごとに操作を受け付けないようにする仕組みも追加されています。

 作ってよかったところは、全体を通してプログラミングになじむことができた上、年単位で構想していた自分の小説をゲームにできたことと、高校での良き思い出になったことです。グラフィックに関する処理についても学べましたし、チームで開発するということの難しさも痛感することができました。また、このゲームの発表が校内に留まらず、小松市で行われた課題研究発表会において褒められたことです。

 改良点としては、まず素材を除いてグラフィックがあまりにも前時代的で、きれいではありませんでした。今のモダンなGUIのようにきれいに表示できるようグラフィックの処理を変更しなければならないのと、既に読んだ部分をスキップすることができるように記録しておくこと、お話の分岐を作ることなどが挙げられます。このゲームは欠陥だらけではありますが、私の高校時代のとても印象に残る思い出そのものであり、私のレベルの低さを教えてくれる、いわば戒めのような存在でもあります。より上のレベルを目指さなくてはならない、自己満足だけで終わってはいけないということを学ぶことができた、一つの人生経験です。

 

 2つ目は内田クレペリンの生成プログラムを作成しました。このプログラムは2~9までの乱数をA4の紙に空白と交えて敷き詰めるというものです。プログラム自体は.txt形式で乱数をファイル出力し、それをWordで開き適度なフォントとサイズに調整し、プリンターが対応しているPDF形式に変換するマクロを組んでプリントアウトしました。卒業後就職する人が多かったので、内田クレペリンの練習が必要だったのですが、高校で配布された用紙だけでは乱数を覚えてしまう可能性があるので、何回でも生成できるこのプログラムを用いて就職試験をサポートしました。一度に十数枚印刷して渡すこともしばしばだったので、予めログを記録するファイルを作成し、そこからこれまでに出力したファイルと名前が被らないようにしました。こうすることでプログラムを実行する回数だけ.txtファイルが出力できます。

 作ってよかったことは、乱数を生成し、それをテキストファイルに出力するなどの基本的な処理を学べたところです。また、ちょっとしたマクロを組むのにわざわざVBAをいじらなくてもマクロの記録をするだけでマクロが作れるなど、Wordの機能も学べたことです。

 改良点としては、作ったクレペリンのテキストファイルは一度手動でWordに読み込ませていたので、この作業も自動化し、プログラムの起動だけで一連の動作が完了するようにすることです。

 

 3つ目は、0~49までの数字の記されたボタンがグリッド上に配置され、その数字を0から順番にクリックしていき、最後の49がクリックされるまでの時間を図るというプログラムを作りました。このプログラムも就職試験の注意力配分テストのために制作しました。Javaで製作したこのプログラムの特徴は、クリックされる数字が順番にならなければ操作を受け付けないようにできています。最期の49の数字がクリックされたとき、0の数字がクリックされてから49の数字がクリックされるまでの時間をタイトルバー上に表示するというものです。PC上で動くのはもちろん、PCが使えない状態でも練習してもらえるよう、問題はスクリーンショットを取得して印刷していました。

 作ってよかったことは、Javaでの基礎的なGUIアプリケーションの作り方が分かったうえに、タイマーを取得して時間を図れるようになったところです。加えて、このアプリケーションを作ったのがきっかけでオブジェクト指向のイメージが掴みやすくなりました。

 改良点としては、配置されたボタンを押した感覚があまり得られていないので、正しいボタンをクリックできた時とそうでない時にSEを鳴らして分かりやすくすることと、一度最後までやり終えると再起動しなければならないので、結果の表示を分かりやすくしたり、リトライするかどうかを尋ねるようにGUIを追加しなければならないと考えます。

 

4つ目は、規則性のある記号を(●、▲、▼、◆、■)などが記されたボタンをグリッド上に配置し、横一列に並んだ複数のボタンの中に仲間外れを一つだけ紛れ込ませるというプログラムを作りました。このプログラムも就職試験の一環となっているテストの対策として作りました。乱数で文字列内の違った記号を出力する位置を指定し、横一列に並んだほかのボタンとは違う並びの文字をボタンの中に書き込んでいます。特徴的な記号ばかりを使った簡単なものから似たような記号を用いた難しいものも作りました。こちらもPC上で何度も実行でき、PCがなくとも予めスクリーンショットを取得して印刷していました。

 作ってよかったことは、記号の並びを再現するために考え込んだので、良い頭の体操になったと考えます。

 改良点をとしては、もっと難しい配置や表現を考えなければならないと思います。そのためには実際の就職試験問題を自分で解いたり、心理系の本を読んだりしなければならないと思います。ここまで就職試験対策用のプログラムを作ったとしましたが、いずれ自分も使うことになるので更なる改良が必要だと考えます。

 

 5つ目は、換字式暗号解読プログラムです。こちらはCTFの対策としてJavaとCの両方で作りました。最初は単純に文字列の各文字に対して加算処理を加え、26通り分全ての文字列を出力していました。しかし、それでは非効率的だったので、CTFのサイトを見て回りながら良く出題されていたROT13の問題を参考に、13文字分ずらした文字列を表示するよう改良しました。また、仮にROT13でなくても対応できるよう、ずらす文字数を指定すれば正の方向と負の方向両方に関係なく対応できるように作りました。

 作ってよかったことは、プログラミングと文字の関係(特にASCII)が良く分かり、自分の作業を簡易に済ませられるよう便利なものを作りながら勉強するという姿勢が学べたことです。

 改善点をとしては、このプログラムは単なる換字式暗号にしか対応できていないので、他の暗号方式にも対応できるようプログラムすることと、コマンドラインベースで動作するので、GUIを実装してコピー&ペーストや復号したい暗号化方式の選択ができるようにするなどより使いやすいプログラムとすることです。

 

 

 6つ目は、アプリケーションなどのクイックランチャーです。私は学校の課題などでよく同じソフトを何度も起動させることがあります。従来はマウスを使ってダブルクリックを繰り返していましたが、私はマウスとキーボードの切り替えをすることが時間の無駄に感じていました。私の読んだ本には、人間にはCPUと同じくコンテキストを備えており、そのコンテキストを切り替えるコンテキストスイッチがあるのだとありました。更にその本には、人間はCPUのようにコンテキストスイッチを行ってもすぐさまそれが脳内で反映されないともありました。この本を読んでから、私は自身の行動を観察し、コンテキストスイッチに相当する場面が無いかと言うことを考えました。

 そこで私が思ったのは、よく使うアプリケーションをダブルクリックする時にコンテキストスイッチが行われていると思いました。私のデスクトップ画面はある程度ファイルを整頓してあるのですが、時々どこにアプリケーションのショートカットアイコンがあるのかが分からなくなります。起動したいアプリケーションは分かっているのに、そのアイコンの場所がどこかと探していると、自分がやろうとしていた作業の内容やひらめいたアイディアがすぐに頭から飛んでいってしまい、それを思い出すのに時間がかかることがあります。

 これがコンテキストスイッチに該当すると思い、私はコマンドラインを常時立ち上げ、必要なアプリケーションをコマンド入力することで起動させることにしました。Windowsであればショートカットキーでタスクバーにあるアプリケーションをクイック起動させられるのですが、数に制限があります。私は、そこをPowerShellエイリアスを作成することでクイックランチャーとしています。例えばInternet Explorerを開きたいときは、iexploreと入力することで起動できます。また、作成したエイリアスを忘れないように、PowerShellの起動時に作成したエイリアスの一覧を表示させるようにしています。何度も見ることで自然と覚えるようにしています。

 作ってよかったことは、以前、IEの起動の際に、引数としてURLを与えたところそのサイトを表示できたので、GUIアプリケーションでも引数を受け取れるのだと知ることができたことです。また、PowerShellがCMDよりも強力であることが分かり、シェル操作に慣れることができたのも良いところです。

 改良点としては、アプリケーション同士の連携が必要で複数同時に起動する必要があるときや、特別な引数を与えた状態で起動させるためのエイリアスを作成し、コマンドの使用頻度から覚えるべきエイリアスを一覧の上に、そうでないエイリアスを一覧の下に表示するか表示しないようにして、エイリアス一覧の表示を最適化する仕組みを追加すべきだと考えます。

 

 7つ目は、暗記を容易にするタイピングプログラムです。このプログラムはあらかじめ設定しておいた問題を表示し、タイピングしながら答えを入力していくことで繰り返し学習し、記憶に定着させるようにすることを目的としたものです。私が学習効率について悩んでいたころ、せめて暗記物の勉強ぐらいは楽しくできるようにしたいと考えたのがこのプログラムのきっかけです。私はタイピングをすることが好きなので、タイピングと勉強を両立できないかと考えた結果このようなプログラムを作ることにしました。

 作ってよかったことは、クラスやメソッドチェーンなどのやり方を再復習することができた点と、暗記の勉強の方法に光明が見いだせたことです。

 改良点としては、問題文と答えをプログラム内部に設定するのではなく、外部からテキストファイルやデータベース等を用いて連携させ、表示させられるようにするところと、正答率や時間などを計測し、苦手な問題や得意な問題などを区別できるようにすることです。

 

 8つ目として、これはプログラムではありませんが、発表用のスライドを作りました。私は中学の頃からずっとPowerPointを使っており、中学では所属していた科学パソコン部でPowerPointを用いて研究発表や部活動紹介を、高校では課題研究発表会で、大学ではグループ活動や勉強会などで数多くのスライドを作ってきました。そこで心掛けているのは、見ている人にとって発表を聞くのがつまらなくならないようにすることです。どの段階においても、私が使える最大限の能力を発揮して、アニメーションや視覚的に見やすいレイアウトなどを作ってきました。私の発表では、見てくれている方が必ず「すごい」や「どのようにして作ったのか気になる」と言ってくれるほどです。

 作ってよかったことは、自分の意見を周りに伝えられることができたことと、発表や教えるということが楽しくなったこと、イラストやアニメーションなどを用いて抽象的で視覚的な表現ができるようになったことです。

 改良点としては、より情報量を削減し、見てもらう人が情報を取り込むのが難しくないように配慮することです。加えて、もっと自信の発表のスキルを上げることです。

 

 ここまでで、私が作ってきたものは、自分自身のスキルアップに繋がるものや、自分以外の人の役に立つもの、そして人に自分の考えを伝えられるものです。

 

(2)それをどのように作りましたか?ソフトウェアの場合にはどんな言語で作ったのか、どんなライブラリを使ったのかなども教えて下さい。

 1つ目のノベルゲームは、ストーリーをくだらないものにはしたくなかったので、半年をストーリー作成に、残りの半年をプログラミングに費やしました。その時のチーム配属で他にプログラミングをできる人がいなかったので、ストーリーとプログラミングを一人で担当していました。その間、友達の就職活動や自身の大学受験、応用情報技術者情報セキュリティスペシャリストの勉強に加え、まじめにやろうとしない人たちへ少しでもやる気を持ってもらえるよう徐々に課題を与えて少しでも仕事してもらえるように配慮したり、他のチームへの助言などをして、本来の活動以外にも真剣に取り組みました。その代わり自分の課題は家に持ち帰ってやりました。小説は、高校入学時に、「高校卒業時には3年間の成果として何か作品を作る『課題研究』をやる」と聞いていたので、2年間かけて構想と執筆を繰り返しました。また、プログラミングも中学の知識だけでは足りないと思い、ゲーム作りから学べるJavaのプログラミングの参考書を購入し、分からないなりに勉強を進めて行きました。中学の頃からプログラミングをしていましたが、どちらかと言えば娯楽要素の色合いが強かったのを覚えています。

 少し話はずれますが、プログラミングはVisual Basicから始めました。こちらもゲーム作りで学べるという参考書を購入して勉強しましたが、当時の私にはよく分からず、Visual Basicは同じでもWordやExcelなどで動くVBAの中でプログラミングしていました。当然、参考書と同じソースコードで動くはずなどなく、なぜ動かないのか悩み、よく理解しないままソースコードの断片だけで動かそうとしたため、基本構文(if,for,while)などしか分かりませんでした。オブジェクト指向のある言語だったのにもかかわらず、そこまで行けなかったのが悔しい思い出です。

 話は戻り、高校入学時に学んだJavaでは環境構築にてこずったりしましたが、オブジェクト指向も何とか理解し、ある程度APIの使い方が分かるぐらいになりました。その参考書ではどうやら誤植があるらしく、「本に書いてあることだから間違いないだろう」と疑わなかった当時は何故ソースコードが正しく動作しないのかが分からないまま参考書の最初に戻ったりソースコードを何度も打ち直していました。後で添付されていたソースコードをコピペして動作を確認し、誤植だったことに気が付いたときには悔しかったものです。また、Java基本情報技術者の試験の際に選んだ言語だったので、課題研究の活動に本格的に入る前にオーバーロードやオーバーライドなどの違いや基本型、参照型の違い、パッケージなど様々な事を学べたおかげで、ゲーム作りで基本的なことで躓くことが少なくなりました。ゲーム作りに関しては、1年生の頃から周りに協力を持ちかけていたこともあり、多くの人が興味を示してくれて、最終的にチーム決定時には10人という当時最大の人数でゲーム作りに挑みました。同じ学科の教員の方々には「やっぱりか」といった感じで見られていましたが、同じ部活動の顧問である方が担当教員になってくださるなど、人に恵まれていたこともあり、私一人では絶対に作れないものが作れると確信しました。私はお話を考えるのが得意なのですが、絵や音楽などマルチメディアを製作することが苦手な人でした。そこで、チームを複数の部門に分けることにし、それぞれシナリオ、プログラミング、サウンド、グラフィック、PVの5つの部門に分けてそれぞれに指示を与えました。私の指示で各自が指定した成果物を作り、その成果物を私がプログラムでまとめあげるという段取りで進めて行きました。まず、予め1、2年生の段階でゲーム作りに興味を持ってくれた人に作った小説を読んでもらい、キャラクターのイメージや物語の世界観などを覚えてもらいました。次に、3年生となり本格的に製作が始まった時、グラフィック班にはキャラクターの性格や特徴、バックグラウンドなどをまとめて提供し、キャラクターデザインをしてもらいました。

また、小説を再編し、シナリオを構成して必要なイベントCGの指定を行いました。サウンド班には、ゲームで用いるSEのフリー素材を探してもらうとともに、世界観に会うようなBGMを製作してもらいました。BGMはそれぞれ使用する場面を指定し、作りやすくなるよう配慮しました。PV班には動画作成の練習からしてもらい、後で完成するグラフィック班やサウンド班の素材を用いてPV動画を作ってもらうことにしました。

 完成した素材を用いて、まずは画面遷移の設計に取り掛かりました。主にタイトル画面、セーブデータセレクト画面、チャプター画面、ストーリー画面などに分けました。また、それぞれの画面で使うGUIパーツの設計を行いました。GUIは全てGraphics2DクラスとSwingクラスから作成したので、文字列幅との調整に苦労しました。特に、ウィンドウを作るところが苦労しました。Graphics2Dクラスで文字列を描画するのですが、この時の文字列の高さにあったウィンドウを作らなくてはならなかったので、目視で文字列のフォントサイズを変更し、測りながら、それに合わせてフォントサイズを算出する式を作り、それに合わせてウィンドウの幅を調整するようプログラムしました。ウィンドウから文字列がはみ出したり、ウィンドウが大きくなりすぎないようにするのが大変でした。そこから、あらかじめ作っておいたストーリーをキャラクターと連動して表示させられるよう、テキストファイルの中に表示する文字列と制御用の文字を書き込み、実行時にはそれを読み込んで適切な画像と背景調整を行えるようにしました。さらに、ストーリーを読み進めたところを保存し、プレイヤーの基本的なデータなどと共に保存するように現在時刻やチャプターとストーリーの進捗状況などを読み込んで保存するクラスを作成しました。さらに、ストーリーのチャプターの初めにはアニメーションでサブタイトルを表示できるように、同じくGraphics2Dクラスを用いて座標を時間ごとにずらしながら、そしてただアニメーションにさせるのではなく、途中で遅くなったり、早くなったりと動きのあるアニメーションにするようにプログラムを調整しました。加えて、完成した素材が足りなかったので、背景の無い画面をせめて何か面白いものにできないかと、水面の波紋が伝わるように円を書いたり、コンピュータの世界を表現するために座標を表示させたりと、これもGraphics2Dクラスを使って前時代的なコンピュータを表現してみました。ここまででプログラムはEclipseを用いて作成し、JMFというフレームワークを音楽再生のために導入しました。

 

 2つ目の内田クレペリン生成プログラムは、まずクレペリンと言うものがどういうものなのかを調べて作ることにしました。使用した言語はJavaで、SwingというAPIを用いることにしました。まず、手始めにA4の紙を全て埋めるだけのフォントサイズと文字数をWordで確認し、その数だけ乱数を出力するようにしました。乱数は3~9の数字が出るように調整し、生成した乱数を文字列として一つずつ結合させていきました。結合させた文字列をファイルストリームに出力し、.txtファイル形式として保存させるようにしました。また、プログラムを起動したときのカレントディレクトリ下に予めログファイルを出力し、これまでに生成したクレペリンのファイルを起動するたびに確認と記録をすることで、ファイル名が被らないようにしました。ここまでのプログラムを開発するのにEclipseを使いました。苦戦したのは、使ってもらう人にとってクレペリンをやりやすい文字の大きさを測ることでした。プログラム自体は苦戦することなく作ることができたのですが、利用者の目線にあった配慮をすることを知らずに自分なりに作っていたので、フォントサイズを少しずつ変えたクレペリンを作成し、使ってもらう人に見てもらい、レビューを得てからフォントサイズを調整するマクロを記録しました。

 

 3つ目の注意力配分テスト対策プログラムは、同じくJavaを用いました。そのなかでJavaのSwingクラスでウィンドウを生成し、Timerクラスを使って時間測定を行いました。この時クラスの概念が分かったというのは、50個のボタンを一気に配置する際に、一つずつクラスの宣言を形式的に行うのが面倒に感じられたので、なにか一気に生成する方法が無いかと探っていたところ、for文でインスタンスだけを生成してしまうというやり方を見つけたことでした。一つ一つの変数にアドレスを格納するのではないやり方があったのを知り、ここからオブジェクト指向というもののやり方が分かりました。また、Timerクラスで開始時間から終了時間までの差を求め、最終的な経過時間をJFrameクラスのウィンドウタイトルに設定するようにしました。そして、押すボタンを間違えた時には、sleepメソッドで操作を受け付けないようにしました。

 

 4つ目の記号を生成するプログラムは、これもまたJavaを用いました。まず、乱数を記号の種類の分だけの範囲内で生成し、3つ目のプログラムで培ったインスタンス生成の方法を用いてボタンをグリッド上に並べました。次に生成した乱数をそれぞれの記号に関連付け、関連した記号を正解の記号の組み合わせと間違いの記号の組み合わせの文字列にそれぞれ変換し、ボタンの表示文字列として設定し、間違いのボタンには予め配列の中に間違いを示す値を格納しました。ボタンが押された時、格納された値をチェックし、間違いかどうかを判定するようにしました。

 5つ目の換字式暗号解読プログラムは、CとJavaで作りました。まず、プログラムが受け取る可能性のある文字列を一文字ずつ文字型の配列に分解、格納し、指定された値(デフォルトだと13文字)分文字をずらすようにしました。このとき、小文字・大文字の区別はそのままの状態で維持されるようにし、記号や文字として認識されないものは元の状態から変更しないようにしました。

 

 6つ目のクイックランチャーは、PowerShellを用いました。まずは、普段よく使うであろうアプリケーションの一覧をリスト化し、そのアプリケーションのショートカットや実態があるディレクトリのアドレスもリスト化しました。次に、同時に起動させたいアプリケーションやプログラムなどの組み合わせもリスト化しました。それぞれリスト化したものを、PowerShellスクリプトを用いてエイリアスを作り、短縮表現ができるかを考えながら最適なエイリアスを設定しました。

 

 7つ目のタイピングプログラムは、Javaを用いました。まず、問題と答えからなるクラスを設定し、そのクラスに必要なメソッドや動作が何かを考え、設計しました。次に問題文を表示して解答文字列を受け取り、その問題と答えが一緒かどうかを確認する、プログラムの核となるクラスを設計しました。その後、設計したクラスを実装し、表示する問題の内容を考えました。暗記物のなかでもコマンドや何かの名前を覚えるためであればタイピングしやすいと考え、それらをクラス内に実装しました。

 

 8つ目のスライドは、PowerPointを用いました。視覚的に良いレイアウトを作るために、2007バージョンからはSmartArtという機能を使うことにしました。発表する内容に合わせ、階層関係やリストなど最適なSmartArtを選択し、見栄えも良くするためカラフルに設定しました。また、SmartArtだけでは表現が難しい時、アニメーションを設定することで説明したいことの流れを分かりやすくするようにしました。アニメーションは、ただ表示させるだけでなく、一つのオブジェクトが出現したり、変形したり、消えたりを繰り返すことで、ちょっとした動画のような動きをするようにアニメーションウィンドウで遅延や同時動作をするように設定しました。

 

(3)開発記のブログなどあれば、それも教えて下さい。コンテストなどに出品したことがあれば、それも教えて下さい。

 当時ブログを持っておらず、開発記のような記録も残していませんでした。また、コンテストには出品したことがありませんでした。唯一それっぽいものがあるとすれば、1つ目に作ったものとして挙げているノベルゲームが、石川県小松市の平成27年度課題研究発表会において作品として載っています。七尾東雲高校の課題研究発表会にも作品があります(公にされているかは分かりません。最近公式ホームページの改変があったらしいので)

 今更ではあるのですが、開発記やブログを通じて自分のやったことを記録しておくことは大切なことだと実感しています。それも、自分のやったことを記録することは、自分の記憶を整理することに繋がり、学んだことを後で見返すことができたり、現状の問題点などを明確にしやすいからです。今もブログのようなものは持ち合わせてはいませんが、大学の中にある研究室のサーバーをお借りすることができたので、そこで開発記やブログを作成する予定です。今は、ブログを作るのに必要な情報や、どのようなレイアウトにするかなどを考案中です。

 

共通問題2

(1)あなたが経験した中で印象に残っている技術的な壁はなんでしょうか?(例えば、C言語プログラムを複数ファイルに分割する方法)

 私が経験した中で一番印象に残っている技術的な壁は、マルウェアの解析や、リバースエンジニアリングをツールなどを用いて行うことです。

 

 まず私は、プログラムがどのように実行されているかがプログラミング言語のレベルでしか分からなかったので、今までの勉強を頼りにしてアセンブラ言語を勉強しなければならないと感じました。それから、アセンブラ言語を勉強したその先はどうすればよいかを調べていたのですが、良く分かりませんでした。当時は、「リバースエンジニアリング」という単語を知らず、「プログラムの中のさらにその中を勉強する」という概念だけが独り歩きしていました。

 ひとまずCPUの動作について勉強し、インターネットなどで調べてようやくリバースエンジニアリングという概念が分かってきたところで、初めて技術的な壁にぶつかりました。それは、そもそものプログラムの中を見る方法が分からなかったことです。実行可能プログラムの拡張子を.exeから.txtなどの適当なテキストファイルに変更して、中身を見てみようと考えたのですが、訳の分からない文字の羅列があったことを覚えています。私がそこで見たかったのは、実行プログラムの中身であるアセンブラコードでした。最初は実行プログラムの中身はアセンブラコードだけだろうと思っていたので、意味不明な文字列の文字コードアセンブラコードを表示するための文字コードとは異なっているだけだと思い、表示方法を変えたり文字列の読み方を無理やり変えてみたりしてアセンブラコードを出そうと思っていたのですが、うまくいきませんでした。今考えてみたら文字コードを変えたとしても機械語バイナリと別物であるため意味がない上に、実行プログラムはアセンブラコードに加え実行時に必要なパラメータ等が設定されているので、変なことをしていたと思います。本で読んだ知識をどうやって生かせばよいのか分からず、実際の動作部分のコードすら判別できないというのは苦痛でした。これが、1つ目の技術的な壁です。

 

更に、ようやくプログラムの解析に必要なツールやエディタが分かったところで、解析をしようと簡単なプログラムを自分で作り、それをリバースエンジニアリングにかけようとImmunity Debuggerでプログラムを開いたところ、自分の書いたコードが一体どの部分にあるのかが読み取れませんでした。分かりやすくするためにCで書いたプログラムには自分の分かる文字列を表示させるようにしてあるのですが、その文字列がImmunity Debuggerの表示されているどこにも見たらたなかったのです。表示されるアセンブラの動作は理解できるのですが、そのアセンブラが自分のプログラムでいうどのコードを実行しているのかが分かりませんでした。プログラムのエントリポイントと言うところも良く分かっておらず、抽象的な概念しか分かってない状態で物事を進めていてはいけないと実感させられました。これが二つ目の技術的な壁です。

 

エントリポイント、実行プログラムやインポートテーブルなどの理解ができ、ようやく自分の作ったプログラムとコンパイラやリンカが勝手に作った処理との区別がつくようになったころ、私はマルウェア解析の練習のため、先輩が自作した(害のない)マルウェアを解析しようとしてみましたが、今度はツールで知りたいことを知るための手段ややり方が分かりませんでした。Win32APIを用いたマルウェアだとどのようなWin32API関数を用いているのかを知れば良い、ということは分かっていたのですが、バイナリエディタでは見つけることができたKERNEL32.DLLやMessageBoxA関数などの一覧を、Immunity Debuggerでどのように表示するかが分からなかったのです。先輩がやっているようなDLLインジェクションなどの作業をする場合インポート関数の一覧をすぐに表示できるようにしなければならないのですが、リバースエンジニアリングをまともにやったことがないど素人にはImmunity Debuggerのようなツールはあまりにも機能が豊富で協力すぎるので、まともに扱うことができませんでした。これが、三つ目の技術的な壁です。

 

(2)また、その壁を乗り越えるために取った解決法を具体的に教えてください。(例えば、知人に勧められた「○○」という書籍を読んだ)

私が取った解決法は大きく分けて二つあります。1つ目は物事の根底の事象から不明確な事象をなくしていくということです。私が解析しようとしたのはWindows上で動作するプログラムで、ゆくゆくはWindows上で動作するマルウェアも解析したいと考えていました。そのためにも、OSとその上で動作するプログラムの仕組みを理解する必要がありました。そこで高校の頃まで馬鹿にしていたC言語を見直し、ポインタやメモリに関する事を再度復習しました。C言語の学習には「詳説 Cポインタ」という書籍を用いました。この本を読んでポインタに関する理解やバッファオーバーフローなど解析に関連する他の分野のことも学ぶことができました。また、発行元のオライリー・ジャパンつながりで「アナライジング・マルウェア」、「リバースエンジニアリング」「デコンパイリングJava」などArt Of Reversingシリーズ中心に様々な書籍を読みました。この本でリバースエンジニアリングに必要なツールや便利なプログラムを知ることができました。特に、WindowsのプログラムはPEヘッダーの理解がかなり重要だったので、アナライジング・マルウェアの存在はとても大きく、そこに載っているプログラムやサイトを漁ることである程度の知識を身につけることができました。他にも、「HACKING:美しき策謀」や「リバースエンジニアリングバイブル」、「楽しいバイナリの歩き方」、「デバッガによるx86プログラム解析入門」なども読むことによってリバースエンジニアリングに必要な知識や分かってきました。また、マイクロソフトの発行している「インサイドWindows」という書籍やMSDNなどの公式の情報を頼りにすることで、Windowsがどういった仕組みで動いているのかを調べました。他にも、CPUの動きを掴むために「コンピュータシステムの理論と実装」という書籍も読みました。これらの書籍を読むことで、コンピュータサイエンスの知識を深く掘り下げられた気がします。更に、インターネット上で見つけた「Reverse Engineering for Beginners」というPDFを見つけたので、それも翻訳しながら読んでいます。また、リバースエンジニアリングの書籍内容でデバッガを作るという内容に挑戦していたところ、x86の環境下でないと動作しないコードがあったので、その点についてはVMwareをインストールし、大学で締結しているDreamSparkからWindows 7の32bit版をダウンロードすることで対処しました。また、書籍やインターネット上の知識が英語ばかりになってきたので、英語の勉強もしました。まだわからない単語や文法、表現があるので、今でも勉強は続けています。英語を読むことが大切なのだと身に染みました。

 2つ目の方法は、人に聞くということです。すごく単純な方法だったのですが、私にはそれができないでいました。というのも、人に聞くのは自分にとって「敗北」を意味するからと人に聞けなかったのです。今、私はセキュリティのプロジェクトに所属しているのですが、そこにはWindowsマルウェア解析に関する技術にとても長けた先輩の方がいます。その人に聞くのもありだったのですが、私は「きっとこの人は自分なりに色々とやってみて、分からないながらも模索しながらここまでたどり着けたのだから、私もそうしなければこの先通用しないのではないか」と考えていました。そして負けず嫌いな性格とちっぽけなプライドが邪魔をして、誰にも聞かず、一人で黙々と進めればよいと考えていました。しかし、そううまくいくはずもなく、技術的な壁に遭遇してしまい、どうすることもできず悩んでいました。このままではいけないと、何かやり方を変えなくては前に進まないと思い、プライドを捨てて聞いてみることにしました。先輩の方は、嫌な顔一つせず私の疑問を解消してくださいました。聞き終わった後、私はこんなに単純なことで済むのかと今までの時間がとても無駄に思えてきました。そこで悟ったのは、一番恥ずかしいのは聞くことじゃなく、知らない事だということです。いつまでたっても意地を張り何も知らないまま役立たずになるよりも、恥を捨てて素直に分からないと良い、教えてもらって理解できればそれでいいと思います。ある程度は自分で考えて自分で模索しなければなりませんが、先に進めない状態というのが一番ダメな状態だと思います。

 また、先輩や友達から聞く話だけでなく、彼らがお勧めする書籍などを読むこともしてみました。私だけでは知りえなかった書籍がたくさんあり、もっと早めに知っておけばよかったと思うほど良い書籍もありました。先人から習うというのもいいですが、やはり良書に出会うというのもまた良いものです。

 

(3)その壁を今経験しているであろう初心者にアドバイスをするとしたら、あなたはどんなアドバイスをしますか?

私がアドバイスを送るとすれば、以下のアドバイスを送ります。

 ①いきなり全てのことを学ぼうとしないでください。何かの技術(この場合はリバースエンジニアリング)をマスターしたい気持ちは分かりますが、それではいけません。周りの人たちがとてもその分野に長けているからと言って、焦ることはありません。最初はできる事から、あるいはできそうなことから始めてください。ハードルを高く設定するのは良いことですが、無理をして理解が難しい書籍を勉強したり、実際のリバースエンジニアのように短時間で高度な解析ができなければならないと思わないでください。大切なのは、自分が将来着実に能力を手に入れていることです。高すぎる目標の前でずっと苦戦して、なかなか知識や技術を手に入れられないようではいけません。常に自分自身が達成すべき適切な目標を考え、着実にレベルアップすることを心掛けて下さい。もちろん、勉強することがどうしても最初から難しいことだってあるでしょう。そんな時は、「分からない」と思うことを「何が分からないのか」と考え直し、それを明確にすることで、大きな問題を小さな問題に分解してください。そして、その小さな問題を少しずつ分かるようにしていって下さい。

 ②臆することなくまず手に入れた知識を実践してほしいです。どんな些細なことでもいいから、まずは自分自身のI/Oの力を強化し、少しでも何かに応用が効かせられるよう体に知識を刷り込ませてほしいです。本を読んでばかりでは何も進みません。教養を得るのは良いことですが、それを活かさなければ宝の持ち腐れになってしまいます。だからと言って、実践にこだわりすぎず、時には理論も大切にしてください。理論と実践のバランスが必要です。

 ③広く情報を収集してください。インターネットには様々な情報が落ちています。しかもそれは殆ど無料で手に入ります。お金のかからない勉強はとても良いものです。失うものは何もないのですから、とにかく情報を収集してください。また、情報を収集した後は、その情報を整理する必要があります。一度手に入れた情報は体系的に揃えることでより記憶に残ります。そして得られた情報で何かをやってみた後は、また情報収集してみてください。一度情報収集したからと言って満足せず、新たな情報を貪欲に集めてください。

 ④英語や数学などの基礎学力を疎かにしないでください。私は工業高校出身なのでそういった基礎学力が遅れています。私は当時情報系の勉強をひたすらすればいいと考えていました。ですが、大学に入学してからというものの、高度な情報系の勉強をするには英語や数学が前提条件として必要なのだと思い知らされました。今回のリバースエンジニアリングの例で言えば、Reverse Engineering for BeginnersやMSDNを読み解く際に英語力が必要になりました。英語は好きだったので翻訳しながら読んでいくのは苦痛ではありませんでしたが、もう少し真面目に英語の勉強をしていて英語力が備わっていれば、より効率よく情報を手に入れることができたと考えています。この例に限らず、新たな技術の発展は主に英語圏で行われることがほとんどですし、情報発信も最新の情報を手に入れるには英語が必要です。普段から英語に触れるなどして、慣れておいてください。最近ではTEDのアプリなど英語を学ぶ環境は非常に豊かになっています。だからと言って、完璧な英語力を求めてはいません。ある程度文章の内容が理解できる程度で十分です。必要以上に時間を割いてリバースエンジニアリングの勉強ができなくなるのでは本末転倒です。

 ⑤良い友人や先輩、先生と巡り合ってください。どんなに頑張っても、必ずどこかで行き詰ることがあります。いつまでも意地を張らず、素直に聞くということをしてください。直接その問題に対する答えが出るとは限りませんが、ヒントぐらいは得られるはずです。そして、競い合う仲間がいてもいいと思います。勉強を一人でただひたすら続けるのはモチベーションを維持するのがそう簡単ではありません。悔しいと思いながらでもいいですから、やる気を保ってくれるライバルのような存在を見つけてください。仮にライバルに負けていたとしても焦る必要はありません。負けていると感じるならば、自分が足りないものは何なのか、相手の長所を見つることも重要です。ライバルの存在は、きっと自分の能力をより高みへと導いてくれるはずです。

 ⑥勉強会やプロジェクト活動には積極的に参加してください。④と似たようなことなのですが、良い人を見つけるのに一番手っ取り早い方法は似たような考えや目標を持つ人の集まりに参加することです。幸い、今は勉強会と言うものが全国各地で行われています。その中でリバースエンジニアリングに関する勉強会も存在するはずです。そこで出会える人たちとコミュニティを形成することで、様々な情報交換をしてください。

 ⑦ここからのアドバイスは技術的な内容になります。まず、コンピュータサイエンス全般に関する事を学んでください。私は基本情報技術者応用情報技術者などの書籍を読むことで学習しました。これはリバースエンジニアリングとその後に繋がるマルウェア解析のために学んでほしいです。これが分からないとどの書籍を読んでも全体像すら掴むことが難しいため、絶対に学んでほしいです。資格の勉強にもなりますし、得られる情報はとても幅広いものです。決して損はしません。

 ⑧C/C++プログラミング言語を学んでください。Pythonのようなきらびやかな言語を学んでセキュリティを勉強するのもよいのですが、やはりC/C++はセキュリティの基礎的なことを知ることができる良い言語です。それは言語上の特性が脆弱性を多く秘めているということにもつながるのですが、自分で実践するには良い言語です。メモリの内容を直接操作することができる上、ポインタという概念にも触れることができます。それを学ぶ上での書籍が多いのも事実ですし、WindowsのほとんどがC言語で書かれているという事実もあります。Windows上で動くプログラムを解析したければ、Cという言語は必須ともいうべきです。もちろん、Pythonでも勉強することはできますので、一通りC/C++に慣れたら、Pythonや、他の言語を学ぶこともお勧めします。

 ⑨アセンブラ言語を学んでください。C/C++という高級言語を学んだら、次はCPUに近い言語を学んでCPUの動作を覚えてください。ここに来ると書籍が一気に少なくなり、内容も複雑になってくると思われます。しかし、やっていることは単純な動作の繰り返しです。アセンブラを読み解くときは、落ち着いて、確実に動作をトレースしてください。細かい動作を理解しないまま焦って一気に読み飛ばそうとすると後々躓きます。

 ⑩PEヘッダーなどのWindows固有の事柄について学んでください。リバースエンジニアリングをしようと思ったのなら、その対象となるプログラムが動く環境のことについても知る必要があります。特に、PEヘッダーにはプログラムを動作させるうえで重要な情報が大量に記されています。PEヘッダーに記されているそれぞれの数値の意味を知ることはプログラムの動作を学ぶ上でひらめきと発見をするための道のりであると考えています。また、WindowsというOS自体の勉強をすることもお勧めします。マルウェア解析において、マルウェアは外部との通信を試みる場合など動作は多岐に渡ります。その時、どのようなハードウェア資源にアクセスしどのようなことを行っているのか、などを知る必要があります。その上、WindowsAPIの理解も必須です。マルウェアは自身が解析されているかどうかを調べることもあれば、ウィンドウの生成やファイルへのアクセスなど、様々なことにWindowsAPIを利用するかもしれません。プログラムとAPIの仕組みについても理解することが重要になります。

 ⑪ツールの使い方を学んでください。ツールから全て自作するぐらいの力があるのは良いことですし、また深く知識や技術が身に付きますが、自作でもしない限り達成できないと言わないのであれば、既存のツールを用いて目的を成し遂げた方が効率的です。ツールの製作に時間を費やすのではなく、あなたがやるべき目的の本質に時間を費やしてください。良いツールがたくさんあるのに、それらを使わないのはもったいないです。また、ツールは一つだけとは限りません。デバッガの例で言うと、WinDbgやImmunity Debugger、OllyDbgなど種類は様々です。どれも一長一短ありますし、どれを使うのが正解ということはありません。状況に応じて使い分けができるようになってください。また、ツールはショートカットキーが豊富です。GUI操作は可能な限り避けて、ツールに設定されているショートカットキーを積極的に使いましょう。

 

共通問題3

(1)あなたが今年のセキュリティ・キャンプで受講したいと思っている講義は何ですか?(複数可)

 そこで、どのようなことを学びたいですか?なぜそれを学びたいのですか?

 私が学びたいと考えているのは主に低レイヤーに関することですが、ネットワークや検知など全てのことについて学びたいと考えています。ですが、それではけじめがつけられないと思ったので、キャンプの時間割を考えてみました。以下はその時間割とその理由です。

 

■1-D Dissecting Malware - x86 Windows malware analysis -

 マルウェアをひたすら読み解くというのが一番のポイントです。私はプログラム(マルウェア)解析のため書籍を読んでいますが、実力不足でどれも実践ができないことが多く、いざ解析をしようと思ってもツールの具体的な使い方や、自作デバッガでのアタッチの方法が分からない、あるいは知りたい挙動を見つけられないなどできないことが多くあります。マルウェア解析はセキュリティの企業をもってしても日々開発される亜種の数に追いついていないと聞いたことがあります。その膨大な種類のマルウェアを解析して少しでも追いつきたいのですが、それ以前にマルウェアを解析する実力が無いのでは話になりません。勉強していても、エントリポイントにたどり着いた後にトレースしてもコードのどの部分を見なければならないのかよく分からなかったという悔しい思い出があります。私はそれがとても恥ずかしいことに感じられます。書籍で身に付けた理論が分かっていても、実践で解析できないのでは笑われると思っています。私がこの講義で得られると考えているのは解析技術の経験です。経験を通して初めて分かることがたくさんあるのは他の講義でも同じですが、ナイーブな場所故に様々な解析上の障壁があるはずです。そういったことは実践で初めて得られると思われます。逆アセンブルコードを読み解くとありますが、講師の方が膨大な数のコードのどこに注目して、どのような手順で効率良く進めて行くかを一番学びたいです。私が考えるに、マルウェア解析は要点を絞ると観察すべき場所が少なくなるのではないかと思います。そのためにはまず、その「要点」を知らなくてはなりません。講師の方も「効率良く」と強調されているので、要点がどこかに存在するはずです。また、そこでツールなどを用いるのであればその使い方も学びたいです。手動で読み解けていくことも大切な技術ですが、ツールを使って効率的に進められることがあるのであればそのテクニックや使い方や連携方法なども学びたいと考えています。他にも、実際のマルウェアを解析する点で躓きやすい点も学びたいと思っています。マルウェアは難読化されたり、パックされたりしてリバースエンジニアリングの対策を講じているはずです。それを見越し、アンパックや難読化されているコードに対する読み方、考え方なども知りたいです。加えて、マルウェアの典型的な挙動や動作なども知りたいと考えています。様々なマルウェアが存在するとはいえ、ほとんどは特定のマルウェアの派生形だと聞いたことがあります。その元となる動作を知り、様々なマルウェアが行っている一般的な動作を知ることで、解析できるマルウェアの幅を広げたいです。これらの経験を積むことで、今後一人でも解析を進めて行けるための基礎地盤としたいと思います。

 

■2-A スマートフォン向けゲームのセキュリティ

 私も含めて殆どの人が所有している為、学んだことを応用させやすいと思ったのがポイントです。技術が普及し、小学生でもスマホを持ち歩くようになりました。それだけターゲットが増えたことも意味します。しかし、エンジニアならともかく、小学生などの知識がない人に技術的対策を教えるのは無理があります。知識や技術はないけど、ゲームをプレイするユーザーは多いという状況は私が考えるに最悪の状態だと思います。付け込まれる可能性が高い以上、そこに注目した対策を知りたいのです。この講義には通信解析がキーワードとして挙げられています。膨大な数のパケットの中でどのようにしてその通信を突き止め解析するのかが予想が付きません。専用のアナライザや、サーバー側に何か埋め込むのか、など詳細な手順を伺いたく思います。そして、ツール群で通信内容をある程度絞っても、関係ない通信パケットは大量に存在するはずです。解析をする際に、講師の方が脳内でどんな通信をフィルタリングしているのか、どこの通信に注目しているのか、どういった内容の通信が危険だと考えているかも伺いたく思います。また、通常のLANの環境下だけでなく、スマートフォンという通信端末も通信内容を解析できるようになりたいと思っています。ゆくゆくは、様々な通信環境下でも通信を解析できるよう経験を蓄えたいです。加えて、スマホのアプリもリバースエンジニアリングするのが楽しみです。いずれモバイル端末のアプリ解析が主流になると思われます。x86などの環境下で動くプログラムの解析も必要ですが、Javaなどのバーチャルマシン上で動く中間言語リバースエンジニアリングも今後必要になると思われます。そういった点でもこの講義は見逃せないと思います。気になっている点は他にもあります。ゲームのセキュリティとは一体何かと言うことです。今まで脆弱性と言うのは業務システムのようなもので見つかるのが一般的だと考えていました。ゲームでも脆弱性は起こり得るとは思っていましたが、それは「バグ」のことなのか、仮にバグだったとして、バグの中でどうやってセキュリティを脅かすような事態に発展させられるのかが気になるところです。

 

■3-C 脆弱性検出実践(ファジング技術と脆弱性報告)

 いずれ何らかのソフトウェアを開発することになるでしょうが、完璧にセキュリティを意識して開発するのは困難です。ですが、受けやすい攻撃パターンなどを逆手に取り、それに関する脆弱性を重点的に埋めていくという手法に魅力を感じています。と言うのも、私は今のセキュリティ技術者がなるべく不必要な知的労働を避けて本来の重きを置かなければならない業務に集中できれば良いと考えています。もし私が企業の中で技術者に対して仕事を与える立場にあるならば、セキュリティ技術者がパフォーマンスを割いて一つ一つ脆弱性を調査していくのは、その人のやるべきことではないと思います。全体からすれば、もっと複雑で解析が困難なものに仕事を割り当てたいと考えます。ファジング技術は機械的に攻撃することで大まかな脆弱性を洗い出すことができるので、私もその技術を習得したく思います。数多く開発されるソフトウェアに追いつくためには、ファジング技術は必須の技術だと考えます。また、脆弱性報告の仕方を実践できるとあり、私もセキュリティ界に少しでも脆弱性報告で貢献したいと思います。また、脆弱性の情報はJVNや各種メーリングリストで公開されています。その様な情報があるにもかかわらず、私はそれを見ても断片的にしか内容を理解することができません。折角良い情報が流れているのにそれを吸収できないのはもったいないです。だからこそ、この講義を活かして、JVNや各種メーリングリストから配信される脆弱性情報を読み取れるようになり、日々更新される情報や更なる脆弱性への知識を深められるようになりたいです。またこの講義ではIoT機器に対するファジングを行うとありました。通常のアプリケーションに対するファジングであれば恐らく一人でも勉強は難しくないと考えます。ですが、IoT機器では実機を揃えたりファジングするにも労力とコストを要します。IoT機器の何をファジングすればいいのかなど、学生でいるうちには中々経験できないことがこの講義には詰まっていると思われます。これは、IoT機器もファジングしなければならない時代が近いと捉えることもできます。この講義を受けて、様々な製品でもファジングできるような技術を習得したいと思います。

 

■4-A クラウドセキュリティ基礎

 クラウドという仮想化技術をサーバ設計や構築などの管理側から関われるというのが私にとって重要なポイントです。今までクラウドのサービスを受けることしかできず、開発に関わる機会は全くありませんでした。ですが、この講義ではそれが学べるうえ、その上セキュリティを意識することができるのが大きいメリットです。私は大学に入学するまでインターネット環境が無く、Webという分野に触れることができず、理論的な部分しか学べませんでした。周りよりもインターネットに関わる知識が乏しいため、積極的にサービスを使ってはいますが、それでもまだ利用者側の視点でしか物事を取られません。この講義ではインターネット関連技術を構築側の視点で学ぶことができ、加えてクラウドについても学べるので、数多くの知識を吸収することができると考えます。また、今後クラウドありきのシステムが一般的になるでしょうが、クラウド上のサービスに脆弱性があった場合、そこを突かれてしまうと他のサービスやクラウドそのものが脅威にさらされるというのを学んだことがあります。クラウドにサービスを集約していると、クラウドを利用している自身だけでなく、他人にも迷惑をかけることに繋がりかねません。クラウドのセキュリティを確保することは、クラウドユーザをひとまとめにセキュリティを確保することができるというメリットになると考えられます(情報資源などを一つの場所に集約することが良いこととは限りませんが、効率とセキュリティの両方の面をバランスよくとっているものだと考えます)。いずれクラウドにも関わるかもしれないので、クラウドとそのセキュリティについて学ぶのは重要であると考えます。また、クラウドといえど動作しているのはあくまでサーバ上です。サーバについて本格的に学ぶにしても、予め動作している大学の研究室などのものを借りたりするか、特別なことが無い限り難しいと思います。ですがこの講義ではサーバについて設計から学ぶことができるとあります。この講義で得られる汎用性のある知識や技術を習得し、それらを活かして総合的にサーバ管理ができるようになりたく思います。また、これからも登場する新しい技術のセキュリティを学ぶための入り口としたいと考えています。

 

■5-B USBメモリからブートしてみよう

 OSのブートが様々な媒体やネットワークからできることは知っていましたが、そもそもOSが無い状態でも起動できるということを初めて知りました。ですが、OSはハードウェアをコントロールした上でアプリケーションを動作させているはずなので、どういったことをすればカラフルな画面が映し出せるのかとても知りたいです。恐らく、アセンブラを使ってハードウェアを操作する具体的なやり方が学べるはずです。アセンブラ言語を機械語に変換するというのは、アセンブラ言語と機械語の対応を学び、且つCPUの構造の理解にも一役買うのではないかと考えます。また、リバースエンジニアリングではアセンブラ言語の動作を頭に染み込ませておく必要があるので、アセンブラ言語を構築するというのは一番効率の良い学習法でもあると思います。そして何より、BIOS機械語などよりハードウェアに近い技術が学べるのはこの上ない機会です。私が考えるに、特定の環境が揃っていないと何もできないエンジニアではこの先生き残っていけないと思います。ある程度、自前で何かを作り、自分の技術力のみで与えられた業務を遂行できるような人材でなければならないと考えます。その点からして、OSの無い環境や、BIOSを自由に操れることは重要だと考えます。この講義ではUSBメモリでブートするというのがとても汎用性のある技術のように感じられます。USBデバイスは殆どのPCに搭載されており、この講義が終わった後に自分でUSBメモリのプログラムを書き変え、自分なりにアレンジすることでよりOSとBIOSに触れ、理解を深めることができると考えます。また、自分たちでOSが無くとも動くプログラムを作成するということは、それ自体がOSのような役割を果たしているのだと思います。つまり、自作OSを作る練習になると思われます。自作OSは兼ねてから作りたいと考えていたので、ハードウェア資源の管理方法を学ぶ良い機会になると同時に、低レイヤーと高レイヤーをつなぐための仕組みや関連、デバイスドライバについての理解なども深めることができると考えます。現在、私はインサイドWindowsという本を読んでいますが、ハードウェアとソフトウェアの両方の知識があるとより理解しやすいのだと感じました。私は、この本を読む際の理解の手助けになるような知識をこの講義で得たいと思っています。

 

■6-D リバースエンジニアリングを自動化せよ

 自動化と言う技術にはいつも惚れ惚れするほど惹かれる言葉ですが、そもそもセキュリティエンジニアが解析しているマルウェアやアプリケーションをそう簡単に自動化することは困難なはずです。しかし、人間のやる作業の中でも形式的にやっていることや同じことを繰り返していることも多くあるはずです。その点では自動化は不可能ではないと思いますが、この講義ではそれだけにとどまらず、脆弱性発見にも応用すると書かれています。つまり、解析や脆弱性の発見を自動化することができるということは、それだけ解析時に注目すべきポイントが存在しているということです。少なくとも、講師の方は頭の中でルーチン化された作業を確立しているはずなのです。私は、講師の方の頭の中で自動化している部分が一体どんなものなのか、パターン化されている脆弱性にはどんなものがあるのか、そして自動化する際に用いるツールやプログラムは一体どんなものなのかを知りたいです。他にも、先進的なソフトウェア解析技術と言うものの中に、普段私たちが知りえないような技術が含まれているのかと思うと、興味の域を超えてワクワクするものがあります。自動化の技術はソフトウェアやマルウェア解析に留まらず、他の分野の自動化にも応用が効くと考えています。これからたくさんのマルウェアの解析をしていくでしょうが、恐らく何度も似たパターンのマルウェアに遭遇するはずです。それらの解析を自動化し、実行動作が違っている部分だけに集中して、様々なマルウェアについての知識を効率よく吸収できるようなツールを自作できるよう役立てていきたいと考えています。また、VirusTotalのようなマルウェアの情報があるサイトでまとめられている概要報告の情報も素早くつかむことができると考えています。とにかく、この講義には講師の方の「マルウェア解析経験」が凝縮され抽出されていると思われます。そのようなとても質の高い情報を得られる講義はそう巡り合えるものではないはずです。私は、1-Dの講義と合わせて勉強することで、マルウェア解析のスタートアップと加速を推し進められると思います。そして、今もなお活躍しているマルウェア解析技術者と肩を並べられるような解析ができる技術力を備えるよう強力な成長を遂げていきたいと考えています。

 

 

■7-B 組込みリアルタイムOSとIoTシステム演習

 リアルタイムOSという、制約の厳しいOSを学ぶ際、理論を分かっていても現実の更なる制約を学ばなければ、本当に組込みリアルタイムOSを学んだことにはならないと考えます。ですが、そのようなシチュエーションは自分で想定できるものではなく、設計・製作するのにも膨大な時間がかかると思われます。この講義では、それを実機で学ぶことができるというのが大きな魅力に感じられます。理論的な部分だけでは得られない、実践的な内容だからこそ得られるものがあり、そして質も量も良い知識と技術が得られると考えます。実機とは一体どんなもののIoTなのか、実例を知れるチャンスでもあります。それだけではなく、組込みリアルタイムOSと通信ミドルウェアの連携について学べると考えています。コンピュータの重要な機能である通信を、リアルタイムOSがどのようにして調整を図りながらデータを送受信させているのかが知りたいです。この講義の良い所は、実機の練習でありながら、ソフトウェアを中心に知ることができるという点です。私はハードウェアについての知識が未熟で、どちらかと言えばソフトウェア寄りです。そんな私にとってソフトウェアの面から学ぶことができるというのが大きなメリットです。また、私は通信ミドルウェアの動作がどのように行われているかが気になります。WireSharkのようなアナライザを使ってパケットを解析するのは良いのですが、それはあくまで受け取った通信の内容のみで、その通信自体を構成している通信ミドルウェアの動作がどうなっているのかまでは知ることができません。ただデータとして表示されている内容を解析して満足するのではなく、どういった動作をして初めて通信が成り立っているのかを知りたく思います。他にも、組込みリアルタイムOSはOSです。基本的な考えはどのOSにも共通して言えるはずです。つまり、全体としてOSの理解も深めることができると考えます。この講義で私はコンピュータアーキテクチャコンピュータサイエンス全体に関することについて学べると思っています。そして、コンピュータそのものを作ることができるための布石を置き、更なるコンピュータアーキテクチャ・サイエンスの理解に繋げていきます。

 

 この他にも、様々な講義を学びたいと思っています。楽しいバイナリの歩き方という書籍の著者である愛甲健二さんの講義は気になるところです。ヒューステリック技術が大体どのようなものかは理解できるのですが、具体的にはどういったプロセスを経て検知を行っているのかが気になります。そして、集中講義の「なぜマルウェア解析は自動化できないのか」という講義も興味があります。6-Dの講義と相対するような内容なので(最終的にはどちらも「可能の限界」に至りますが)、二つの講義の主張を突き合わせてみたら面白いことが生まれるのかもしれません。

 

 この時間割で私が目的としていることは、総合的な知識をまんべんなく取り入れることです。なるべく特定の分野に偏らないものにしました。それは、今後幅広い視野と可能性を見失わないようにするためです。どの講義も受けてみたいですし、欲を言うなら全部の講義を通してたくさんのことを学習したいです。今の私に必要と考えているのは、今後の活動のために必要な知識の地盤固めです。これをしっかりして、更なる応用につなげていきたいと考えています。

 全体を通して私が学びたいのは、理論だけでは得られない知識と、生の環境と実践を通した体に染み込む技術です。

 

(2)あなたがセキュリティ・キャンプでやりたいことは何ですか?身につけたいものは何ですか?(複数可)自由に答えてください。

 私はセキュリティ・キャンプで、とにかく分野に縛られず色々なことをやってみたいです。まずはリバースエンジニアリングマルウェア解析についです。私は物事の根底にある事象に興味があります。情報機器以外で言えば原子や分子、メタ認知などと言ったことです。コンピュータでは、ソフトウェアの一番の原子である機械語レベルについて学びたいのです。機械語の詳細な手順や動作だけであれば市販の書籍やデベロッパーズマニュアルなどを読めば済みますが、それを「利用していること」については書籍だけでは限界があります。つまり、(機械語に限らず)仕様の弱点を見つけるための技術や知識などが必要であり、私はそれをとても知りたいです。脆弱性というのも、仕様の中で製作者が予想もしない事だと私は考えます。そういったことを知るためには、実際にリバースエンジニアリングマルウェア解析をしてみるというのが一番です。そして物事の根底と言うのは色々な部分に応用が効かせやすいものです。高レイヤーで動くアプリケーションも、最終的には低レイヤーの機械語に落とし込めます。どんな些細な動作も低レイヤーの視点から見ることでしっかりとその動作を捉えることができます。その動作を捉えるためにも、リバースエンジニアリングマルウェア解析はとても良い「関門」なのです。何かのプログラムには、何かの目的や存在意義があり、それを突き止めるにはその製作者がどのレイヤーからの視点にいても対応できる必要があります。一番下のレイヤーからの技術や知識を得ることで、製作者の意図を知ることができます。他にも、以下に続くハードウェア全般のことに繋がりますが、低レイヤーを知ることは、コンピュータを制することに近いと考えています。だからこそ、リバースエンジニアリングマルウェア解析などを行い低レイヤーを熟知するための糧としたいのです。

 次に、ハードウェア全般についてです。ソフトウェアはハードウェアありきで動いているので、ソフトウェアを知るにはハードウェアも知らなければならないと思います。私の物理に関する知識は乏しいですが、そうでなくとも最低限情報機器がどうやって動いているのかと言ったところまでは身につけておきたいのです。いずれ、IoTの時代が最盛期になった時、家電などの従来の組込みシステムに限らず、そもそも電気で動いていないものも情報機器が搭載される時代が来るはずです。たとえば、インターネットに繋がった椅子や机などが開発されてもおかしくないはずです。そういった時、ソフトウェアの面でしか開発に携われないとしたら、それはとても歯がゆい思いをするはずです。

「私はソフトウェア専門なので…」という言葉を言い訳にしたくないのです。そんな思いをしないよう、予めハードウェアの部分にも触れておき、電子機器や様々な媒体がどのような仕組みで動いているのか、そしてその技術を用いてどんなものでも開発できるようにならなければならないと考えています。更に、IoTは様々なモノへのサイバー攻撃も助長するはずです。例えばですが、真夏の熱帯夜の中、IoTでインターネットに繋がったエアコンが外部から攻撃を受け、操作を乗っ取られたとします。もし悪意ある者が殺意を持ってしてエアコンの設定温度を暖房あるいは高温に設定した場合、正規の利用者は暖房により脱水症状などの身体的損傷を受けかねません。また、仮に人間に害がなかったとしても、エアコンの内部では熱によって精密部品などが損傷あるいは破壊されるかもしれません。こういったことにはソフトウェアの部分からも対策を立てる必要はあるでしょうが、それだけにとどまらずハードウェアからの対策を立てることも重要です。ハードウェアの知識があるだけでも、セキュリティ上の対策の幅が広がるはずです。つまり、私達の生活を豊かにするありとあらゆるものが、私達に牙をむく武器にならないような事前の対策を打てるよう、ハードウェアというものを知らなければならないのです。また、最近ではソフトウェアではなくハードウェアに感染するマルウェアが存在するようです。私の知っているのはUSBデバイスのハードウェア部分に感染し、全てのUSB間の通信内容を知られてしまい、一度感染すると専用の装置を使わない限り削除は難しいという恐ろしい動作をするマルウェアです。どこの国の陰謀とか、そういうところも気になりますが、我々一般人には手の届かないマルウェアという存在に非常に驚きました。私がハードウェアに関する知識も必要だと考え始めたのは、このマルウェアの存在がきっかけです。ソフトウェアの方面だけを勉強していても太刀打ちができないと感じたからです。しかし、ただ勉強するだけなら誰にでもできますが、勉強と言うのはあくまで理論的な部分が多く、実践では理論通りにうまくいかないことがあります。そういったことも含め、実際に触れて理解し、体に染み込ませるといった意味でも、ハードウェアに関する講義などを受けてハードウェア全体の知識と技術を身につけたいのです。

 

 もちろん、低レイヤーに限らず高レイヤーのことについても学びたいと思っています。高レイヤーは利用者に一番近い部分です。WebアプリケーションやSQLなどはとても便利ですが、利便性とセキュリティの強度が両立できないように、私は便利=危険という見方で捉えています。開発環境や新たな技術が生まれやすいこともあり、続々と良いWebアプリケーションなどが開発されていますが、時代がスピード開発を求めていることもあってか、脆弱性がより多くなりがちです。だからこそそこを狙う者も多くいるはずです。ネットワークを介するだけで比較的攻撃がしやすいこともあり、よくニュースで企業のWebサイトなどが改ざんされるなどの被害に遭うことを目にします。ではこの高レイヤーな部分を勉強しなければならないと思うのは当然ですが、種類が多く、どれかのWebアプリケーションなどに絞って知識を蓄えるというのは非効率的です。だからこそ、

Webアプリケーションに共通する骨格部分の知識を学ぶことが重要だと考えます。Webアプリケーション全てを5日で学ぶのは不可能だとしても、それぞれに共通している部分を学ぶのは困難ではないはずです。私は高レイヤーについての知識が低レイヤーに比べて乏しいので、この範囲の知識をすぐさま補わなくてはという使命感も感じています。スマートフォン向けのアプリが日々開発されているため、それに合わせて脆弱性も様々なものが現れているはずです。PC上で動くアプリケーションにも同じことは言えます。ですが、共通する技術があるように、共通する(似たような)脆弱性もあるはずです。そういったことを学び、たとえ多種多様な脆弱性がこの先現れたとしても、それに対応できるように知識や技術を身につけておきたいのです。また、共通した知識は共通していない知識を吸収するための呼び水になるため、学習効率を少しでも上げられるようにしたいです。

 

 低レイヤーや高レイヤーについて学びたいとしましたが、私は中レイヤーのことも学ぶ必要があると考えています。低レイヤーと高レイヤーの中間に位置するレイヤーを中レイヤーと呼ぶのかわかりませんが、ここではそう呼ぶことにします。その中レイヤーがネットワークの分野なのか、コンピュータアーキテクチャの分野なのかは問いません。とにかくこの中レイヤーについても熟知している必要があると思われます。ほとんどの入門書では中レイヤーに関する事はあまり取り上げられていません。上と下のレイヤーをつなぐ部分はそれだけ複雑な機構を備えていることが多く、たいていの場合は極端に上のレイヤー(あるいは下のレイヤー)からしか学ばないからです。プログラム全般について例を挙げると、各種プログラミング言語(高レイヤー)や機械語(低レイヤー)については様々な解説書や勉強ができますが、コンパイラ構文解析などと言った部分に関する情報は比較的少なめです。非常に高度で学術的な内容であっても、そこを攻撃されてしまう可能性はゼロではありません。仮に攻撃された場合、対策もそう簡単ではないはずです。そこを専門とする人材もそう多くないと考えられます。今回私が共通問題3-1で様々な分野の講義の受講を希望しているのは、高レイヤー、低レイヤー両方から学習を進め、中レイヤーの勉強をするための地盤を築きたいからでもあります。

 

 

 技術的な面から外れますが、私はグループワークというものにも興味を持っています。講義の中もグループ単位で行うものはあるらしいのですが、そもそもセキュリティについて学ぶ上でグループワークと言うものがどういう風に機能するのかがとても気になります。私は、セキュリティの仕事(もしくは勉強)は一人で自分と向き合いながらもくもくと進めて行くイメージがあります。誰かに教えてもらうにしても、最終的にパソコンと向き合っているのは自分一人です。だからこそ、セキュリティ・キャンプでグループワークを行うというのは、一体どんなことをするのか気になります。仮にセキュリティを学ぶ上でグループワークでしかできない事、もしくは一人でもできるがグループワークにすることもできる事など、そういうことがあればぜひ学びたいです。私は今、学校内でセキュリティに関するプロジェクトや自身で開いている勉強会に参加しているので、私がセキュリティ・キャンプで学んだグループワークを積極的に活かし、プロジェクトや勉強会の成長に役立たせたいと考えています。もしかしたらセキュリティとはあまり関係なく、友好を深めるという目的のものかもしれませんが、それでも楽しみです。むしろ友好を深める目的でもいいと思っています。様々な考えを持った人に出会えるのは自分にとって良い刺激になる上、いわば競い合うライバルのようなものができます。私は負けず嫌いなので、競い合う相手ができた方がより勉強に打ち込むことができます。競い合うどころか、私の実力不足で既に差が開きすぎて勝負にならない事もあるでしょうが、それでも負けたくないので、そこで色々な人と仲良くなりたいです。もちろん競い合うだけでなく、将来的に積極的に情報交換ができるコミュニティなどにも参加したいです。折角インターネットでつながっているのですから、実際に会うのはその場限りであったとしても、良い人脈を形成できたらいいと考えています。自分一人ではできない事でも、誰かと一緒にできることがあるのであれば、そのためにも良い人に巡り合ってみたいと考えています。

 また、一人ひとり受けられる講義に限界があったとしても、会場で知り合った友人と協力して、それぞれが受けた講義について情報交換したいとも考えています。受講した内容を他人に教えてはいけないルールがあるのでしたらそれは当然やめますが、できる事であれば情報交換をして、ただ講義を受けるだけよりも実りのある時間にしたいと考えています。

 

 私に限ったことではないですが、学校を卒業すればいずれ就職するので、サイバーセキュリティに関する仕事にはどのようなものがあるかも気になります。私が知っている限り、サイバーセキュリティに関する企業と言うのは有名どころの企業しか知りません。SymantecTrend Microなどと言った大企業が、ウィルスをひたすら解析してそれらに対するシグネチャや対策プログラムなどを作っている様子しか思い浮かびません。恐らく他にもサイバーセキュリティに関する仕事と言うのは存在するのでしょうが、その性質上公にできないものやそもそも周知されていないことも多くあるのでしょう。もしかしたら、技術面に関する事ばかりではないのかもしれません。私は、将来セキュリティに携わる仕事に就きたいと考えていますが、このまま先述したイメージだけを持っていながら就職するのでは危険だと考えています。凝り固まった考えばかりではなく、新たな知見を広げられるようにして、将来の変化に対応できる、「技術者」ではなく「人材」になりたいと考えています。そして何より、世の中にある色んな職業を知らずに一生を過ごすのは損でしかないと考えています。より多くの出来事に触れるチャンスは、やはりより多くの出来事を知ることが第一歩です。そういった意味でも、サイバーセキュリティに関する仕事の紹介は外せないところです。仕事の紹介だけでなく、サイバー犯罪による被害と言うのも気になります。先日NHKのテレビでセキュリティに関する話題が取り上げられていました。そこではスタックスネットというマルウェアに関する話題がありましたが、どうやらそれはかなり昔のことだというのです。テレビの情報が最新の情報に感じてしまったのは否めませんが、それでもただでさえセキュリティに関する情報と言うのはテレビでもインターネットでも仕入れにくいというのに、情報が古いとなってはあまり意味がないような気がします。所謂歴史を学ぶのは大切なことではありますが、私のような一般人にはセキュリティの最新情報というのはなかなか手に入れ難い機会です。サイバー犯罪による被害はもともと知られにくいというのもありますが、それでも最新(あるいはそれに近い)情報であると期待しています。新しい情報だけを学ぶことが良いこととは言いませんが、それでも最新の情報は私にとってとても貴重な情報です。是非お話を伺い、最先端の現場でどのようなことが起きているのか知りたいです。

 

 自分の実力を図るためにも、CTFへの参加は欠かせません。セキュリティの技術や知識を競技の形で比べられるのは良いアイディアだと思います。その問題には答えがあるとはいえ、自分で何が脆弱性なのか、何がいけないのかを考えて、調べて行動できるという機会があるのは自分の思考力や知識を深められる点でCTFは優れていると思います。私はCTFの問題をそれほど解くことはできないのですが、CTFには様々なジャンルの問題があるので、私の知らない分野の知識を広げられるというのが好きです。セキュリティ・キャンプのCTFだけに留まらず、インターネット上にある様々なCTFやSECCON、いずれはDEFCONなどに参加し、様々な問題と周りの人たちなどの環境に触れてみたいです。そして新しい問題に挑戦し続けることで、「知らなかったこと」を知っていこうと思います。知らなかったという体験こそが私自身を成長させられる栄養素だと考えています。もちろん、セキュリティに関する大会だけでなく、プログラミングコンテストなど他の大会などにも参加し、大会等に参加して得られる新たな発見を追及していく皮切りにしていきたいと考えています。

 

ここまで、私は様々なことについて学びたいとしました。特別興味のあるものや一時的に特定の分野を勉強することはありますが、それでも私は特定の分野に特化することを避けて、様々な分野に目を向けていきたいと考えています。それは、特定の分野に特化した人材では、その特定の分野でしか物事を見なくなるからです。セキュリティは、誰もが予想しなかったことで虚を突いたもの勝ちだと考えています。その予想しない事を可能な限り予想できるためには、特定の分野に偏らない考えが必要だと思います。だからこそ、低レイヤーや高レイヤーなどに限らず色々な分野に目を向けて勉強することが大切だと思います。きっと周りの人は「そんなのは現実的ではない」と言うかもしれませんが、やってみなければ分かりませんし、人間の記憶できる容量は生きている時間そのもののはずです。それが可能かどうかは証明されないでしょうが、不可能も証明されないはずです。加えて、私は誰に対してもどんなことに対しても負けたくありません。私の身近にいる友人だろうと同じプロジェクトや学科の先輩だろうと、そして社会人の大人の方々だろうと誰だろうと負けたくありません。その性分も私の様々な分野を勉強したいという気持ちを後押ししています。そしてセキュリティと言う視点からも凝り固まらないようにしたいです。セキュリティは大切な要素ですが、完璧なセキュリティが存在するわけでもありません。だからこそ、セキュリティに固執するのは良くないと思っています。何事も適度なバランスが必要なのです。開発を優先してセキュリティの質を落とすことも許容するような考えも必要だと考えています。最善の行動がとれるような選択肢を広げられるよう、広い知識や技術があることも大切だと考えます。

 そして私はセキュリティ・キャンプで得られたことを他の人に教えてあげたいです。どのようなことを学んだとか、どういった雰囲気だったとか、セキュリティ・キャンプに参加した経験を丸ごと広めていきたいです。私はブログや開発誌のようなものを持っておらず、Twitterのアカウントはあっても呟くこともあまりありませんでした。しかし、以前、大学のプロジェクトの一環でセキュリティに関する講師をお呼びしてお話を伺った時、「ブログなどを通じて自分の得たことを他の人にも知ってもらえるよう情報を発信することが重要だ」とおっしゃっていました。この時私は、この情報発信は素晴らしいことだと気づかされました。まず一つ目に自分のためになることです。情報を発信するということは、自分の知識体系を整理することにもつながり、より明確な形にすることができます。二つ目に、他の人のためになるということです。自分が躓いたことを経験として語ったり記したりすることで、他の人がそれを糧にして勉強をしたり先に進むことができます。その他の人がさらに情報発信をすれば、それはもう立派なコミュニティになると考えたのです。今後、ブログなどを作成し、情報発信などを進めて行きたいと考えています。セキュリティ・キャンプは希望者全員が参加できるようなものではない、貴重な経験です。情報発信をするためにも、(セキュリティ・キャンプの参加に限りませんが)セキュリティ・キャンプの参加は重要なものだと考えています。また、ブログに限らず、私の身の回りにある勉強会やプロジェクトの中でも情報発信を行い、(一段落前などの私の考えが正しいとは言いませんが)少なくともこんな考えがあるんだよと言うことも含めて、ローカル、グローバルを問わず情報を発信していきたいと考えています。

 

ここまでをまとめて、私はセキュリティキャンプで様々なことを体験・学習し、広い知識や経験・考えなどを身につけ、私自身の成長はもちろん、それらを発信することで社会全体に良い影響を与えられるような行動を続けていきたいと考えています。

 

選択問題1

以下は変数hogeとfugaのメモリアドレスを表示するプログラムと、その実行結果です。実行結果のhogeとfugaのメモリアドレスを見て、思うことを説明してください。(ソースコード省略)

 見たところ普通にポインタの位置を示しているように見えました。ですが、気になるところがいくつかありました。アドレスの値が少し違和感を覚えたことです。

 hoge address、fuga addressはどちらも0x7fXXXXXXXXXXと、メモリのちょうど半分より少し低位アドレスにあると思います。このアドレスは、Windowsでいうユーザー用メモリ空間にあるのではないかと思われます。やたらとOSなどが使う0x800000000000以降のアドレスに近いと思いました。また、fuga addressの値をよく見ると、0x7fca11404c70という値になっており、これが0x7f ca11 404c70という風に分けて見えます。つまり、0x7f call(コール、呼び出しの意)、404c70という文字の並びに見えます。404c70という値がOllyDbgなどのデバッガでプログラムの中身を見た時によく見るアドレスなので、このアドレスが404c70のアドレスのコードを実行するためのちょっとした暗号のようなものではないかと思われます。私の考えでは、これは仮想アドレス空間のアドレスで、プログラムのエントリポイントに近い感じがします。

 また、fugaのmallocの割り当てられた範囲が1byteしかないのも気になりました。intへのポインタだとしたら、普通はsizeof演算子を用いてsizeof(int)と指定するはずではないかと考えました。他にも、このシステムは48bitのメモリ空間をもつのではないかと考えます。

 これはたまたまかもしれませんが、問題文のhoge addressもfuga addressもどちらも下1桁が0という区切りのいい数字になっていると思いました。そして、それが偶然なのか問題の仕様なのかを調べるために、試しに自分の環境下(Windows 8.1, x64, Visual C Compiler)で調べてみたところ、アドレスの値は必ずも下1桁が0になるとは限りませんでした。さらに、メモリの位置関係はhoge addressの方が低位、fuga addressの方が高位に必ずなっていることがわかりました。加えて、fuga addressの下一桁が8になっていました。ですが、これは問題文の実行結果と違っています。

 調べた時に気になったのが、同じソースコードのはずなのに、実行結果の方でアドレスに0xのプリフィックスが付いていないところでした。そこで、VMware上にKali-Linuxを立ち上げ、そこでgccを使ってコンパイルし、実行したところ、アドレスの値に0xのプリフィックスが付加されるようになりました。なので、問題のプログラムが実行されている環境はgccが搭載されているのだと考えます。また、その時に調べたアドレスを見ると、私の環境下ではhoge addressが必ず0xbfで始まり、下一桁が4で終わっていました。さらに、fuga addressはWindows上で実行したときと同じく下一桁が8になっていました。加えて、hoge addressが高位のアドレスに、fuga addressが低位のアドレスになっていました。hoge addressの上2桁目がfになっているところと、hoge addressとfuga addressの位置関係は問題文と一致することが分かりました。これはLinuxWindowsの違いから生じることではないかと考えます。

 

選択問題5

PCなどに搭載されているOSは「汎用OS」と呼びますが、それに対して、家電やAV機器などの「組込みシステム」に搭載されているOSは「組込みOS」と呼ばれます。
組込みOSと汎用OSの違い、「OSが無い」や「ベアメタル」という環境、そもそもOSとは何なのか?など、あなた自身はどう考えているのかを、あなた自身の言葉で自由に説明してください。(「正しい答え」を聞いているわけではありません。あなた自身の考えを教えて下さい)

 Windowsなどの汎用OSは、一般的にハードウェア資源をアプリケーション側から隠し、それらを効率良く利用することができるよう管理すると言われていますが、私は少し違う気がします。動作の面であればそれで間違いないと思いますが、現状ではWindowsなどのOSに合わせた変化がハードウェアに要求されているのだと思います。なぜなら、Windowsは世界的標準のOSであり、シェアの大半を占めています。しかし、それが災いして、ハードウェアベンダが新たなデバイスを製品化する際、「Windows用にデバイスドライバを作らなくては」と自然と連想させてしまいます。たくさんの利用者に使ってもらうようシェアの大きいOSに合わせたドライバ開発をするのは当然のことです。Windowsに限ったことではありませんが、私は、汎用OSの存在自体がハードウェアベンダをコントロールしているような気がします。つまり、汎用OSがコントロールするのはハードウェアに加えてハードウェアベンダもコントロールしていると考えます。仕様が徐々に統一されていき、ある程度環境が変わっても動作が可能になるのは開発面にとってはメリットですが、セキュリティにとってはデメリットのことが多く含まれます。現に、Windowsを狙ったマルウェア開発やハッキング(クラッキング)は後を絶ちませんし、他の汎用OSに比べてマルウェアの動作するOSの割合が多いのも事実です。これからIoTの発展により様々なモノに対して情報機器が用いられる未来、ある程度仕様の違うものが必要になると考えられます。

 また、汎用OSは便利ですが、強力過ぎる存在であるとも考えます。汎用OSの特徴は何でもできる事で、様々なアプリケーションやハードウェアを扱うことができます。それ自体は良いことですが、それだけ管理しているものが多いということにもなります。仮に、Windowsが乗っ取られてしまった場合、乗っ取られたWindows上で管理されているものも全て操られてしまう可能性があります。強力なOSであるが故に、セキュリティも厳重にはなっていますが、そこを突破されたときの被害が大きすぎるのです。一度乗っ取られてしまうと、その強力さを活かした踏み台にし、他のホストに攻撃を加えていく可能性もあります。便利と危険は表裏一体となっており、あまり強力過ぎるもいけないのではと考えます。

 さらに、汎用OSはユーザに優しすぎると考えます。というのも、汎用OSが協力で何でもできる上、徐々にユーザにとって使いやすいものに進化しているからです。昔のコマンドラインで操作するのが主流だった時代に比べて、汎用OSがユーザに求めている前提の知識が少なくなっています。視覚的に、マウスをクリックするだけで目的を達成できるのはそれだけ汎用OSが強力になり進歩した証ですが、反面、ユーザの敷居を低くしたことでほぼ知識がないユーザも扱うことができるようになりました。それは、そのユーザがセキュリティに関する問題に直面したとき、対処が難しくなることを意味します。知識もないのに、ファイアーフォールが無効化されているだの、オーバーフローが起きているだの、そんなことを言われても一般人にはよくわかりません。Windowsが「安全です」と謳っている事が危険だと感じるのです。セキュリティの世界に絶対安全と言う概念が存在しない事を、一般ユーザがもっと深く認知すべきなのに、昔からよく聞く名前の汎用OSの存在が根拠のない安心感を呼び起こしているような気がしてなりません。最近はマルウェアの活動も巧妙化しており、ステルス化する一方、一般人にとってはマルウェアに感染していることが気づきにくくなっています。マルウェアが感染していると分かればよいのですが、ユーザが汎用OSの中で起きていることを気にしなくてよくなった分、マルウェアやその他危険なソフトなどが動いていることも「気にしなく」なりました。つまり、扱うユーザの知識の無さが大きな脆弱性となってしまっているのです。私は、汎用OSを扱うのであれば、それに対しての知識を身につけておくことが必要であり、扱うものを「扱える」だけの知識を有しているべきだと考えます。

 ただし、汎用OSは学ぶ意欲のある者にとっては良い「教材」にもなります。ハードウェア資源を管理する方法や、効率的に処理をするための工夫、もちろんセキュリティについても、汎用OSは素晴らしい知識の結晶です。勉強するのは難しいにしても、そこから得られる知識は汎用的なものから応用的なものまで様々です。そういったことに興味を持ってもらえる可能性があるユーザの幅を広げるという点では、汎用OSのシェアは強みになると考えられます。

 

 ここまでは汎用OSの良い点と悪い点を挙げましたが、組込みOSにも同様に良い点と悪い点があると考えます。組込みOSはある特定の製品に対して組み込まれるため、その製品に特化した処理や性能、製品の特性を考慮した設計を備えていなければなりません。中には命に関わるような製品にも組み込まれるので、それぞれに合わせた開発をしなければならなくなるのは目に見えています。開発の効率を上げるためにある程度モジュール化するでしょうが、それでも完璧に一緒な組込みOSは同一製品を除いてごく稀なはずです。このような組込みOSの特徴は、セキュリティにとってメリットがあるはずです。開発後の動作テストやセキュリティ上の問題が無いかなどのテストをする際はその性質上問題発見が難しくなりがちですが、仕様が違うため悪意を持った人たちもそれに攻撃を行うことは容易ではないと思われます。仕様書などのデータは公開されないか、あるいは限られた範囲でしか周知されないはずなので、ソーシャルエンジニアリングを通したとしてもその情報を手に入れられるのは難しいはずです。また、Windowsなどの汎用OSのように広く普及する目的で作られていないので、解析するための環境やデータを揃えにくいはずです。こういった特性が、セキュリティを脅かすような攻撃を受けにくいと考えられます。つまり、それぞれバラバラな「仕様」こそがセキュリティを維持する対策になると考えます。初めて導入したOSを外部からの攻撃から身を守る場合、一番良い方法なのがネットワークに接続しないのと同じように、セキュリティで最も強固なのは「知られていない事」だと私は考えます。ここまで組込みOSは攻撃を受けにくいなどのことを述べましたが、仮にスピアー型の攻撃を受け、脆弱性が露呈した場合には汎用OSよりも対策が遅れるのが事実です。それは組込みOSを作る企業が必ずしも大企業とは限らず、中小企業でも開発する可能性があり、その企業が脆弱性に対して対策を迅速に打つことができるとは言えないからです。脆弱性を発見しやすくするために、あるいは開発期間の短縮やコスト削減を狙ってモジュール化するのは悪くありませんが、全てをモジュール化するのではなく、適度なモジュール化と適度な差別化を図る必要があると考えます。

 また、組込みOSは一般のユーザにより良くも悪くも情報技術のレベルを発展させると思われます。今、Raspberry PiArduinoなどのミニコンピュータが流行っています。特にRaspberry Piでは5ドルで買えるモデルも現れています。それらを扱うための手順やプログラムが記された書籍なども大量に流通している今、教育分野として取り入れているところも少なくありません。電子工作をしたり、組込みOS上でプログラムを作ったりと、コンピュータに触れる年齢がどんどん低下していき、コンピュータサイエンスに触れる機会も多くなるでしょう。そうなると、趣味や生活レベルでコンピュータが浸透していきます。結果、一般のユーザが自分で好きなようにカスタマイズができるという点を活かして、様々な想像力に溢れたものを生み出すのではないかと考えられます。アイディアは誰もが持つ素晴らしいものですので、年齢や立場に縛られることなく情報技術の発展につながるでしょう。そのコンピュータサイエンスの知識をセキュリティに活かすこともできます。より早い段階でセキュリティに関心を持ってもらえるのではないかと思います。

 当然、その反対にハッキングやクラッキングなどを楽しんで倫理的に良くない事をする行為を助長するかも知れません。インターネット上での心無い書き込みがあるように、コンピュータに攻撃することに対して罪悪感が生まれてこない可能性があります。教育の現場で組込みOSなどを用いたコンピュータを利用するのは悪いことではありませんが、そこで得られた知識が容易に実行されやすいからこそ、その対策を十分にした上で、倫理面での教育をしっかりする必要があると考えます。

 

 今後、汎用OSと組込みOSの違いは徐々になくなっていくと私は考えます。完全に同じものになることはなく、ある程度搭載する製品別に特化したOSになると思われます。Raspberry Piなどのミニコンピュータに搭載できるOSがWindowsLinuxであったりと、搭載するハードウェア本体の性能が向上していることもあり、IoTに用いられるOSも必ずしも組込みOSとは限らなくなってくると思います。また、組込みOS自体も強力なものになり、汎用OSのレベルに近づいてきていることも二つのOS間の違いをなくしつつあるものだと思われます。

 

選択問題6

IDとパスワードを入力してユーザの認証を行うWebアプリがあります。あなたがこのアプリに対してセキュリティテストを行う場合、まず、どのようなテストをしますか?

なぜそのテストを選択したのか、その背景や技術的根拠と共に記載してください。アプリの内部で使われている技術やシステム構成に、前提を置いても構いません。

 私が行うテストは、IDやパスワードのログイン試行を行っているのが人間かコンピュータかを判断することです。

その理由は、機械学習人工知能などの技術が一般的になってきているからです。最近はAlpha Goなど人工知能機械学習などの話題がとても多く取りざたされています。それを考慮し、パスワードをクラックするために機械学習人工知能などの技術が用いられてもおかしくないと思いました。つまり、パスワードクラックの自動化です。私は、このWebアプリケーションの中に前提としてCAPTCHAのような人間であることを確かめる機構を追加することを前提とします(人間であることを確かめる機構であればCAPTCHAに限らないとします)。

 レインボーテーブルや辞書攻撃、古典的な推測攻撃ブルートフォースなど、パスワードに対する攻撃手法は様々なものがあります。ですが、直接人間の手でパスワードクラックをするのはあまりないのではないかと思われます。何故なら、たくさんあるアカウントに対して一つずつ攻撃して得られるものよりも、一度に多くのアカウントに対して機械的に攻撃して得られるものの方の価値が大きいはずです。

それに、世の中の人がパスワードを作る際、ある一定の規則に従って作っている人や、そもそもパスワードを覚えるのが面倒だからと全部同じパスワードにしたりと、本当の意味でのちゃんとしたパスワードを作る人は少ないと思います。それはパスワードを求められることが多くなったからでもありますし、パスワードを覚えなくてもいいよというシステムが多くなったこともあり、人間が「パスワード管理の大切さ」を失いつつあるのが現状だからです。初期パスワードのまま変更しない人もいるでしょう。そんな中、パスワードのパターンにもある一定の法則や規則的なものが見いだせてくるはずです。それらを機械学習させ、人工知能が予測することで、ある一定のパスワードクラックの成果は見いだせるのではないかと考えます。

私がよくニュースで聞くのは、設定したパスワードはどんなものですかという問いに対して「password」ですということを聞きます。それでは意味がないと思います。

他にも、デジタル機器の普及やインターネットをよく使う世代が増えたこと、機器の性能面の強化などによって、かなりの数のユーザが特定、あるいは少数のシステムに登録することで、攻撃者側も攻撃拠点を絞りやすくなっています。攻撃拠点は絞りやすいのに対して、攻撃できる的の数は豊富です。それもまた機械的な攻撃を助長するのではないかと考えます。

 仮にパスワードが人工知能によって推測され、ある程度の見当が付けられている場合、アカウントを守る手段はロックアウト程度しかありません。パスワードがパスワードとして機能しないのなら、IDを入力するだけで良くなってしまいます。なので、CAPTCHAのような人間か否かを区別する仕組みが必要なのです。もちろん、CAPTCHAの画像を正しく認識し、その中に書かれている文字列を判別するような人工知能も研究されているはずです。ですが私が言いたいのは、何もCAPTCHAを強化しろというのではなく、常にその時の新しい技術を用いて、人工知能が学んだことの無い、あるいは学ぶのが難しい認証の仕組みを追加しなくてはならないということです。

当然、正規のユーザにとってはCAPTCHAのような認証機構は利便性の低下を招くだけです。認証機構によっては、正規のユーザすらも容易にログインできなくなる場合もあるので、人工知能には難しい、かつ人間にはある程度容易にできる認証機構が必要だと考えます。

 

 Webアプリケーションでの脆弱性は攻撃されやすいものですし、脆弱性の種類にも様々なものがあるでしょう。そういった脆弱性はパッチを適用したり、脆弱性を利用されない機構にすれば多少の攻撃を防げるはずです。少なくとも、脆弱性が発覚したとしてもそれを直すことができます。ですが、直せない脆弱性があります。それは私達人間が人間であると証明できない事です。人工知能が人間と同等に近づくにつれ、データのやりとりだけでは区別が難しくなっています。だからこそ、私はログインを試みている相手が人間か人工知能かを判断するような機構が正しく動作しているか、人工知能で認証を突破することが困難であるかどうかを確認することが第一に必要だと考えます。

 

選択問題7

あなたが管理するネットワークに悪意ある第三者が存在しない事を証明する方法を思いつく限り列挙してください。なお、条件として物理的にアクセスされる可能性を想定してください。

 まず、固定されたデスクトップPCのみのネットワーク内で調査をする場合、電源の使用料について調べます。正規のユーザが用いるPCの電源消費量をPCの仕様から算出し、その総計よりも多くないかを確認します。可能であれば、調査するネットワークが敷設された敷地及び建物内に不審な人物が立ち入ったかどうかを入退室管理記録等から調べます。

 物理的な調査ができない場合などは、ネットワーク自体の調査を行います。ミラーポートやタップを挟み込み、通信内容をモニタリングします。まず、使用しているIPアドレス空間を調べます。固定IPアドレス空間内であれば割り当てられているIPアドレスを使用していないホストがいないか調べます。動的IPアドレス空間内であればDHCPの使用履歴から、リースした先のMACアドレスを所有する端末を検索します。MACアドレスでも、正規のユーザが使用しているMACアドレスが固定であるならば、それ以外のMACアドレスで接続されていないか確認します。また、MACアドレスを偽装していないかを確認するために、重複しているMACアドレスの存在を確認します。加えて、APRキャッシュポイズニングの可能性を考慮し、不審なARP応答が無いかブリッジやルータのログを確認します。

 悪意ある第三者のホストを調べられない時は、ネットワークの通信内容を解析します。同一IPアドレスからのアクセス数が異常ではないかを、通常時のアクセス数から比較します。また、同一IPアドレスに対してポートスキャンが行われていないかを確認します。また、同一ポートに対するTCPコネクションの要求が多すぎないかも確認します。ここまでで、同一ネットワーク内の構成を調べようと様々なIPアドレス(存在しないアドレス空間も含む)やポートにアクセスしようとする通信が無いか確認します。DNSキャッシュポイズニングを試みたり、DNSを取得しようとしている通信など、内部のネットワークに存在するだけで特段認証もなく得られるような情報を収集している通信がないかも確認します。通信方向にも注視します。ネットワーク内にIDSやIPS、プロキシサーバなどがあれば、そのログから確認します。怪しいURLまたはIPアドレスにアクセスし、マルウェアなどをダウンロードしていないか、あるいは外部に何かしらの情報(恐らくネットワーク内で得られた情報)を送信していないかなどを確認します。ここで独自のプロトコルなどを用いているかも確認します。また、特定のサーバなどにログインを試みていないかなども確認します。IDSやIPSなどで使用しているポート(サービス)に制限がある場合、そのポートにアクセスしようとした通信が無いかも調べます。

 

ーーーーーーー以上ーーーーーーー

ここまで読んでくださった方、ありがとうございます!

それとも、一気に流し読みしましたか?いや、流し読みしたくなる気持ちも分かります。だって僕ならこんなの読みたくないです。

その読みたくない文章を講師の方々に送りつけました…すみません。ですが、これで気持ちだけは伝わったのか、合格を頂くことができました!

長い文章を読んだ上に合格まで下さり、本当にありがとうございます!

 

今後の方針としては他の参加者の皆さんの迷惑にならないよう、CTFや事前学習を頑張っていきます!

 

結果報告などは、今後ブログにUPしていく予定です。とにかく頑張るしかないみたいです!

 

(キャンプの人、レベル高すぎて泣ける(´;ω;`))