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

10,698 views

Published on

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

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
10,698
On SlideShare
0
From Embeds
0
Number of Embeds
8,008
Actions
Shares
0
Downloads
28
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

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

  1. 1. NTT Secure Platform Laboratories NTTセキュアプラットフォーム研究所 Jubatus分類器の活用テクニック ~マルウェアの静的判定を題材として~ Jubatus Casual Talk #2 2013年 12月 14日 セキュアプラットフォーム研究所 © 2013 NTT Secure Platform Laboratories
  2. 2. はじめに この発表の目的はただ1つ 奇妙な Jubatus分類器の活用テクニックを伝授 !! • 分類器なのに、一致検索の用途でも使えちゃう • 分類時のスコア、有効に活用してますか? • 複数分類するときでも、Jubatus分類器1つにまとめる方法 • どうして分類できてるのか、学習の中身を知りたくないですか? 2 © 2013 NTT Secure Platform Laboratories
  3. 3. なぜ機械学習でマルウェア判定するの? 異常データ=マルウェアと見做して、機械学習を使ってマルウェア判定したい。 ⇒機械学習で未知のマルウェアが検出できるのでは、という期待 異常データがある程度手に入る場合は分類器でも異常判定できる。 以下の場合は異常検知器より分類器の方が適しているという感触: • 異常データに特有な値がある場合 • 正常データに特にまとまった傾向が見られない場合 • 教師データが大量にある場合 研究用マルウェアは意外と入手できる • MWS 研究用データセット: http://www.iwsec.org/mws/2013/about.html • Malware.lu : http://malware.lu 等 MS Windowsの実行形式ファイル(EXEファイル)でマルウェアの静的判定を Jubatus分類器で行えないかを試みたのでご紹介 (静的判定=ファイルを実行せずに判定すること) 3 © 2013 NTT Secure Platform Laboratories
  4. 4. マルウェアの静的判定手法 • 一般的なウィルススキャンソフトの処理 (静的判定) – ハッシュ値一致判定 ファイルのハッシュ値(MD5、SHA1、SHA256等)を取って、 既知のマルウェアのハッシュ値と一致するかをチェック – パターンマッチ判定 (シグニチャスキャン) マルウェアに含まれる特定の文字列やバイトコードがあるかをチェック。 (例) マルウェア ZeuSボット系亜種はプログラム中に“ZeuS”という文字列がある。 – ヒューリスティック判定 これまでの経験から「マルウェアらしさ」を定義し、その定義に従って判定する。 実際の手法は各社様々。行動パターンで推論するものが多いらしい。 (例) 「既存のEXEファイルを開いて、最後尾にコードを追加後、保存する」行動はウ ィルス。 (バイトコードのパターンマッチ判定で実装する場合もある。) 4 © 2013 NTT Secure Platform Laboratories
  5. 5. 機械学習を用いたヒューリスティック判定手法 着目点 コード バイト列などに注目、機械学習し、攻撃コードに似た部分の探 [伊沢2013] 索や似ているコード群での分類を実施 [鐘2012] API ◎ 説明 参考文献 コールしているAPIの種類や数、順番等に着目して機械学習、 [Ye2008] 利用APIの組や、APIの実行順の近似等で分類・判定 メモリ 配置情報 実行時のメモリ配置、サイズ、開始アドレス等の情報を機械学 [Shafiq2009] 習、マルウェアに特徴的なプロファイルを作成し、分類・判定 ⇒ 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. 5 © 2013 NTT Secure Platform Laboratories
  6. 6. 今回試作するマルウェアの静的判定器 構成 マルウェア/ 通常ファイル JSON形式 データ ハッシュ値 一致判定 PEヘッダでのヒュー リスティック判定 ○ 今回の実装のルール(縛り) • ハッシュ値一致判定もヒューリスティック判定もJubatus分類器で作る • ヒューリスティック判定は誤検知率 0% にできるか試みる (感度調整) (マルウェアを100%検知する、または、通常ファイルをマルウェアと誤検知しない) • 2つの判定器を1つのJubatus分類器でまかなう 6 © 2013 NTT Secure Platform Laboratories
  7. 7. マルウェアから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"} 7 © 2013 NTT Secure Platform Laboratories
  8. 8. マルウェアからJSON形式データを作成 2/2 C:¥work¥test>set Path=C:¥Program Files¥Microsoft Visual S tudio 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 num_sections characteristics 8 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 entry_point section_names Section Name SECTION HEADER #2 .rdata name (以下略) © 2013 NTT Secure Platform Laboratories
  9. 9. (参考) 今回利用したPEヘッダの説明 PEヘッダ項目 characteristics このファイルの特性。 実行ファイルかDLLか、32ビットアーキテクチャのマシン用か、デ バッグ情報を削除しているか等の情報がある。 entry_point エントリポイント(実行開始位置)のアドレス section_names セクション名。 セクションとは、メモリを利用特性に応じて区分したもので、実行 コードがあるコード領域、表示メッセージ等の静的データがあるデ ータ領域等がある。 セクション名自体には特別な意味はないが、良く使われる名前が ある。 (.text、 .rdata、 .idata、.rsrc、.bss、.reloc、.tls等) num_sections 9 説明 セクション数 © 2013 NTT Secure Platform Laboratories
  10. 10. (参考) 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 } } 10 © 2013 NTT Secure Platform Laboratories
  11. 11. 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個返ってきた : 教師データに同じハッシュ値を持つマルウェアと通常ファイルあり。 非常に稀。 (ハッシュ値の衝突を偶然にも見つけてしまった。) 11 © 2013 NTT Secure Platform Laboratories
  12. 12. (参考) 一致判定 サンプルコード #!/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)]) 12 Jubatus 0.4.X # 分類開始 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() © 2013 NTT Secure Platform Laboratories
  13. 13. (参考) 一致判定 サンプルコード #!/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)]) 13 Jubatus 0.5.0 # 分類開始 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() © 2013 NTT Secure Platform Laboratories
  14. 14. 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 だが、動かすと「感度調整」が可能。 14 © 2013 NTT Secure Platform Laboratories
  15. 15. Jubatus分類器でヒューリスティック判定 2/2 マルウェア判定率 ◆真陽性率 (大きい方が良い) (True Positive Rate) = マルウェアと 正しく判定できた割合 = (正しく判定した マルウェア数) ÷ (全マルウェア数) ■偽陽性率 (小さい方が良い) (False Positive Rate) = マルウェアと 間違って判定した割合 = (間違ってマルウェアと 判定した通常ファイル数)÷ (全通常ファイル数) スコア閾値 取りこぼしは減るが、 間違いが増える 15 閾値を 減らす 閾値を 増やす 間違いは減るが、 取りこぼしが増える © 2013 NTT Secure Platform Laboratories
  16. 16. (参考) ヒューリスティック判定 サンプルコード #!/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): 16 Jubatus 0.4.X 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() © 2013 NTT Secure Platform Laboratories
  17. 17. (参考) ヒューリスティック判定 サンプルコード #!/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回繰返し学習 17 Jubatus 0.5.0 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() © 2013 NTT Secure Platform Laboratories
  18. 18. 一つの分類器で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]] 18 © 2013 NTT Secure Platform Laboratories
  19. 19. 一つの分類器で2つ判定する 2/2 • なんでできるの? • 学習: 学習モデルの係数を適切に更新するのが学習。 その際、指定されていない特徴の係数は更新されないため。 – train時に"sha1"の特徴しか指定していないとき、 他の”characteristics”等の特徴に関する学習は全く行われない。 • 推論:指定されていない特徴は、特徴量=0になる。 なのでスコア算出で無関係になる。 – classify時に"sha1"の特徴しか指定していないとき、 他の”characteristics”等の特徴はスコア計算にまったく影響しない。 19 © 2013 NTT Secure Platform Laboratories
  20. 20. 実験 ○実験方法: leave-one-out 交差検証 1つのデータだけを推論データとし、残りすべてを教師データにする。 これを全データ繰り返す。 長所: データを余すことなく 評価できる 0. 1つの推論データと残り全部の教師データに分割 短所: 時間が非常にかかる ⇒Jubatusは学習も早いので、 1. Jubatusの学習モデルを初期化 (clear) この手法が可能 2. 教師データをハッシュ一致判定、ヒューリスティック判定の両方で学習 3. 1つの推論データを判定・記録。ハッシュ一致判定、ヒューリスティック判定両方とも実施。 • 判定結果(malware/normal)と、その判定が正解か不正解か(OK/NG)を記録 • ハッシュ一致判定ではマルウェアが不一致だった場合は判定不正解(NG)、通常ファイルが不一致だっ た場合は正解(OK)とする。 4. 別のデータ1つを推論データにし、残りを教師データに分割 全データが1度は推論データとなるまで、1 以降を繰り返す。 5. ハッシュ一致判定、ヒューリスティック判定、それぞれで判定率を算出 TPR = (判定結果がmalware かつ 判定正解(OK)) の件数 / 全マルウェア数 FPR = (判定結果がmalware かつ 判定不正解(NG)) の件数 / 全通常ファイル数 20 © 2013 NTT Secure Platform Laboratories
  21. 21. 判定結果 ○実験 第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% (全部不一致になるのであたりまえ) • ヒューリスティック判定率 – – – – 21 スコア閾値 = 0 : TPR= 92% FPR=12% スコア閾値 = -0.32: TPR=100% FPR=84% スコア閾値 = 0.86: TPR=26% FPR=0% AUC = 0.924 (1に近いほど良く、0.5に近いほど悪い) 意外と判定できているが、 「完璧」を目指すと難しい © 2013 NTT Secure Platform Laboratories
  22. 22. 学習モデルの中身をみる Jubatus 0.4.4+ • スコアの計算方法: スコア = 学習モデルの係数 ・ 特徴ベクトル (・ は内積) • 係数が大きいものほど、マルウェアによく現れる「語」である。 ★ セーブファイルから係数をダンプする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 num_sections$2@space#bin/bin num_sections$2@space#bin/bin characteristics$Debug_information_stripped@space#bin/bin characteristics$Debug_information_stripped@space#bin/bin entry_point$E213@space#bin/bin entry_point$E213@space#bin/bin section_names$UPX1@space#bin/bin section_names$UPX1@space#bin/bin 22 num_sections$2@space#bin/bin ↓ ↓ ↓ 特徴のKey名 特徴 "string_rules" ClassID 0 1 0 1 0 1 0 1 Weight -0.152445 0.152445 0.267797 -0.256519 -0.157051 0.157051 -0.064586 0.064586 © 2013 NTT Secure Platform Laboratories
  23. 23. (参考) jubadump Jubatus 0.5.0 • https://github.com/jubatus/jubadump 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@ 23 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 }, v2: 学習時に "malware": { 使用する変数 "v2": 0.435413209842, "v1": 0.15705101192, v1: スコア計 "v3": 0 } 算時の係数 }, (中略) } } } © 2013 NTT Secure Platform Laboratories
  24. 24. 数値データを文字列として扱う • num_sectionsは整数値 ⇒ だけど数値型(type=num)で取り扱うと精度が悪くなる • 係数をみると、マルウェアは、2 と 6が特徴的 典型例) num_sections$5@space#bin/bin 1 -0.121920 num_sections = 2 : 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 : num_sections$6@space#bin/bin 1 0.110195 難読化処理用に1つ余計 num_sections$2@space#bin/bin 1 0.152445 なセグメントがついている。 • 数値型だと、直線で近似しようとするので、凹凸がある場合はうまく近似できない スコア 1 1 2 3 4 5 6 num_section type=space type=num -1 24 © 2013 NTT Secure Platform Laboratories
  25. 25. まとめ • Jubatusはテキスト情報の機械学習がすごく得意だけど、 マルウェアのようなバイナリ情報の機械学習も 特徴抽出を工夫すれば OK。 • スコア値判定も工夫すると意外な使い方ができるかも。 • 学習モデルの中身を見れば、 データマイニング的な使い方もできそう。 •Free 万歳 !! 25 © 2013 NTT Secure Platform Laboratories
  26. 26. (参考) 学習モデル係数ダンプツール 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(); 26 Jubatus 0.4.4+ 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>&) {} © 2013 NTT Secure Platform Laboratories
  27. 27. (参考) 学習モデル係数ダンプツール 2/3 Jubatus 0.4.4+ 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; void dump_local_storage::clear() { // Clear and minimize id_features3_t().swap(tbl_); jubatus::core::common::key_manager().swap(class2id_); } 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_); } }; bool dump_local_storage::load(std::istream& is) { pfi::data::serialization::binary_iarchive ia(is); ia >> *this; return true; } 27 bool dump_local_storage::save(std::ostream& os) { pfi::data::serialization::binary_oarchive oa(os); oa << *this; return true; } std::string dump_local_storage::type() const { return "dump_local_storage"; } © 2013 NTT Secure Platform Laboratories
  28. 28. (参考) 学習モデル係数ダンプツール 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; } } Jubatus 0.4.4+ 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); } // 全係数のダンプ 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; } } } 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; } 28 © 2013 NTT Secure Platform Laboratories

×