Upload
jubatusofficial
View
8.312
Download
0
Embed Size (px)
DESCRIPTION
Jubatus分類器の活用テクニック
Citation preview
セキュアプラットフォーム研究所
© 2013 NTT Secure Platform Laboratories
NTTセキュアプラットフォーム研究所
NTT Secure Platform Laboratories
Jubatus分類器の活用テクニック ~マルウェアの静的判定を題材として~
Jubatus Casual Talk #2
2013年 12月 14日
2 © 2013 NTT Secure Platform Laboratories
はじめに
この発表の目的はただ1つ
Jubatus分類器の活用テクニックを伝授 !!
•分類器なのに、一致検索の用途でも使えちゃう
•分類時のスコア、有効に活用してますか?
•複数分類するときでも、Jubatus分類器1つにまとめる方法
•どうして分類できてるのか、学習の中身を知りたくないですか?
奇妙な
3 © 2013 NTT Secure Platform Laboratories
なぜ機械学習でマルウェア判定するの?
異常データ=マルウェアと見做して、機械学習を使ってマルウェア判定したい。
⇒機械学習で未知のマルウェアが検出できるのでは、という期待
異常データがある程度手に入る場合は分類器でも異常判定できる。
以下の場合は異常検知器より分類器の方が適しているという感触:
• 異常データに特有な値がある場合
• 正常データに特にまとまった傾向が見られない場合
• 教師データが大量にある場合
研究用マルウェアは意外と入手できる
• MWS 研究用データセット: http://www.iwsec.org/mws/2013/about.html
• Malware.lu : http://malware.lu 等
MS Windowsの実行形式ファイル(EXEファイル)でマルウェアの静的判定を
Jubatus分類器で行えないかを試みたのでご紹介
(静的判定=ファイルを実行せずに判定すること)
4 © 2013 NTT Secure Platform Laboratories
マルウェアの静的判定手法
• 一般的なウィルススキャンソフトの処理 (静的判定)
–ハッシュ値一致判定
ファイルのハッシュ値(MD5、SHA1、SHA256等)を取って、
既知のマルウェアのハッシュ値と一致するかをチェック
–パターンマッチ判定 (シグニチャスキャン) マルウェアに含まれる特定の文字列やバイトコードがあるかをチェック。
(例) マルウェア ZeuSボット系亜種はプログラム中に“ZeuS”という文字列がある。
– ヒューリスティック判定
これまでの経験から「マルウェアらしさ」を定義し、その定義に従って判定する。
実際の手法は各社様々。行動パターンで推論するものが多いらしい。
(例) 「既存のEXEファイルを開いて、最後尾にコードを追加後、保存する」行動はウィルス。 (バイトコードのパターンマッチ判定で実装する場合もある。)
5 © 2013 NTT Secure Platform Laboratories
機械学習を用いたヒューリスティック判定手法
⇒ PEヘッダからメモリ配置情報等取得し、Jubatusでのヒューリスティック判定を試みる
– PEヘッダ情報の取得は容易・高速なので、大量に判定するのに良く使う静的分析に合う。
– 意外と判定できるという報告もあり、なぜ判定できるのか、興味を持った。
参考文献
[伊沢2013] 伊沢、他、「マルウェアのアンパックコードのバイト列に基づくSVMを用いた パッカー特定手法」, SCIS, 2013.
[鐘2012] 鐘、他、「マルウェアのオペコードに着目した高速な分類手法」,信学技報,vol.112,pp.43-48,2012.
[村上2013] 村上、他、「類似度に基づいた評価データの選別によるマルウェア検知精度の向上」, MWS2013, 2013.
[Ye2008] Y. Ye, et.al., "An intelligent PE-malware detection system based on association mining", J. Comput. Virol., vol.4,
pp.343-334, 2008.
[Shafiq2009] M. Shafiq, et.al., "PE-Miner: Mining Structural Information to Detect Malicious Executables in Realtime",
Recent Advances in Intrusion Detection (RAID), 2009.
着目点 説明 参考文献
コード バイト列などに注目、機械学習し、攻撃コードに似た部分の探索や似ているコード群での分類を実施
[伊沢2013]
[鐘2012]
API コールしているAPIの種類や数、順番等に着目して機械学習、利用APIの組や、APIの実行順の近似等で分類・判定
[Ye2008]
メモリ
配置情報 実行時のメモリ配置、サイズ、開始アドレス等の情報を機械学習、マルウェアに特徴的なプロファイルを作成し、分類・判定
[Shafiq2009] ◎
6 © 2013 NTT Secure Platform Laboratories
今回試作するマルウェアの静的判定器
○ 今回の実装のルール(縛り)
• ハッシュ値一致判定もヒューリスティック判定もJubatus分類器で作る
• ヒューリスティック判定は誤検知率 0% にできるか試みる (感度調整) (マルウェアを100%検知する、または、通常ファイルをマルウェアと誤検知しない)
• 2つの判定器を1つのJubatus分類器でまかなう
構成
マルウェア/
通常ファイル
JSON形式
データ
ハッシュ値
一致判定
PEヘッダでのヒューリスティック判定
7 © 2013 NTT Secure Platform Laboratories
マルウェアからJSON形式データを作成 1/2
• 今回使うデータ
– マルウェア: Malware.lu 2013年 2月分 261個
– 通常ファイル: 業務用PCの Program Files 配下のファイル 574個
• マルウェアを直接取り扱わず、一旦、 JSON形式データに変換
– 試作の段階で直接マルウェアを扱うのは、うっかりミスもあり、危険。
• JSON形式データ作成方法
– SHA1でハッシュ値を取得
– Microsoft Visual C++ 2010 Express付属の"dumpbin.exe"を利用、PE情報の一部を取得
今回利用: characteristics、entry_point、section_names、num_sections の4つ
• JSON形式データの例 (教師データ/推論データで共通のフォーマット)
{"malware": true, "file_name":"105.exe",
"sha1":"0c693894e86aa5618aa83a96e153a7ea943354de ",
"num_sections":"2",
"characteristics":"Relocations_stripped Executable Line_numbers_stripped
Symbols_stripped 32_bit_word_machine",
"entry_point":"200",
"section_names":".text .rdata"}
8 © 2013 NTT Secure Platform Laboratories
マルウェアからJSON形式データを作成 2/2
C:¥work¥test>set Path=C:¥Program Files¥Microsoft Visual Studio 10.0¥Common7¥IDE¥;C:¥Program Files¥Microsoft Visual Studio 10.0¥VC¥BIN;%Path%
C:¥work¥test>dumpbin /headers 7z.exe
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file 7z.exe
PE signature found
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (x86)
4 number of sections
4CE54F63 time date stamp Fri Nov 19 01:08:03 2010
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
10F characteristics
Relocations stripped
Executable
Line numbers stripped
Symbols stripped
32 bit word machine
OPTIONAL HEADER VALUES
10B magic # (PE32)
6.00 linker version
1F000 size of code
AE00 size of initialized data
0 size of uninitialized data
1D0CC entry point (0041D0CC)
1000 base of code
20000 base of data
400000 image base (00400000 to 0042CFFF)
(中略)
SECTION HEADER #1
.text name
1EF0A virtual size
1000 virtual address (00401000 to 0041FF09)
1F000 size of raw data
400 file pointer to raw data (00000400 to 0001F3FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
Execute Read
SECTION HEADER #2
.rdata name
(以下略)
characteristics
entry_point
Section Name section_names
num_sections
9 © 2013 NTT Secure Platform Laboratories
(参考) 今回利用したPEヘッダの説明
PEヘッダ項目 説明
characteristics このファイルの特性。
実行ファイルかDLLか、32ビットアーキテクチャのマシン用か、デバッグ情報を削除しているか等の情報がある。
entry_point エントリポイント(実行開始位置)のアドレス
section_names
セクション名。
セクションとは、メモリを利用特性に応じて区分したもので、実行コードがあるコード領域、表示メッセージ等の静的データがあるデータ領域等がある。
セクション名自体には特別な意味はないが、良く使われる名前がある。 (.text、 .rdata、 .idata、.rsrc、.bss、.reloc、.tls等)
num_sections セクション数
10 © 2013 NTT Secure Platform Laboratories
(参考) Jubatus分類器の設定
{
"method": "AROW",
"converter": {
"string_filter_types": {},
"string_filter_rules": [],
"num_filter_types": {},
"num_filter_rules": [],
"string_types": {},
"string_rules": [
{ "key": "*", "type": "space", "sample_weight": "bin", "global_weight": "bin"}
],
"num_types": {},
"num_rules": [
{ "key" : "*", "type" : "num" }
]
},
"parameter": {
"regularization_weight" : 1.0
}
}
以下の設定を使用します;
11 © 2013 NTT Secure Platform Laboratories
Jubatus分類器でHash値一致判定
• 一致判定も分類器でできないか ⇒ (一般的でないけど)できます。
• 以下のように学習させておくと;
classifier.train("", [("malware",
types.datum([["sha1", "0c693894e86aa5618aa83a96e153a7ea943354de"]],[]))])
classifier.train("", [("normal",
types.datum([["sha1", "9018a7d6cdbe859a430e8794e73381f77c840be0"]],[]))]) …..
• 推論時に以下の結果が返ってくる;
ans = classifier.classify("",[(
types.datum([["sha1", "0c693894e86aa5618aa83a96e153a7ea943354de "]],[]))])
ans の 内容 (イメージ):
[["malware", 0.5]]
★一致判定
–空だった: 一致しない。
– 1個返ってきた: 一致あり。そのラベルがマルウェアか否かをそのまま表す。
– 2個返ってきた : 教師データに同じハッシュ値を持つマルウェアと通常ファイルあり。非常に稀。 (ハッシュ値の衝突を偶然にも見つけてしまった。)
12 © 2013 NTT Secure Platform Laboratories
(参考) 一致判定 サンプルコード
#!/usr/bin/env /usr/local/bin/python2.7
# -*- coding: utf-8 -*-
import sys,json
from jubatus.classifier import client
from jubatus.classifier import types
if __name__ == '__main__':
sTraindata='train-pe.json' #教師データ
sTestdata='test-pe.json' #推論データ
pname = ""
# Jubatusサーバに接続
classifier = client.classifier('127.0.0.1', 9199)
# 学習開始
print("Learn")
for line in open(sTraindata):
# JSON形式のデータを変換
item = json.loads(line)
# malwareか否かの分類を取得
if item["malware"] == True:
label = "malware"
else:
label = "normal"
# 学習
datum = types.datum([["sha1", item["sha1"]]],[])
classifier.train(pname,[(label,datum)])
# 分類開始
print("Classify")
for line in open(sTestdata):
# JSON形式のデータを変換
item = json.loads(line)
# 推論
datum = types.datum([["sha1", item["sha1"]]],[])
ans = classifier.classify(pname,[(datum)])
# 一致判定
# ans[0]が空なら、一致なし。分類 Unkown、score 0
if len(ans[0]) == 0:
estm = "Unknown"
score = 0.0
# ans[0]が要素1つなら一致あり
elif len(ans[0]) == 1:
estm = ans[0][0].label
score = ans[0][0].score
if estm == "normal":
score = - score
# ans[0]が要素2つ以上なら分類ERROR、score 0
else:
estm = "ERROR"
score = 0.0
# 結果出力: 分類,スコア,ファイル名
print(estm + ", " + str(score) + ", " + item["file_name"])
sys.stdout.flush()
Jubatus
0.4.X
13 © 2013 NTT Secure Platform Laboratories
(参考) 一致判定 サンプルコード
#!/usr/bin/env /usr/local/bin/python2.7
# -*- coding: utf-8 -*-
import sys,json
from jubatus.classifier.client import Classifier
from jubatus.classifier.types import LabeledDatum
from jubatus.common import Datum
if __name__ == '__main__':
sTraindata='train-pe.json' #教師データ
sTestdata='test-pe.json' #推論データ
# Jubatusサーバに接続
classifier = Classifier('127.0.0.1', 9199, "", 10.0)
# 学習開始
print("Learn")
for line in open(sTraindata):
# JSON形式のデータを変換
item = json.loads(line)
# malwareか否かの分類を取得
if item["malware"] == True:
label = "malware"
else:
label = "normal"
# 学習
datum = Datum({"sha1": item["sha1"]})
classifier.train( [LabeledDatum(label,datum)])
# 分類開始
print("Classify")
for line in open(sTestdata):
# JSON形式のデータを変換
item = json.loads(line)
# 推論
datum = Datum({"sha1": item["sha1"]})
ans = classifier.classify([datum])
# 一致判定
# ans[0]が空なら、一致なし。分類 Unkown、score 0
if len(ans[0]) == 0:
estm = "Unknown"
score = 0.0
# ans[0]が要素1つなら一致あり
elif len(ans[0]) == 1:
estm = ans[0][0].label
score = ans[0][0].score
if estm == "normal":
score = - score
# ans[0]が要素2つ以上なら分類ERROR、score 0
else:
estm = "ERROR"
score = 0.0
# 結果出力: 分類,スコア,ファイル名
print(estm + ", " + str(score) + ", " + item["file_name"])
sys.stdout.flush()
Jubatus
0.5.0
14 © 2013 NTT Secure Platform Laboratories
Jubatus分類器でヒューリスティック判定 1/2
• 以下のように学習させると;
classifier.train("", [("malware", types.datum([
["characteristics", " Relocations_stripped Executable Line_numbers_stripped
Symbols_stripped 32_bit_word_machine "],
["entry_point", "200"], ["section_names",".text .rdata"], ["num_sections","2"]], []))])
classifier.train("", [("nomal", types.datum([["characteristics", " Executable
32_bit_word_machine"], ["entry_point", "145EE"], ["section_names",".text .rsrc .reloc"],
["num_sections","3"]], []))]) ….
• 推論時に以下の結果が返ってくる;
ans = classifier.classify("",[(types.datum([["characteristics", " Relocations_stripped
Executable Line_numbers_stripped Symbols_stripped 32_bit_word_machine "],
["entry_point", "200"], ["section_names",".text .rdata"], ["num_sections","2"]], []))])
ans の 内容 (イメージ):
[["malware", 0.9321], ["normal", -0.8632]]
★マルウェア判定
– 「ラベルが"malware"のスコア > スコア閾値」 なら、マルウェアと判定。
–通常、スコア閾値 = 0 だが、動かすと「感度調整」が可能。
15 © 2013 NTT Secure Platform Laboratories
Jubatus分類器でヒューリスティック判定 2/2
◆真陽性率 (大きい方が良い) (True Positive Rate)
= マルウェアと
正しく判定できた割合
= (正しく判定した
マルウェア数) ÷
(全マルウェア数)
■偽陽性率 (小さい方が良い) (False Positive Rate)
= マルウェアと
間違って判定した割合
= (間違ってマルウェアと
判定した通常ファイル数)÷
(全通常ファイル数)
スコア閾値
マルウェア判定率
間違いは減るが、
取りこぼしが増える
取りこぼしは減るが、
間違いが増える 閾値を減らす
閾値を増やす
16 © 2013 NTT Secure Platform Laboratories
(参考) ヒューリスティック判定 サンプルコード
#!/usr/bin/env /usr/local/bin/python2.7
# -*- coding: utf-8 -*-
import sys,json
from jubatus.classifier import client
from jubatus.classifier import types
def set_datum(item):
return types.datum([
["characteristics", item["characteristics"]],
["entry_point", item["entry_point"]] ,
["section_names", item["section_names"]],
["num_sections", item["num_sections"]]
],[])
if __name__ == '__main__':
sTraindata='train-pe.json' #教師データ
sTestdata='test-pe.json' #推論データ
pname = ""
repeat_count = 3 #繰返し学習回数
score_thr = 0.0 #スコア閾値
# Jubatusサーバに接続
classifier = client.classifier('127.0.0.1', 9199)
# 学習開始
print("Learn")
# データ件数がやや少ないのでrepeat_count回繰返し学習
for count in range(repeat_count):
for line in open(sTraindata):
# JSON形式のデータを変換
item = json.loads(line)
# malwareか否かの分類を取得
label = "malware" if item["malware"] else "normal"
# 学習
classifier.train(pname,[(label,set_datum(item))])
# 分類開始
print("Classify")
for line in open(sTestdata):
# JSON形式のデータを変換
item = json.loads(line)
# 推論
ans = classifier.classify(pname,[(set_datum(item))])
# マルウェア判定
score = 0.0
for a in ans[0]:
if a.label == "malware":
score = a.score
if score > score_thr:
estm = "malware"
else:
estm = "normal"
# 結果出力: 分類,スコア,ファイル名
print(estm + ", " + str(score) + ", " + item["file_name"])
sys.stdout.flush()
Jubatus
0.4.X
17 © 2013 NTT Secure Platform Laboratories
(参考) ヒューリスティック判定 サンプルコード
#!/usr/bin/env /usr/local/bin/python2.7
# -*- coding: utf-8 -*-
import sys,json
from jubatus.classifier.client import Classifier
from jubatus.classifier.types import LabeledDatum
from jubatus.common import Datum
def set_datum(item):
return Datum( {
"characteristics": item["characteristics"],
"entry_point": item["entry_point"],
"section_names": item["section_names"],
"num_sections": item["num_sections"]
} )
if __name__ == '__main__':
sTraindata='train-pe.json' #教師データ
sTestdata='test-pe.json' #推論データ
repeat_count = 3 #繰返し学習回数
score_thr = 0.0 #スコア閾値
# Jubatusサーバに接続
classifier = Classifier('127.0.0.1', 9199, "", 10.0)
# 学習開始
print("Learn")
# データ件数がやや少ないのでrepeat_count回繰返し学習
for count in range(repeat_count):
for line in open(sTraindata):
# JSON形式のデータを変換
item = json.loads(line)
# malwareか否かの分類を取得
label = "malware" if item["malware"] else "normal"
# 学習
classifier.train(
[LabeledDatum(label, set_datum(item))])
# 分類開始
print("Classify")
for line in open(sTestdata):
# JSON形式のデータを変換
item = json.loads(line)
# 推論
ans = classifier.classify([set_datum(item)])
# マルウェア判定
score = 0.0
for a in ans[0]:
if a.label == "malware":
score = a.score
estm = "malware" if score > score_thr else "normal"
# 結果出力: 分類,スコア,ファイル名
print(estm + ", " + str(score) + ", " + item["file_name"])
sys.stdout.flush()
Jubatus
0.5.0
18 © 2013 NTT Secure Platform Laboratories
一つの分類器で2つ判定する 1/2
• ハッシュ値一致判定とヒューリスティック判定を「1つのJubatus分類器」でしたい。
⇒
★ 普通に混ぜて書けばよい
※ 特徴のKey名が重複していないことが条件
• 学習;
classifier.train("", [("malware",
types.datum([["sha1", "0c693894e86aa5618aa83a96e153a7ea943354de"],[]])])
classifier.train("", [("malware", types.datum([["characteristics", " Relocations_stripped
Executable Line_numbers_stripped Symbols_stripped 32_bit_word_machine "],
["entry_point", "200"], ["section_names",".text .rdata"], ["num_sections","2"]], []))]) …..
• 推論
ans1 = classifier.classify("",[(
types.datum([["sha1", "0c693894e86aa5618aa83a96e153a7ea943354de "],[]]))])
ans2 = classifier.classify("",[(types.datum([["characteristics", " Relocations_stripped
Executable Line_numbers_stripped Symbols_stripped 32_bit_word_machine "],
["entry_point", "200"], ["section_names",".text .rdata"], ["num_sections","2"]], []))])
ans1 の 内容 (イメージ): [["malware", 0.5]]
ans2 の 内容 (イメージ): [["malware", 0.9321], ["normal", -0.8632]]
19 © 2013 NTT Secure Platform Laboratories
一つの分類器で2つ判定する 2/2
• なんでできるの?
• 学習: 学習モデルの係数を適切に更新するのが学習。
その際、指定されていない特徴の係数は更新されないため。
– train時に"sha1"の特徴しか指定していないとき、
他の”characteristics”等の特徴に関する学習は全く行われない。
• 推論:指定されていない特徴は、特徴量=0になる。
なのでスコア算出で無関係になる。
– classify時に"sha1"の特徴しか指定していないとき、
他の”characteristics”等の特徴はスコア計算にまったく影響しない。
20 © 2013 NTT Secure Platform Laboratories
実験
○実験方法: leave-one-out 交差検証
1つのデータだけを推論データとし、残りすべてを教師データにする。
これを全データ繰り返す。
0. 1つの推論データと残り全部の教師データに分割
1. Jubatusの学習モデルを初期化 (clear)
2. 教師データをハッシュ一致判定、ヒューリスティック判定の両方で学習
3. 1つの推論データを判定・記録。ハッシュ一致判定、ヒューリスティック判定両方とも実施。
• 判定結果(malware/normal)と、その判定が正解か不正解か(OK/NG)を記録
• ハッシュ一致判定ではマルウェアが不一致だった場合は判定不正解(NG)、通常ファイルが不一致だった場合は正解(OK)とする。
4. 別のデータ1つを推論データにし、残りを教師データに分割
全データが1度は推論データとなるまで、1 以降を繰り返す。
5. ハッシュ一致判定、ヒューリスティック判定、それぞれで判定率を算出
TPR = (判定結果がmalware かつ 判定正解(OK)) の件数 / 全マルウェア数
FPR = (判定結果がmalware かつ 判定不正解(NG)) の件数 / 全通常ファイル数
長所: データを余すことなく
評価できる
短所: 時間が非常にかかる
⇒Jubatusは学習も早いので、
この手法が可能
21 © 2013 NTT Secure Platform Laboratories
判定結果
○実験 第1回目
– マルウェア: Malware.lu 2013年 2月分 261個
– 通常ファイル: 業務用PCの Program Files 配下のファイル 574個
• ハッシュ一致判定率
– TPR= 81%、FPR=0% (マルウェア 211個を一致判定)
⇒ ハッシュ値がユニークなマルウェアは88種、他は別ファイル名にしただけのコピーだったため
• ヒューリスティック判定率
– スコア閾値 = 0: TPR = 90%、FPR = 2.4% : AUC = 0.981
○実験 第2回目: ハッシュ値が同一だったマルウェアは1つだけ使うこととした
– マルウェア: 88個
– 通常ファイル: 574個
• ハッシュ一致判定率
– TPR= 0%、FPR=0% (全部不一致になるのであたりまえ)
• ヒューリスティック判定率
– スコア閾値 = 0 : TPR= 92% FPR=12%
– スコア閾値 = -0.32: TPR=100% FPR=84%
– スコア閾値 = 0.86: TPR=26% FPR=0%
– AUC = 0.924 (1に近いほど良く、0.5に近いほど悪い)
意外と判定できているが、
「完璧」を目指すと難しい
ちょっと卑怯なので
再実験
22 © 2013 NTT Secure Platform Laboratories
学習モデルの中身をみる
• スコアの計算方法:
スコア = 学習モデルの係数 ・ 特徴ベクトル (・ は内積)
• 係数が大きいものほど、マルウェアによく現れる「語」である。
★ セーブファイルから係数をダンプするC++プログラム ”dump_features" を作りました
– storage_baseクラスを継承して作成
– ぶっちゃけ、local_storageクラスのソースコードから必要な部分をコピペしたのがほとんど
• 出力例
dump_features /tmp/192.168.122.219_9199_jubatus_pe.js
#c ClassID ClassName
0 normal
1 malware
#f FeatureName ClassID Weight
num_sections$2@space#bin/bin 0 -0.152445
num_sections$2@space#bin/bin 1 0.152445
characteristics$Debug_information_stripped@space#bin/bin 0 0.267797
characteristics$Debug_information_stripped@space#bin/bin 1 -0.256519
entry_point$E213@space#bin/bin 0 -0.157051
entry_point$E213@space#bin/bin 1 0.157051
section_names$UPX1@space#bin/bin 0 -0.064586
section_names$UPX1@space#bin/bin 1 0.064586
num_sections$2@space#bin/bin
↓ ↓ ↓
特徴のKey名 特徴 "string_rules"
Jubatus
0.4.4+
23 © 2013 NTT Secure Platform Laboratories
(参考) jubadump
• https://github.com/jubatus/jubadump
Jubatus
0.5.0
jubadump -t classifier –i ¥
/tmp/192.168.122.219_9199_jubatus_pe.jubatus {
"weights": {
"document_frequencies": {
"num_sections$2@space#bin¥/bin": 75,
"characteristics$Debug_information_stripped@
space#bin¥/bin": 189,
"entry_point$E213@space#bin¥/bin": 3,
"section_names$UPX1@space#bin¥/bin": 36,
(中略) },
"document_count": 1986
},
"storage": {
"weight": {
"num_sections$2@space#bin¥/bin": {
"normal": {
"v2": 0.105731543441,
"v1": -0.152445334206,
"v3": 0
}
"malware": {
"v2": 0.105731543441,
"v1": 0.152445334206,
"v3": 0
},
"characteristics$Debug_information_stripped@
space#bin¥/bin": {
"normal": {
"v2": 0.080512960942,
"v1": 0.267797104461,
"v3": 0
}
"malware": {
"v2": 0.080512960942,
"v1": -0.256518908223,
"v3": 0
},
"entry_point$E213@space#bin¥/bin": {
"normal": {
"v2": 0.435413209842,
"v1": -0.15705101192,
"v3": 0
},
"malware": {
"v2": 0.435413209842,
"v1": 0.15705101192,
"v3": 0
}
},
(中略) }
}
}
特徴の出現数
学習したデータの件数
v2: 学習時に使用する変数
v1: スコア計算時の係数
24 © 2013 NTT Secure Platform Laboratories
数値データを文字列として扱う
• num_sectionsは整数値 ⇒ だけど数値型(type=num)で取り扱うと精度が悪くなる
• 係数をみると、マルウェアは、2 と 6が特徴的 num_sections$5@space#bin/bin 1 -0.121920
num_sections$3@space#bin/bin 1 -0.113202
num_sections$4@space#bin/bin 1 -0.093553
num_sections$8@space#bin/bin 1 -0.050809
num_sections$10@space#bin/bin 1 -0.037065
num_sections$7@space#bin/bin 1 0.080426
num_sections$6@space#bin/bin 1 0.110195
num_sections$2@space#bin/bin 1 0.152445
• 数値型だと、直線で近似しようとするので、凹凸がある場合はうまく近似できない
スコア
num_section
1
-1
2 3 4 5 6 1
典型例)
num_sections = 2 :
小サイズのトロイの木馬。実行後、マルウェア本体をダウンロードしようとする。
num_sections = 6 :
難読化処理用に1つ余計なセグメントがついている。
type=num
type=space
25 © 2013 NTT Secure Platform Laboratories
まとめ
• Jubatusはテキスト情報の機械学習がすごく得意だけど、
マルウェアのようなバイナリ情報の機械学習も
特徴抽出を工夫すれば OK。
•スコア値判定も工夫すると意外な使い方ができるかも。
•学習モデルの中身を見れば、
データマイニング的な使い方もできそう。
•Free 万歳 !!
26 © 2013 NTT Secure Platform Laboratories
(参考) 学習モデル係数ダンプツール 1/3
// dump_features jubaclassifier_SAVEFILE
// for Jubatus 0.4.4+, copyright 2013, NTT.
// c++ dump_features.cpp -lmsgpack -lpficommon ¥
// -ljubastorage -o dump_features
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <jubatus/core/common/exception.hpp>
#include <jubatus/core/common/key_manager.hpp>
#include <jubatus/core/storage/storage_base.hpp>
#include <jubatus/core/storage/storage_type.hpp>
#define DELI "¥t"
using std::string;
typedef pfi::data::unordered_map<uint64_t,
jubatus::core::storage::val3_t> id_feature_val3_t;
typedef pfi::data::unordered_map<std::string,
id_feature_val3_t> id_features3_t;
class dump_local_storage : public
jubatus::core::storage::storage_base {
public:
void dump_classes();
void dump_weights();
void clear();
bool save(std::ostream&);
bool load(std::istream&);
dump_local_storage() {}
~dump_local_storage() {}
void get(const std::string &feature,
jubatus::core::storage::feature_val1_t& ret) {}
void get2(const std::string &feature,
jubatus::core::storage::feature_val2_t& ret) {}
void get3(const std::string &feature,
jubatus::core::storage::feature_val3_t& ret) {}
void inp(const jubatus::core::common::sfv_t& sfv,
jubatus::core::storage::map_feature_val1_t& ret) {}
void set(
const std::string& feature,
const std::string& klass,
const jubatus::core::storage::val1_t& w) {}
void set2(
const std::string& feature,
const std::string& klass,
const jubatus::core::storage::val2_t& w) {}
void set3(
const std::string& feature,
const std::string& klass,
const jubatus::core::storage::val3_t& w) {}
void get_status(std::map<std::string, std::string>&) {}
Jubatus
0.4.4+
27 © 2013 NTT Secure Platform Laboratories
(参考) 学習モデル係数ダンプツール 2/3
void update(
const std::string& feature,
const std::string& inc_class,
const std::string& dec_class,
const jubatus::core::storage::val1_t& v) {}
void bulk_update(
const jubatus::core::common::sfv_t& sfv,
float step_width,
const std::string& inc_class,
const std::string& dec_class) {}
std::string type() const;
private:
id_features3_t tbl_;
jubatus::core::common::key_manager class2id_;
friend class pfi::data::serialization::access;
template <class Ar>
void serialize(Ar& ar) {
ar & MEMBER(tbl_) & MEMBER(class2id_);
}
};
void dump_local_storage::clear() {
// Clear and minimize
id_features3_t().swap(tbl_);
jubatus::core::common::key_manager().swap(class2id_);
}
bool dump_local_storage::save(std::ostream& os) {
pfi::data::serialization::binary_oarchive oa(os);
oa << *this;
return true;
}
bool dump_local_storage::load(std::istream& is) {
pfi::data::serialization::binary_iarchive ia(is);
ia >> *this;
return true;
}
std::string dump_local_storage::type() const {
return "dump_local_storage";
}
Jubatus
0.4.4+
28 © 2013 NTT Secure Platform Laboratories
(参考) 学習モデル係数ダンプツール 3/3
// 全分類のダンプ
void dump_local_storage::dump_classes() {
std::cout << "#c ClassID" << DELI << "ClassName" <<
std::endl;
for (int i=0; i < class2id_.size(); ++i) {
std::cout << i << DELI << class2id_.get_key(i) <<
std::endl;
}
}
// 全係数のダンプ
void dump_local_storage::dump_weights() {
std::cout.setf(std::ios::fixed, std::ios::floatfield);
std::cout << "#f FeatureName" << DELI << "ClassID" <<
DELI << "Weight" << std::endl;
for (id_features3_t::const_iterator it2 = tbl_.begin(); it2 !=
tbl_.end(); ++it2){
const id_feature_val3_t& m = it2->second;
for (id_feature_val3_t::const_iterator it3 = m.begin();
it3 != m.end(); ++it3) {
std::cout << it2->first << DELI << it3->first << DELI <<
it3->second.v1 << std::endl;
}
}
}
int main( int argc, char* argv[] )
{
if (argc < 2) {
std::cerr << "usage: " << argv[0] <<
"Jubclassifier_SAVEFILE" << std::endl;
return (1);
}
std::ifstream ifs(argv[1], std::ios::binary);
if (!ifs) {
std::cerr << "cannot open input file: " << argv[1] <<
std::endl;
return (1);
}
dump_local_storage model;
model.clear();
model.load(ifs);
model.dump_classes();
std::cout << std::endl;
model.dump_weights();
std::cout << std::endl;
return 0;
}
Jubatus
0.4.4+