基于機器學習的 Android 惡意 App 識別
問題描述
Android 市場的開放性導致了惡意軟件(Malware)的盛行。據 360 安全中心報告,每天都能截獲數萬個 Android 惡意軟件,使得 Android Malware Detection 成為研究人員熱議的話題。傳統的 Android 惡意軟件檢測方法主要依賴于基于規則或簽名的檢測機制,其中使用 yara 實現相對簡單。但這種基于簽名的檢測方法是信息密集型的,需要持續收集新的簽名,而基于規則的實現則極為復雜,極易導致誤報或讓狡猾的惡意軟件逃過檢測。
隨著機器學習的流行,越來越多的研究人員開始嘗試利用機器學習來實現惡意軟件的檢測。核心思路是從 Android 的 APK 文件中提取信息,用于訓練模型,隨后預測其他 APK 文件是否為惡意軟件。根據信息提取方法的不同,主要分為兩類:一類是通過靜態分析,從 APK 中提取 permissions、intents、receivers 等組件,以及通過反編譯提取代碼調用,利用這些信息進行模型訓練;另一類是通過實際安裝運行 APK,攔截網絡請求和監聽系統 API 調用來獲取數據,作為模型訓練的基礎。
在探討此問題時,由于“Incinerator”項目的動態檢測功能尚未完全實現,我們暫時缺乏研究動態分析的條件,因此選擇采用靜態分析方法進行研究。
當前主流方案
基于靜態分析的機器學習訓練方案主要包括以下幾類:
- 權限提取訓練:
- 從 AndroidManifest.xml 中提取 permissions 信息進行模型訓練。
- 綜合信息提取訓練:
從 AndroidManifest.xml 中提取 permissions、intents、receivers 等信息,并通過反編譯從 APK 中基于規則抽取 Android 系統 API 調用等信息進行模型訓練。
- 整體 APK 訓練:
將整個 APK 文件作為機器學習訓練的輸入,包括將 APK 文件的二進制字節流作為輸入,或通過反編譯抽取 opcode 作為訓練輸入。
據文獻報道,這些方案可實現 90% 以上的準確率。尤其是方案 3,準確率在 92%-93% 之間,而方案 1 和 2 在多數研究中可達到 95% 以上的準確率。
我們試圖重現文獻中的方案,首先著手基于 permissions 的方案進行驗證。
數據源:
惡意軟件集合:
a. 來自威脅情報公司 abuse.ch 的 Malware APK 集合 2000 個(簡稱 MB)
b. VirusShare 2020/2021/2022 的 Malware 集合(簡稱 VS2020/VS2021/VS2022)
良性軟件集合:
a. 從應用寶下載的 APK 10000 個
b. 從 APKPURE 下載的 APK 10000 個
訓練方法
通過靜態分析從 APK 的 AndroidManifest.xml 中抽取 AOSP (Android Open Source Project) permissions,并通過 One-hot Encoding 的方式輸入模型進行訓練。模型選擇采用傳統的機器學習二分類模型如隨機森林、SVM 等進行訓練。經測試,隨機森林的效果最佳,準確率可達 98%。
我們選擇應用寶的 APK 作為良性樣本,VS2022 作為惡意軟件樣本,進行訓練。訓練數據如下:
模型 | Precision | Recall | FPR |
隨機森林 | 0.983 | 0.983 | 0.056 |
SVM | 0.981 | 0.977 | 0.063 |
然后我們對其他數據集進行測試驗證:
數據集 | Precision | Recall | FPR |
APKPure | 0.0 | NAN | 0.59 |
MB | 1.0 | 0.95 | NAN |
VS2020 | 1.0 | 0.96 | NAN |
VS2021 | 1.0 | 0.94 | NAN |
在進行 APKPure 數據集的驗證時,發現模型的假陽性率異常高,超過了 50%,這表明模型在不同數據集的交叉驗證上表現不佳。同時,在 MB、VS2020、VS2021 數據集上得到的高準確率由于高假陽性率而變得無意義。
為了深入理解模型的預測表現,我們選擇使用 LinearSVM(線性支持向量機)來解釋模型的預測結果,并嘗試探討可能出現的問題:
在訓練過程中,共有 265 個權限被用于訓練模型。我們重點分析了對于 Malware 預測結果影響最大的 30 個權限:
0 1.9507425950717683 android.permission.READ_SMS
1 1.6805547441380115 android.permission.SEND_SMS
2 1.5291784053142392 android.permission.RECEIVE_SMS
3 1.281383891333467 android.permission.WRITE_SMS
4 1.1385944832617678 android.permission.GET_DETAILED_TASKS
5 1.0870145778775504 android.permission.MANAGE_USERS
6 0.9822953162458009 android.permission.SET_TIME_ZONE
7 0.9815855293627985 android.permission.REQUEST_DELETE_PACKAGES
8 0.8705538278525148 android.permission.ACCOUNT_MANAGER
9 0.7701851337780519 android.permission.ACCESS_CACHE_FILESYSTEM
10 0.7493889020376178 android.permission.PERSISTENT_ACTIVITY
11 0.742267985802697 android.permission.SET_PREFERRED_APPLICATIONS
12 0.6575763216374741 android.permission.USE_SIP
13 0.6423455602781643 android.permission.MODIFY_PHONE_STATE
14 0.5733719308777389 android.permission.READ_CALL_LOG
15 0.5713221448442122 android.permission.WRITE_SECURE_SETTINGS
16 0.5177117115666185 android.permission.CLEAR_APP_CACHE
17 0.5013751180995185 android.permission.WRITE_SYNC_SETTINGS
18 0.47540432455574055 android.permission.INJECT_EVENTS
19 0.450576746748121 android.permission.BIND_ACCESSIBILITY_SERVICE
20 0.4497437629117625 android.permission.READ_SYNC_STATS
21 0.40721040702182304 com.android.alarm.permission.SET_ALARM
22 0.3958974436391258 android.permission.GET_PACKAGE_SIZE
23 0.35828369132005317 android.permission.TRANSMIT_IR
24 0.3538089622374305 android.permission.CHANGE_COMPONENT_ENABLED_STATE
25 0.3303834311984685 android.permission.STATUS_BAR
26 0.3277728921018696 android.permission.WRITE_USER_DICTIONARY
27 0.31322691738916597 android.permission.SET_DEBUG_APP
28 0.28600828593282673 android.permission.INSTALL_PACKAGES
29 0.27804088205285526 android.permission.SHUTDOWN
導致 Benign 結果最重要的 30 個權限:
1 -1.0280830288092226 android.permission.FORCE_STOP_PACKAGES
2 -1.0244749163270055 android.permission.DELETE_CACHE_FILES
3 -0.9235183435775582 android.permission.READ_PRIVILEGED_PHONE_STATE
4 -0.7975588094210508 android.permission.USE_BIOMETRIC
5 -0.7691538868495551 android.permission.READ_CELL_BROADCASTS
6 -0.7288571523071693 android.permission.REQUEST_INSTALL_PACKAGES
7 -0.7278186994140812 android.permission.WRITE_CALL_LOG
8 -0.7029898754031535 android.permission.READ_SEARCH_INDEXABLES
9 -0.6832562629713737 android.permission.ACCESS_NOTIFICATION_POLICY
10 -0.6442707037030093 android.permission.BIND_NOTIFICATION_LISTENER_SERVICE
11 -0.6229441323892875 android.permission.CAPTURE_AUDIO_OUTPUT
12 -0.5951302503005503 android.permission.REORDER_TASKS
13 -0.552113274404841 android.permission.FACTORY_TEST
14 -0.5512329811397917 android.permission.CAMERA
15 -0.5415431826751977 android.permission.PACKAGE_USAGE_STATS
16 -0.5373788445105623 android.permission.READ_SYNC_SETTINGS
17 -0.5300427083556158 android.permission.ACCESS_WIFI_STATE
18 -0.48952375397337794 android.permission.READ_PHONE_NUMBERS
19 -0.4822239255635727 android.permission.STOP_APP_SWITCHES
20 -0.4525220364959383 android.permission.WRITE_MEDIA_STORAGE
21 -0.4133049145725493 com.android.browser.permission.WRITE_HISTORY_BOOKMARKS
22 -0.3902532535519829 android.permission.CAPTURE_VIDEO_OUTPUT
23 -0.34681147328619505 android.permission.READ_FRAME_BUFFER
24 -0.34134222449779317 android.permission.WRITE_GSERVICES
25 -0.3335042039412585 android.permission.BIND_APPWIDGET
26 -0.3263774109427998 android.permission.AUTHENTICATE_ACCOUNTS
27 -0.3136298914538836 android.permission.NFC
28 -0.3000955825422318 android.permission.READ_EXTERNAL_STORAGE
29 -0.2846046321402758 android.permission.CALL_PRIVILEGED
30 -0.28338090002182315 android.permission.READ_CALENDAR
在表格中,第二列顯示了通過 SVM 計算得到的權重值。由于在標簽設定中,Malware 被標記為 1,而 Benign 被標記為 0,且訓練數據的格式是 0,1,1,0,...0,1,1,0,...這樣的布爾值,因此,當權重為正時,該權重在計算 Malware 的預測結果時具有較高的重要性;權重值越大,其重要性越高。相反,當權重為負時,該權重在計算 Benign 的預測結果時具有較高的重要性;權重值越小,其重要性越高。
通過分析這些權限及其功能,我們發現 Malware 相關的權限通常比 Benign 相關的權限具有更高的危害性。在一定程度上,這種模型的設計是合理的。例如,模型成功識別了與 SMS 相關的權限主要與 Malware 相關,并賦予了較高的權重,這意味著,基本上,一個 APP 如果包含 SMS 權限,就非常可疑。實際上,普通的 APP 不應該請求此類權限,因為短信管理通常是系統 APP 的職責。
然而,這里存在一個問題:權限的存在是因為 Android 系統認為某些行為可能不妥,需要用戶確認。所以,理論上,所有需要請求的權限都有可能對用戶造成損害。因此,沒有請求權限應該被視為一個加分項。但在二分類機器學習的情境下,模型會做出區分,因為 Benign 類別的存在意味著一定會有一部分權限被視為支持 Benign 的證據。
現在我們來分析為什么會出現如此高的假陽性率: 我們使用 LinearSVC 來解釋模型的預測結果,并對一些具有假陽性的權限信息進行分析:
0.1773649887447295 android.permission.WAKE_LOCK
0.01285824377030036 android.permission.INTERNET
-0.1357928094523775 android.permission.ACCESS_NETWORK_STATE
0.43102404170044467 com.android.alarm.permission.SET_ALARM
0.1773649887447295 android.permission.WAKE_LOCK
0.14741402851800423 android.permission.SYSTEM_ALERT_WINDOW
0.02740438240042149 android.permission.FOREGROUND_SERVICE
0.01285824377030036 android.permission.INTERNET
-0.1357928094523775 android.permission.ACCESS_NETWORK_STATE
-0.15043626374678254 android.permission.WRITE_EXTERNAL_STORAGE
-0.1975995718519041 android.permission.CHANGE_WIFI_STATE
-0.20461138790573433 android.permission.VIBRATE
-0.511067438637911 android.permission.ACCESS_WIFI_STATE
0.1773649887447295 android.permission.WAKE_LOCK
0.02740438240042149 android.permission.FOREGROUND_SERVICE
0.01285824377030036 android.permission.INTERNET
-0.1357928094523775 android.permission.ACCESS_NETWORK_STATE
-0.33867385510052594 android.permission.READ_EXTERNAL_STORAGE
-0.511067438637911 android.permission.ACCESS_WIFI_STATE
而真陽的權限信息:
0.32757400447767016 android.permission.INSTALL_PACKAGES
0.2870058866311678 android.permission.READ_PHONE_STATE
0.1773649887447295 android.permission.WAKE_LOCK
0.1545767541451571 android.permission.FLASHLIGHT
0.14613075920332474 android.permission.BLUETOOTH_ADMIN
0.140268653568319 android.permission.GET_ACCOUNTS
0.08641386050999389 android.permission.MOUNT_UNMOUNT_FILESYSTEMS
0.06460516872049353 android.permission.ACCESS_COARSE_LOCATION
0.01285824377030036 android.permission.INTERNET
-0.009804892771664459 android.permission.ACCESS_FINE_LOCATION
-0.12321341834571817 android.permission.READ_LOGS
-0.1357928094523775 android.permission.ACCESS_NETWORK_STATE
-0.15043626374678254 android.permission.WRITE_EXTERNAL_STORAGE
-0.15994619600450963 android.permission.CHANGE_NETWORK_STATE
-0.16005902734200772 android.permission.WRITE_SETTINGS
-0.1975995718519041 android.permission.CHANGE_WIFI_STATE
-0.20461138790573433 android.permission.VIBRATE
-0.23536025455979454 android.permission.CALL_PHONE
-0.24802834827531783 android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
-0.30018060973660377 android.permission.BLUETOOTH
-0.33867385510052594 android.permission.READ_EXTERNAL_STORAGE
-0.511067438637911 android.permission.ACCESS_WIFI_STATE
-0.5625902678304402 android.permission.CAMERA
-0.7242676191415552 android.permission.REQUEST_INSTALL_PACKAGES
通過分析,我們發現了一個模式:擁有較少權限的 APK 往往會被誤判,而權限較多的 APK 基本能得到正確的預測。深入探究后,我們理解到這種現象的出現主要是由于 APKPure 樣本中大多數 APK 的權限數量較少,而我們的訓練模型主要基于權限較多的應用寶 APK 樣本。因此,預測誤差的產生在一定程度上是由樣本差異導致的。
為了解決這個問題,一個直接的方法是將 APKPure 的數據也納入訓練過程,以增強模型的泛化能力和預測準確性。
我們采取了以下措施:從 APKPure 樣本中隨機抽取一半,即 5000 個 APK,同時從應用寶樣本中隨機抽取一半,約 5000 個 APK,一同用于模型的訓練。然后,我們使用這個新訓練得到的模型來預測未參與訓練的樣本。結果顯示,新模型的預測準確率得到了顯著提高。
模型 | Precision | Recall | FPR |
隨機森林 | 0.994 | 0.967 | 0.008 |
SVM | 0.994 | 0.967 | 0.008 |
然后我們對其他數據集進行測試驗證:
數據集 | Precision | Recall | FPR |
APKPure 未參與訓練的樣本 | 0.0 | NAN | 0.018 |
MB | 1.0 | 0.878 | NAN |
VS2020 | 1.0 | 0.92 | NAN |
VS2021 | 1.0 | 0.89 | NAN |
假陽性率已降至可接受的水平。這個實驗揭示了一個重要的現象:在訓練集上獲得理想的結果相對容易,但在現實世界中準確預測卻可能面臨挑戰。無人能保證所收集的樣本完美地反映了現實世界的情況,而我們的目標是識別那些真正與惡意軟件(Malware)相關的特征。因此,我們決定嘗試探索其他可能的解決方案。
1. 基于 Intents 和 Receivers 的訓練
隨后,我們擴展了特征集,加入了從 AndroidManifest.xml 中提取的 intents 和 receivers 信息進行訓練,然而,這并沒有提高模型的準確率。
2. 基于系統 API 調用的訓練
我們進一步嘗試提取 APK 中的所有系統 API 調用,將其轉換為適合卷積神經網絡(CNN)的格式,并通過 CNN 來訓練模型。在訓練集上,模型達到了令人滿意的 97% 的準確率,但在數據集交叉驗證時,表現仍然不盡如人意。
在這過程中,我們遇到了幾個問題:、
- API 調用頻率的不明顯差異: 最初,我們通過反編譯提取了所有出現過的 API 調用,卻發現這些 API 的調用頻率并沒有明顯差異。例如,我們原本認為 accessibilityservice 的調用明顯與惡意軟件相關,卻發現在良性軟件中也頻繁出現。后來我們了解到,這主要是因為大多數 APK 都依賴于 android 這個庫,而該庫中包含了大量的系統 API 調用。由于 Malware 和 Benign APK 都依賴于大量的第三方庫,這些庫中存在大量的系統 API 調用,使得我們難以從系統 API 調用的統計結果中區分 Malware 和 Benign。即便我們使用了 incinerator 的 SCA 分析功能來檢測和剔除這些第三方庫,結果仍然不盡如人意。
- 第三方庫的干擾: 我們發現,很少有研究考慮到第三方庫的干擾,并提出剔除第三方庫的具體方案。如果不剔除這些庫,基于靜態分析的方法幾乎毫無意義,因為靜態抽取會抽取出大量未被調用的 API,而這在 Malware 和 Benign APK 中沒有明顯區別。
- 反編譯和脫殼問題: 由于這種方法涉及從 APK 中抽取系統 API 調用,需要進行反編譯。然而,許多 Malware 都加殼處理,而脫殼是一個復雜的對抗技術。我們查閱的資料中,很少提到這一點。脫殼對于非專業團隊來說可能太過困難,但至少應該從數據集中篩選出沒有殼的 APK。如果不進行脫殼,直接抽取的話,只能得到極少數的 dexloader 等系統 API 調用,這大大影響了訓練效果。
3. 回歸基于 Permissions 的模型
鑒于前述的嘗試未能取得預期效果,我們重新回到基于 Permissions 的模型,尋求通過其他方法提升交叉驗證的準確率。我們進行了以下嘗試:
- 通過 Select 模型選擇 Permissions 采用此法的目的是尋找 Malware 實際所利用的 Permissions。然而,實際測試結果顯示,訓練準確率下降,驗證準確率也下降,且交叉驗證的準確率更是降低。
- 我們的實驗過程如下: 使用 SelectFromModel 方法,基于 RandomForestClassifier 模型(該模型包含所有參與訓練的數據)進行參數抽取。我們分別抽取了 100、50、30 個 Permissions 進行實驗,并得到了如下數據:
- 選取 100 個 Permissions訓練數據:
模型 | Precision | Recall | FPR |
隨機森林 | 0.989 | 0.974 | 0.013 |
數據集 | Precision | Recall | FPR |
APKPure | 0.0 | NAN | 0.64 |
MB | 1.0 | 0.95 | NAN |
VS2020 | 1.0 | 0.96 | NAN |
VS2021 | 1.0 | 0.94 | NAN |
- 選取 50 個 Permissions訓練數據
模型 | Precision | Recall | FPR |
隨機森林 | 0.981 | 0.986 | 0.063 |
數據集 | Precision | Recall | FPR |
APKPure | 0.0 | NAN | 0.59 |
MB | 1.0 | 0.94 | NAN |
VS2020 | 1.0 | 0.96 | NAN |
VS2021 | 1.0 | 0.94 | NAN |
- 訓練 30 個 Permissions訓練數據
模型 | Precision | Recall | FPR |
隨機森林 | 0.983 | 0.983 | 0.054 |
數據集 | Precision | Recall | FPR |
APKPure | 0.0 | NAN | 0.59 |
MB | 1.0 | 0.96 | NAN |
VS2020 | 1.0 | 0.96 | NAN |
VS2021 | 1.0 | 0.95 | NAN |
分析及新的嘗試
從前述數據中可見,減少 Permissions 的數量并未能改善假陽性率或提高準確率。
- 利用自編碼器(Auto Encoder)進行降維
- 為了進一步嘗試改善模型表現,我們轉向了自編碼器(Auto Encoder)技術,期望通過對 Permissions 的分組和降維來提高準確率。自編碼器是一種能夠學習數據編碼的神經網絡,通常被用于降維或特征學習。我們的想法是通過自編碼器將 Permissions 的高維數據轉換為低維數據,同時保留與 Malware 識別相關的重要信息。
- 然而,盡管我們嘗試了自編碼器的降維方法,交叉驗證的結果仍然不盡如人意,假陽性率依然較高。
模型 | Precision | Recall | FPR |
隨機森林 | 0.977 | 0.980 | 0.074 |
數據集 | Precision | Recall | FPR |
APKPure | 0.0 | NAN | 0.64 |
MB | 1.0 | 0.95 | NAN |
VS2020 | 1.0 | 0.95 | NAN |
VS2021 | 1.0 | 0.92 | NAN |
通過業務邏輯選擇 Permissions
隨后,我們嘗試通過業務規則來挑選適當的 Permissions。我們的方法是這樣的:
- 我們統計了所有 Malware 中每個 Permission 的出現頻率 mp 和所有 Benign 中每個 Permission 的出現頻率 bp。
- 然后計算了 bp/mp
然而,這種方法也未能提高訓練準確率和驗證準確率。例如,android.permission.INTERNET 這樣的權限在 Malware 和 Benign 中出現的概率非常接近,大約都在 97% 左右,這樣的權限參與訓練并沒有太大的意義。類似地,android.permission.WAKE_LOCK 在 Malware 和 Benign 中出現的概率也非常接近,大約在 80% 左右。
我們還嘗試了其他研究論文中提到的一些方法。經過測試,我們發現無論采取何種方法來篩選 Permissions,篩選后的訓練準確率都不如不篩選、直接使用所有 Permissions 進行訓練的準確率高。這個發現與許多將 Permissions 篩選作為主要研究目的的論文的結論相左。
結論
經過多次嘗試,我們暫時未能訓練出一個在單一數據集上訓練,而在其他數據集上也具有理想準確率的模型。因此,我們決定將應用寶和 APKPure 的數據合并作為 Benign APK 的訓練集,同時將其他幾個 Malware 數據集也合并作為 Malware APK 的訓練集,以提高樣本的平均均衡度。
當然,我們也發現了一些可能的優化方向:
- 我們注意到 Malware 和 Benign 的 APK 簽名存在一定的模式,如果能夠驗證這些模式,可以將其納入現有模型中。
- 在手動分析樣本時,我們發現許多 Malware APK 樣本在靜態分析階段無法判斷為惡意,因為它們的權限沒有任何可疑信息。例如,許多 dropper、downloader 等類型的惡意 APK,在權限上與 Benign APK 沒有明顯區別。因此,人工篩選惡意 APK 可能有助于提高訓練準確率。
- 同時,將動態檢測的信息納入訓練模型也是一個值得嘗試的方向。我們計劃在后續的研究中加入動態信息以提升模型的表現。
原文鏈接:https://www.liansecurity.com/#/main/news/TfrG0IoBQKl-d7iA6Wuh/detail