機器學習方法檢測惡意檔案
1. 惡意檔案的傳統檢測方法
惡意檔案檢測在機器學習方法流行之前,一直是防毒引擎的黑箱技術,很少為外界所周知。對於一般粗淺的應用者而言,最簡單的做法是有兩種:
1. 尋找各種開源的病毒庫或者威脅情報網站,收集惡意檔案的MD5值,作為黑名單使用。
2. 同時整合各種知名的防毒軟體或者沙箱,然後儲存每個防毒軟體或沙箱對惡意檔案的執行結果,然後綜合所有的執行結果做綜合判定:設定判定規則,或者用機器學習的方法做模型判定。
2. 機器學習的惡意檔案檢測
那麼更智慧的機器學習方法如何做惡意檔案檢測呢?論文《Deep Neural Network Based Malware Detection Using Two Dimensional Binary Program Features》給出了使用深度學習檢測惡意程式的具體方法,在論文中他們描述了具體的特徵提取方法,並在約40萬程式上進行了測試,檢出率達到95%,誤報率為0.1%。
隨後《Web安全之強化學習與GAN》一書總結了上述論文的特徵提取方法,以及如何用Python工具做具體的實現。這裡作為讀書筆記記錄如此,便於以後溫故而知新。
2.1 PE首部特徵提取
2.1.1 特徵直方圖
本質上PE檔案也是二進位制檔案,可以當作一連串位元組組成的檔案。位元組直方圖又稱為ByteHistogram,它的核心思想是,定義一個長度為256維的向量,每個向量依次為0x00,0x01一直到0xFF,分別代表 PE檔案中0x00,0x01一直到0xFF對應的個數。例如經過統計,0x01有兩個,0x03和0x05對應的各一個,假設直方圖維度為8,所以對應的直方圖為:[0,2,0,1,0,0,1,0,0]
Python中實現自己直方圖非常方便,主要是numPy提供了一個非常強大的函式:
numpy.bincount(x, weights=None, minlength=None)
numpy.bincount專門用於以位元組為單位統計個數,比如統計0~7出現的個數:
>>> np.bincount(np.array([0, 1, 1, 3, 2, 1, 7])) array([1, 3, 1, 1, 0, 0, 0, 1], dtype=int32)
其中, minlength引數用於指定返回的統計陣列的最小長度,不足最小長度的會自動補0,比如統計0~7出現的個數,但是指定minlength為10:
>>> np.bincount(np.array([0, 1, 1, 3, 2, 1, 7]),minlength=10) array([1, 3, 1, 1, 0, 0, 0, 1, 0, 0], dtype=int32)
實際使用時,單純統計直方圖非常容易過擬合,因為位元組直方圖對於PE檔案的二進位制特徵過於依賴,PE檔案增加一個無意義的0位元組都會改變直方圖;另外PE檔案中不同位元組的數量可能差別很大,數 量佔優勢的位元組可能會大大弱化其他位元組對結果的影響,所以需要對直方圖進行標準化處理。一種常見的處理方式是,增加一個維度的變數,用於統計PE檔案的位元組總數,同時原有直方圖按照位元組總數取 平均值。
2.1.2 位元組熵直方圖
若信源符號有n種取值:U1 ,U2 ,U3 ,…,Un ,對應概率為:P1 ,P2 ,P3 ,…,Pn ,且各種符號的出現彼此獨立。這時,信源的資訊熵定義如下:
通常,log是以2為底。
PE檔案同樣可以使用位元組的資訊熵來當作特徵。我們把PE檔案當作一個位元組組成的陣列,如圖8-5所示,在這個陣列上以2048位元組為視窗,以1024位元組為步長計算熵。
2.1.3 文字特徵
惡意檔案通常在文字特徵方面與正常檔案有所區分,比如硬編碼上線IP和C&C域名等,我們進一步提取PE檔案的文字特徵,下面我們先總結需要關注的文字特徵。
- 可讀字串個數
- 平均可讀字串長度
- 可讀字元直方圖,由於可讀字元的個數為96個,所以我們定義一個長度為96的向量統計其直方圖。
- 可讀字元資訊熵.
- C盤路徑字串個數,惡意程式通常對被感染系統的根目錄有一定的檔案操作行為,表現在可讀字串中,可能會包含硬編碼的C盤路徑,我們將這類字串的個數作為一個維度。
- 登錄檔字串個數,惡意程式通常對被感染系統的登錄檔有一定的檔案操作行為,表現在可讀字串中,可能會包含硬編碼的登錄檔值,我們將這類字串的個數作為一個維度。登錄檔字串一般包含"HKEY_"字串,例如:self._registry = re.compile(b'HKEY_')
- URL字串個數,惡意程式通常從指定URL下載資源,最典型的就是下載者病毒,表現在可讀字串中,可能會包含硬編碼的URL,我們將這類字串的個數作為一個維度:self._urls = re.compile(b'https?://', re.IGNORECASE)
- ·MZ頭的個數,例如:self._mz = re.compile(b'MZ')
2.1.4 解析PE結構特徵
上面提到的位元組直方圖、位元組熵直方圖和文字特徵直方圖都可以把PE檔案當作位元組陣列處理即可獲得。但是有一些特徵我們必須按照PE檔案的格式進行解析後才能獲得,比較典型的就是檔案資訊。我 們定義需要關注的檔案資訊包括以下幾種:
- 是否包含debug資訊。
- 匯出函式的個數。
- 匯入函式的個數。
- 是否包含資原始檔。
- 是否包含訊號量。
- 是否啟用了重定向。
- 是否啟用了TLS回撥函式。
- 符號個數。
我們使用lief庫解析PE檔案:binary = lief.PE.parse(bytez)
我們定義一個維度為9的向量記錄我們關注的檔案資訊:
return np.asarray([
binary.virtual_size,
binary.has_debug,
len(binary.exported_functions),
len(binary.imported_functions),
binary.has_relocations,
binary.has_resources,
binary.has_signature,
binary.has_tls,len(binary.symbols),
]).flatten().astype(self.dtype)
2.1.5.檔案頭資訊
PE檔案頭中的資訊也是非常重要的資訊,下面我們對關注的內容做出說明。
- PE檔案的建立時間,例如:[binary.header.time_date_stamps]
- 機器碼 ,每個CPU擁有唯一的機器碼,雖然PE檔案把機器碼定義為一個WORD型別,即2個位元組。一種特徵定義方式就是直接把機器碼當成一個數字處理;另外一種方式就是類似詞袋的處理方式,定義一個固定 長度為N的詞袋,把機器碼轉換成一個維度為N的向量,例如:FeatureHasher(10, input_type="string", dtype=self.dtype).transform( [[str(binary.header.machine)]]).toarray(),
- 檔案屬性,檔案屬性中包含大量重要資訊,比如檔案是否是可執行的狀態,是否為DLL檔案等。例如:FeatureHasher(10, input_type="string", dtype=self.dtype).transform( [[str(c) for c in binary.header.characteristics_list]]).toarray()
- 該PE檔案所需的子系統,例如:FeatureHasher(10, input_type="string", dtype=self.dtype).transform( [[str(binary.optional_header.subsystem)]]).toarray()
- 該PE檔案所需的DLL檔案的屬性。 例如:FeatureHasher(10, input_type="string", dtype=self.dtype).transform( [[str(c) for c in binary.optional_header.dll_characteristics_lists]]).toarray()
- Magic,例如:FeatureHasher(10, input_type="string", dtype=self.dtype).transform( [[str(binary.optional_header.magic)]]).toarray()
- 映像的版本號,版本號有兩個維度:[binary.optional_header.major_image_version], [binary.optional_header.minor_image_version]
- 連結器的版本號,使用其版本號作為兩個維度:[binary.optional_header.major_linker_version], [binary.optional_header.minor_linker_version]
- 所需子系統版本號,例如:binary.optional_header.major_subsystem_version], [binary.optional_header.minor_subsystem_version]
- 所需作業系統的版本號,[binary.optional_header.major_operating_system_version], [binary.optional_header.minor_operating_system_version]
- 程式碼段的長度,[binary.optional_header.sizeof_code]
- 所有檔案頭的大小,[binary.optional_header.sizeof_headers]
2.1.6 匯出表
匯出表包含匯出函式的入口資訊,與檔案屬性處理方式相同:
FeatureHasher(128, input_type="string",dtype=self.dtype).transform([binary.exported_functions]).toarray().flatten().astype(self.dt)
2.1.7.匯入表
匯入表中儲存的是函式名和其駐留DLL名等動態連結所需的資訊,與匯出表處理方式類似,我們分別將匯入的庫檔案以及匯入的函式使用FeatureHasher轉換成維度為256和1024的向量:
libraries = [l.lower() for l in binary.libraries]
imports = [lib.name.lower() + ':' + e.name for lib in binary.imports for e in lib.entries]
return np.concatenate([
FeatureHasher(256, input_type="string", dtype=self.dtype).transform([libraries]).toarray(),
FeatureHasher(1024, input_type="string", dtype=self.dtype).transform([imports]).toarray() ],
axis=-1).flatten().astype(self.dtype)
其中,為了解決不同庫具有同名函式的問題,我們把匯入函式和對應的庫使用冒號連線成新的字串。
2.2 PE節中的特徵提取
整個PE的檔案結構如下:
之前提取的的是除節頭和節區之外的特徵。本節提取節頭和節區的特徵。
2.2.1 節頭特徵提取
- 節的個數:len(binary.sections)
- 長度為0的節的個數:sum(1 for s in binary.sections if s.size == 0)
- 名稱為空的節的個數:sum(1 for s in binary.sections if s.name == "")
- 可讀可執行的節的個數。可讀可執行,在lief中表示為:lief.PE.SECTION_CHARACTERISTICS.MEM_READ 和lief.PE.SECTION_CHARACTERISTICS.MEM_EXECUTE
- 統計可讀可執行的節的個數的方法為:sum(1 for s in binary.sections if s.has_characteristic(lief.PE.SECTION_CHARAC TERISTICS. MEM_READ) and s.has_characteristic(lief.PE.SECTION_CHARACTERISTICS.MEM_EXECUTE))
- 可寫的節的個數:sum(1 for s in binary.sections if s.has_characteristic( lief.PE.SECTION_CHARACTERISTICS.MEM_WRITE))
2.2.2 節大小的特徵
節的大小包括兩部分:一個是節在物理檔案中的大小,一個是節在記憶體中的大小。
section_sizes = [(s.name, len(s.content)) for s in binary.sections]
section_vsize = [(s.name, s.virtual_size) for s in binary.sections]
然後使用FeatureHasher均轉換成維度為50的向量:
FeatureHasher(50, input_type="pair", dtype=self.dtype).transform( [section_sizes]).toarray(),
FeatureHasher(50, input_type="pair", dtype=self.dtype).transform( [section_entropy]).toarray(),
FeatureHasher(50, input_type="pair", dtype=self.dtype).transform( [section_vsize]).toarray()
2.2.3 節的熵
統計節的熵:並使用FeatureHasher均轉換成維度為50的向量:
section_entropy = [(s.name, s.entropy) for s in binary.sections]
FeatureHasher(50, input_type="pair", dtype=self.dtype).transform( [section_entropy]).toarray()
2.2.4.節的入口點名稱和屬性
根據節的入口點(entry point),找到入口點的名稱和屬性。
entry = binary.section_from_offset(binary.entrypoint)
if entry is not None:
entry_name = [entry.name]
entry_characteristics = [str(c)
for c in entry.characteristics_lists]
else:
entry_name = []
entry_characteristics = []
將入口點的名稱和屬性使用FeatureHasher轉換成維度為50的向量:
FeatureHasher(50, input_type="string", dtype=self.dtype).transform( [entry_name]).toarray()
FeatureHasher(50, input_type="string", dtype=self.dtype).transform([entry_characteristics]).toarray()
2.3 檢測模型
惡意程式的檢測過程是個典型的二分類問題,工業界和學術屆經常使用的方法包括多層感知機(MLP)、卷積神經網路(CNN)、梯度提升決策樹(GBDT)和XGBoost。
相關推薦
機器學習方法檢測惡意檔案
1. 惡意檔案的傳統檢測方法 惡意檔案檢測在機器學習方法流行之前,一直是防毒引擎的黑箱技術,很少為外界所周知。對於一般粗淺的應用者而言,最簡單的做法是有兩種: 1. 尋找各種開源的病毒庫或者威脅情報網站,收集惡意檔案的MD5值,作為黑名單使用。 2
使用機器學習方法識別音訊檔案的音樂和演講
背景 最近下載了一批類似百家講壇的音訊檔案。這些檔案前面部分是演講類的音訊,主要講歷史的,後面一部分是音樂,每個檔案的音樂都不一樣。 所以希望把檔案切割,把音樂部分切走,只留下演講部分。 這裡一個技術難點就是怎麼識別哪些音訊是演講,哪些音訊是音樂。 通過KNN演算法,1s的音訊檔案的預測正確率是92%。 同時
文本情感分析的基礎在於自然語言處理、情感詞典、機器學習方法等內容。以下是我總結的一些資源。
建議 中心 這場 分詞 自然語言處理 目前 能力開放 計算 推薦算法 文本情感分析的基礎在於自然語言處理、情感詞典、機器學習方法等內容。以下是我總結的一些資源。 詞典資源:SentiWordNet《知網》中文版中文情感極性詞典 NTUSD情感詞匯本體下載 自然語言處理
R語言進行機器學習方法及實例
最近鄰 ridge glog 原始的 默認值 ria er模型 不能 預測概率 機器學習的研究領域是發明計算機算法,把數據轉變為智能行為。機器學習和數據挖掘的區別可能是機器學習側重於執行一個已知的任務,而數據發掘是在大數據中尋找有價值的東西。 機器學習一般
各種 機器學習方法 / 學習範式 匯總
原理 語音合成 可能 深入 系統 dual 成功 信息 www 各種機器學習方法(學習範式)匯總 強化學習 入門資料 《深入淺出強化學習原理入門》. 郭憲等編著. 電子工業出版社 An Introduction to Reinforcement Learning, Sutt
機器學習方法的本質是什麽?
傳輸 不可 content IV 給人 極值 事情 便是 靠譜 機器學習方法本質上是人類認知方式的新世界,是人類的未來。 工業革命解放了人類的體力,以機器學習技術逐步解鎖的人工智能革命將解放人類的腦力。 這不是技術層面上的進步,而是從根本上改
搭建了一個在線的機器學習webshell檢測RESTful API
如果 restful mongo 請求 日誌 結構 IV int 執行 # 地址: http://118.190.147.89:5000/ # 說明: 簡單的基於機器學習檢測webshell:目前只支持php的檢測#使用方法: 1.上傳檢測文件 接口地址: /put
不平衡數據下的機器學習方法簡介 imbalanced time series classification
表現 平衡 for www cat 加權 但是 依賴 線下 imbalanced time series classification http://www.vipzhuanli.com/pat/books/201510229367.5/2.html?page=2 這
OpenCV3 SVM ANN Adaboost KNN 隨機森林等機器學習方法對OCR分類
轉摘自http://www.cnblogs.com/denny402/p/5032839.html opencv3中的ml類與opencv2中發生了變化,下面列舉opencv3的機器學習類方法例項: 用途是opencv自帶的ocr樣本的分類功能,其中神經網路和adaboost訓練速度很慢,效
吳恩達機器學習 - 異常檢測 吳恩達機器學習 - 異常檢測
原 吳恩達機器學習 - 異常檢測 2018年06月25日 21:09:33 離殤灬孤狼 閱讀數:69
ML筆記 - 機器學習方法三要素
機器學習方法通常都是由模型、策略和演算法三部分構成:方法 = 模型 + 策略 + 演算法。 模型確定學習範圍,策略確定學習規則,演算法按規則在範圍內學習。 模型 輸入空間到輸出空間的對映關係,學習過程即為從假設空間搜尋適合當前資料的假設。 分析當前需要解決的問題,確定模型:
CS229 7.2 應用機器學習方法的技巧,準確率,召回率與 F值
建立模型 當使用機器學習的方法來解決問題時,比如垃圾郵件分類等,一般的步驟是這樣的: 1)從一個簡單的演算法入手這樣可以很快的實現這個演算法,並且可以在交叉驗證集上進行測試; 2)畫學習曲線以決定是否更多的資料,更多的特徵或者其他方式會有所幫助; 3)人工檢查那些演算法預測錯誤的例子(在交叉驗證集上)
基於機器學習演算法識別惡意url
參考連結: https://blog.csdn.net/solo_ws/article/details/77095341?utm_source=blogxgwz5 https://www.freebuf.com/articles/network/131279.html 下面的說法直接拷貝
自然語言處理系列-2-文字分類-傳統機器學習方法
文件分類是指給定文件p(可能含有標題t),將文件分類為n個類別中的一個或多個,本文以人機寫作為例子,針對有監督學習簡單介紹傳統機器學習方法。 文件分類的常見應用: 新聞分類: 也就是給新聞打標籤,一般標籤有幾千個,然後要選取k個標籤,多分類問題,可見2017知乎
sklearn如何選擇機器學習方法
從 START 開始,首先看資料的樣本是否 >50,小於則需要收集更多的資料。 由圖中,可以看到演算法有四類,分類,迴歸,聚類,降維。 其中 分類和迴歸是監督式學習,即每個資料對應一個 label。 聚類 是非監督式學習,即沒有 label
【機器學習】R語言進行機器學習方法及例項
R語言進行機器學習方法及例項 機器學習的研究領域是發明計算機演算法,把資料轉變為智慧行為。機器學習和資料探勘的區別可能是機器學習側重於執行一個已知的任務,而資料發掘是在大資料中尋找有價值的東西。 機器學習一般步驟 收集資料,將資料轉化為適合分析的電子資料 探索和準備資料,
為什麼某個問題可以用機器學習方法來解決?
不知道大家有沒有想過,基於歷史資料去預測未知資料的問題,為什麼我們就知道這種問題可以用機器學習來解決? 偶爾看到了《統計學習方法概論》裡的一個小節,小節的內容我認為可以解答這個問題。總而言之就是,這是一種假設,即假設他可以用機器學習方法來解決,同時假設學習模型是存在的。該小
機器學習方法中的一些基本概念
輸入空間、特徵空間和輸出空間 監督學習中,將輸入與輸出所有可能取值的集合稱為輸入空間與輸出空間。 輸入與輸出空間可以是有限集合,也可以是整個歐式空間;二者可以是同一個空間,也可以是不同的空間;通常情況下,輸出空間遠小於輸入空間。 每個具體輸入是一個例項,由特徵向量來表示,所有特徵向量存在
Stanford機器學習-異常檢測和多元高斯分佈
一、異常檢測 這章主要學習異常檢測問題,它是機器演算法的一個常見應用,同時也對於我們生活中的很多問題有很大的幫助,總的來說,它主要用於非監督的學習問題。 那我們怎麼來理解異常檢測是一個怎麼樣的問題呢?我們來看一個相關的問題:飛機引擎的檢測。因為引擎對於飛機來說
機器學習方法(四):決策樹Decision Tree原理與實現技巧
歡迎轉載,轉載請註明:本文出自Bin的專欄blog.csdn.net/xbinworld。 技術交流QQ群:433250724,歡迎對演算法、技術、應用感興趣的同學加入。 前面三篇寫了線性迴歸,lasso,和LARS的一些內容,這篇寫一下決策樹這個經典的分