28
セキュアプラットフォーム研究所 © 2013 NTT Secure Platform Laboratories NTTセキュアプラットフォーム研究所 NTT Secure Platform Laboratories Jubatus分類器の活用テクニック ~マルウェアの静的判定を題材として~ Jubatus Casual Talk #2 20131214

Jubatus分類器の活用テクニック

Embed Size (px)

DESCRIPTION

Jubatus分類器の活用テクニック

Citation preview

Page 1: Jubatus分類器の活用テクニック

セキュアプラットフォーム研究所

© 2013 NTT Secure Platform Laboratories

NTTセキュアプラットフォーム研究所

NTT Secure Platform Laboratories

Jubatus分類器の活用テクニック ~マルウェアの静的判定を題材として~

Jubatus Casual Talk #2

2013年 12月 14日

Page 2: Jubatus分類器の活用テクニック

2 © 2013 NTT Secure Platform Laboratories

はじめに

この発表の目的はただ1つ

Jubatus分類器の活用テクニックを伝授 !!

•分類器なのに、一致検索の用途でも使えちゃう

•分類時のスコア、有効に活用してますか?

•複数分類するときでも、Jubatus分類器1つにまとめる方法

•どうして分類できてるのか、学習の中身を知りたくないですか?

奇妙な

Page 3: Jubatus分類器の活用テクニック

3 © 2013 NTT Secure Platform Laboratories

なぜ機械学習でマルウェア判定するの?

異常データ=マルウェアと見做して、機械学習を使ってマルウェア判定したい。

⇒機械学習で未知のマルウェアが検出できるのでは、という期待

異常データがある程度手に入る場合は分類器でも異常判定できる。

以下の場合は異常検知器より分類器の方が適しているという感触:

• 異常データに特有な値がある場合

• 正常データに特にまとまった傾向が見られない場合

• 教師データが大量にある場合

研究用マルウェアは意外と入手できる

• MWS 研究用データセット: http://www.iwsec.org/mws/2013/about.html

• Malware.lu : http://malware.lu 等

MS Windowsの実行形式ファイル(EXEファイル)でマルウェアの静的判定を

Jubatus分類器で行えないかを試みたのでご紹介

(静的判定=ファイルを実行せずに判定すること)

Page 4: Jubatus分類器の活用テクニック

4 © 2013 NTT Secure Platform Laboratories

マルウェアの静的判定手法

• 一般的なウィルススキャンソフトの処理 (静的判定)

–ハッシュ値一致判定

ファイルのハッシュ値(MD5、SHA1、SHA256等)を取って、

既知のマルウェアのハッシュ値と一致するかをチェック

–パターンマッチ判定 (シグニチャスキャン) マルウェアに含まれる特定の文字列やバイトコードがあるかをチェック。

(例) マルウェア ZeuSボット系亜種はプログラム中に“ZeuS”という文字列がある。

– ヒューリスティック判定

これまでの経験から「マルウェアらしさ」を定義し、その定義に従って判定する。

実際の手法は各社様々。行動パターンで推論するものが多いらしい。

(例) 「既存のEXEファイルを開いて、最後尾にコードを追加後、保存する」行動はウィルス。 (バイトコードのパターンマッチ判定で実装する場合もある。)

Page 5: Jubatus分類器の活用テクニック

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] ◎

Page 6: Jubatus分類器の活用テクニック

6 © 2013 NTT Secure Platform Laboratories

今回試作するマルウェアの静的判定器

○ 今回の実装のルール(縛り)

• ハッシュ値一致判定もヒューリスティック判定もJubatus分類器で作る

• ヒューリスティック判定は誤検知率 0% にできるか試みる (感度調整) (マルウェアを100%検知する、または、通常ファイルをマルウェアと誤検知しない)

• 2つの判定器を1つのJubatus分類器でまかなう

構成

マルウェア/

通常ファイル

JSON形式

データ

ハッシュ値

一致判定

PEヘッダでのヒューリスティック判定

Page 7: Jubatus分類器の活用テクニック

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"}

Page 8: Jubatus分類器の活用テクニック

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

Page 9: Jubatus分類器の活用テクニック

9 © 2013 NTT Secure Platform Laboratories

(参考) 今回利用したPEヘッダの説明

PEヘッダ項目 説明

characteristics このファイルの特性。

実行ファイルかDLLか、32ビットアーキテクチャのマシン用か、デバッグ情報を削除しているか等の情報がある。

entry_point エントリポイント(実行開始位置)のアドレス

section_names

セクション名。

セクションとは、メモリを利用特性に応じて区分したもので、実行コードがあるコード領域、表示メッセージ等の静的データがあるデータ領域等がある。

セクション名自体には特別な意味はないが、良く使われる名前がある。 (.text、 .rdata、 .idata、.rsrc、.bss、.reloc、.tls等)

num_sections セクション数

Page 10: Jubatus分類器の活用テクニック

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

}

}

以下の設定を使用します;

Page 11: Jubatus分類器の活用テクニック

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個返ってきた : 教師データに同じハッシュ値を持つマルウェアと通常ファイルあり。非常に稀。 (ハッシュ値の衝突を偶然にも見つけてしまった。)

Page 12: Jubatus分類器の活用テクニック

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

Page 13: Jubatus分類器の活用テクニック

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

Page 14: Jubatus分類器の活用テクニック

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 だが、動かすと「感度調整」が可能。

Page 15: Jubatus分類器の活用テクニック

15 © 2013 NTT Secure Platform Laboratories

Jubatus分類器でヒューリスティック判定 2/2

◆真陽性率 (大きい方が良い) (True Positive Rate)

= マルウェアと

正しく判定できた割合

= (正しく判定した

マルウェア数) ÷

(全マルウェア数)

■偽陽性率 (小さい方が良い) (False Positive Rate)

= マルウェアと

間違って判定した割合

= (間違ってマルウェアと

判定した通常ファイル数)÷

(全通常ファイル数)

スコア閾値

マルウェア判定率

間違いは減るが、

取りこぼしが増える

取りこぼしは減るが、

間違いが増える 閾値を減らす

閾値を増やす

Page 16: Jubatus分類器の活用テクニック

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

Page 17: Jubatus分類器の活用テクニック

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

Page 18: Jubatus分類器の活用テクニック

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]]

Page 19: Jubatus分類器の活用テクニック

19 © 2013 NTT Secure Platform Laboratories

一つの分類器で2つ判定する 2/2

• なんでできるの?

• 学習: 学習モデルの係数を適切に更新するのが学習。

その際、指定されていない特徴の係数は更新されないため。

– train時に"sha1"の特徴しか指定していないとき、

他の”characteristics”等の特徴に関する学習は全く行われない。

• 推論:指定されていない特徴は、特徴量=0になる。

なのでスコア算出で無関係になる。

– classify時に"sha1"の特徴しか指定していないとき、

他の”characteristics”等の特徴はスコア計算にまったく影響しない。

Page 20: Jubatus分類器の活用テクニック

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は学習も早いので、

この手法が可能

Page 21: 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に近いほど悪い)

意外と判定できているが、

「完璧」を目指すと難しい

ちょっと卑怯なので

再実験

Page 22: Jubatus分類器の活用テクニック

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+

Page 23: Jubatus分類器の活用テクニック

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: スコア計算時の係数

Page 24: Jubatus分類器の活用テクニック

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

Page 25: Jubatus分類器の活用テクニック

25 © 2013 NTT Secure Platform Laboratories

まとめ

• Jubatusはテキスト情報の機械学習がすごく得意だけど、

マルウェアのようなバイナリ情報の機械学習も

特徴抽出を工夫すれば OK。

•スコア値判定も工夫すると意外な使い方ができるかも。

•学習モデルの中身を見れば、

データマイニング的な使い方もできそう。

•Free 万歳 !!

Page 26: Jubatus分類器の活用テクニック

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+

Page 27: Jubatus分類器の活用テクニック

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+

Page 28: Jubatus分類器の活用テクニック

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+