この記事はChainer Advent Calendar 2015 13日目の記事です.
はじめに
Chainerで実装を進めているのですが,今回は構想的な話をします.ご容赦下さい.
私は修士論文でEディスカバリ*1を対象に自然言語処理と機械学習を用いて研究を進めていますが,それとは別に,Deep Learningでマルウェア検出に取り組んでいます.本当は研究室配属された時に,これで論文書きたいと思っていましたが,色々大変であることが発覚したので,個人的に細々とやっている感じです.卒業までになんとか実現しようと奮闘しております.
マルウェアを機械学習させるための戦略
マルウェアにも様々な種類がありますが,PEフォーマット*2のマルウェアを対象にしております.
マルウェアも可変長の入力になるので,文書分類などで用いられている手法が使えるはずです.機械学習アルゴリズムの殆どは固定長の入力が一般的なので,可変長の入力に対応するためには何かしらの方法で特徴ベクトルを固定長にする手法が必要です.その手法は以下がよく使われています.
Bag-of-Words
文書中の単語の出現回数を素性とするBinary
文書中に単語が出現したか否かを1,0で表現して素性とするTF-IDF
TF:Term Frequency -> 単語の出現頻度,IDF:Inverse Document Frequency -> 単語の文書頻度であるdf(document frequency)の逆数
しかし,これら手法は「単語数がそのまま次元数になるので超高次元になりやすい」「語の順序が失われる」「語の意味が失われる」という問題があります.
高次元になる問題は,適切に特徴選択をすれば対処することができます.問題は「語の順序が失われる」ということです.マルウェアはプログラムなので,「命令の順序」が文書における語の順序に相当するでしょう.
私はこの「命令の順序」も大きな意味を持っていると考えているため,これも素性として含める必要があります.そのため,順序が失われる手法を用いるのは望ましくありません.
そこで注目しているのが,Recurrent Neural Networkです.
Recurrent Neural Networkは可変長の入力に対応しているDeep Learningの手法なので,これを用いることにします.
語の順序を保ちながら固定長の次元に落とし込めるParagraph Vectorという手法も存在しますが,こちらはDeep Learning Advent Calendar 23日目で取り上げたいと思います.
今まではRNNの実装は結構大変でしたが,Chainerの登場により,実装の敷居は大きく下がりました.
Chainerについて
Caffe,Touch7,Chainer,TensorFlowなどのDeep Leaningのライブラリ・フレームワークの登場によって,Deep Learningを試す敷居は相当下がったと思います.しかし,それらフレームワークの中でもChainerは一線を画した存在であると私は思います.
Chainerの仕組みは先進的で,特にBackwardのやり方が非常に素晴らしいと感じました.また並列化や最適化にも力を入れられており,CPUで実行しても割りと高速なのも素敵です.
RNN(RNNLM)をChainerで実装するのですが,RNNを構成するLSTMの使い勝手がv1.5から非常に良くなりました.以前まで多層LSTMのモデルでforward関数を記述する際は,直前の状態と自分の状態をHashで渡していたのですが,その必要がなくなりました.これにより,RNNLMをより簡潔に書けるようになったと思います.
examplesのptbを参考に,後述するモデルを実装を進めております.
RNNに期待していること
攻撃者はマルウェアを作成する際,一からプログラミングしているわけではありません.
既存の部品の組合せと,パラメータやプログラミングの並び,暗号化のアルゴリズムを少しだけ変えてマルウェアを生成しています*3.
何億という種類のマルウェアが存在していると言われていますが,実際には既存のマルウェアの亜種が増えている感じです.
そこで私はDeep Learningの表現学習*4によって,上記の組み合わせや特徴量をうまいこと学習して高い検出精度を出せないかと期待してます.
RNNベースの学習・検出システムの考案
私の取り組みでは,PEフォーマットのマルウェアを対象にしているので,学習・検出システムの構成図は以下の通りとなります.
マルウェアを静的解析して得た素性(Hexdump,逆アセンブル)と動的解析して得た素性(APIの呼び出しなど)を,それぞれ別のDeep LSTMに学習させ,その後に多数決を取ることでうまいこと検出精度を高めることができないかという構想です.
Deep LSTMのモデルは以下のようにしました.こちらはdeeplearning.netを参考にしています.
参考にしたモデルの改良点として
LSTMを多層化(2〜4層)
Meam PoolingをMax Poolingに変更
分類器にAROWを採用
が挙げられます.
Meam PoolingをMax Poolingにした理由として,Max poolingで得られる特徴ベクトルは識別性能が高いこと,線形分類器との相性が良いことです.
分類器にAROW*5を採用した理由としては,調整すべきハイパパラメータが少なく,識別性能が高いことから,個人的に使い勝手がいいという理由です.
しかし今回は,機械学習させる対象があまりにもクリティカルなので,ギリギリまで精度が必要です.
そのため,AROWより高性能な線形分類器であるSCW*6を,あるいはXGBoostの利用も検討しても良いかもしれません.
マルウェアを学習させる難しさ
先の学習モデルを実装して,即座に学習させることができるわけではありません.攻撃に使われるマルウェアのほとんどは,解析を妨害するために様々な仕組みが備わっています.
この妨害こそがDeep Learningでマルウェアを学習させることへの大きな障壁となっています.
静的解析の難しさ
マルウェアを実行せず,リバースエンジニアリングなどを用いて,どういう機能を有しているのかを調べる手法のことを静的解析と言います.
マルウェア製作者は,この静的解析を妨害するために,マルウェアに対してパッカーを使います.
パッカーとは,プログラムの実行形式を保ったまま圧縮・難読化(パック)するツールのことです*7.
パックされたプログラムは本来のコードが圧縮・難読化されているため,逆アセンブルしても本来のコードを得ることはできません.
そのため,パックされたプログラムを解凍するアンパックという処理が必要です.
しかし,機械学習させるためには,多くのマルウェアの検体を必要とします.学習させるために膨大な量の検体を入手しても,ひとつひとつの検体のパッカーを判別をしたり,アンパックを施していくのは大変な労力を必要とします.
これを自動化する技術は今後出てきそうですが,高度なマルウェアはアンパックする作業に対しても妨害を仕掛けてくることがあります.
これが静的解析で有効な特徴量を得ることを難しくしています.
動的解析の難しさ
マルウェアを実際に動かして,挙動を観察することを動的解析と言います.動的解析を行うことにより,より詳細な機能を把握することができます.
動的解析はサンドボックス*8で行うことになりますが,マルウェアはこのサンドボックスを検出する仕組みを備えていることがあります.サンドボックスを検出した場合は動作を停止したり,偽の挙動を示したりします.
動作を停止した場合はその検体を学習に用いないようにすればいいですが,偽の挙動を示すものに対しては学習に対するノイズになりうる可能性があります.
これらが動的解析で有効な特徴量を得ることを難しくしています.
今後の課題
より性能が高いDeepLeaningによる分類手法は今後も出てくると考えているので,逐次その手法を取り入れていくつもりです.
考えるべき点はやはり「いかにしてマルウェアの妨害をかい潜り,機械学習させるための良質なデータセットを作るか」だと考えています.
この辺り何か良い方法があれば教えていただきたいです.
おわりに
今回は構想だけで終わってしまったので,進展があれば,その都度ブログに書いていく予定です.
ご意見・ご感想お待ちしております.
*1:電子証拠開示,米国独自の裁判制度のこと
*2:Portable Executable:Windows上で使用される実行ファイルのフォーマットのこと
*3:八槇博史先生インタビュー「セキュリティの視点から考える,AI の強みと盲点」より引用
*4:有効な特徴の組み合わせを自動的に学習すること
*5:Adaptive Regularization of Weight Vectors:http://www.cs.jhu.edu/~mdredze/publications/nips09_arow.pdf
*6:Exact Soft Confidence-Weighted Learning:http://icml.cc/2012/papers/86.pdf
*8:保護された領域内でプログラムを動作させる仕組み