基於python深度學習的apk風險預測腳本
為了有效判斷安卓apk有無惡意操作,利用python腳本,通過解包apk文件,對其中xml文件進行特征提取,通過機器學習構建模型,預測位置的apk包是否有風險。
一、APK拆包
一般的方法有兩種
- 由google開發的apktool。
- python的androguard包。
網上關於apktool的教程比較多,但是筆者在嘗試使用后發現,
-
apktool是基於java開發的,而機器學習由python控制,雖然可以利用python控制apktool,但有點多此一舉。
-
apktool對apk進行完全解包,浪費太多時間,在我准備構建的模型中有很多內容並不會使用。
固使用快速又強大的androguard。
from androguard.core.bytecodes import apk
import re
def get_permissions_one(filename):
app = apk.APK(filename)
permission = app.get_permissions()
with open(re.sub(r'.apk', '', filename) + '.txt', 'w', encoding='UTF-8')as f:
for temp in permission:
f.write(temp + '\n')
通過app.get_permissions()提取所有權限,利用正則寫入txt文件。
關於androguard的更多命令可以看這篇博客,也可以看官方的API說明文檔,本腳本只需要get_permissions()函數。、
先使用任意apk進行測試,執行結果如下:
得到了寫入權限的txt文件。
網上有挺多惡意、正常apk例子,筆者是在網站下載的。
二、標准權限獲取
之前提到實現類似功能的博客中,采用了動態標准。在解包apk文件的時候,每次遇到了新的權限,就將權限寫入標准權限的列表。而筆者在嘗試了幾個常見apk(qq、微信等)后發現,由於安卓有各類延申的os,而不同軟件又有各自生態,有各種各樣權限。筆者認為太多的權限會導致最后的模型不准確,固選擇直接從網上找了個安卓權限大全,進行正則提取。大全網址
import re
with open("帶安卓權限.txt", "r", encoding='utf-8') as f: # 打開文件
data = f.read() # 讀取文件
temp = re.findall(r'android.permission.(.+?),', data)
print(len(temp))
with open('帶安卓權限簡述.txt', 'w')as f1:
i = 0
while i < len(temp):
f1.write('android.permission.' + temp[i])
f1.write('\n')
i = i + 1
有三條不滿足標准,手動補上
com.android.browser.permission.READ_HISTORY_BOOKMARKS
com.android.browser.permission.WRITE_HISTORY_BOOKMARKS
com.android.alarm.permission.SET_ALARM
於是得到了120條標准權限。
三、對照並得出抽象值
筆者對數據的抽象是這樣設計的:
由於權限一共有120條,在解包萬任一文件后,創建一個120*[0]的數組,將提取后txt中每條權限與標准權限對比,當匹配到相同的權限時,令全[0]的數組中對應元素為[1],這樣就完成了數據抽象化。
關鍵代碼:
def power_compare(filename):
standard = get_ready()
list = list_dir_read_txt(filename)
apk = []
for txt in list:
with open(txt, 'r')as f:
temp = [0] * 120
for line in f.readlines():
line = line.strip('\n') # 去掉列表中每一個元素的換行符
for i, power in enumerate(standard):
if line == power:
temp[i] = 1
apk.append(temp)
return apk
四、對抽象值進行處理
雖然用列表進行搜索,一個一個匹配挺蠢的,但是這么做確實是最簡單的,直接貼代碼吧。
def power_compare(filename):
standard = get_ready()
list = list_dir_read_txt(filename)
apk = []
for txt in list:
with open(txt, 'r')as f:
temp = [0] * 120
for line in f.readlines():
line = line.strip('\n') # 去掉列表中每一個元素的換行符
for i, power in enumerate(standard):
if line == power:
temp[i] = 1
apk.append(temp)
return apk
五、通過算法得到模型
使用sklearn,簡單暴力。
第一次只用了朴素貝葉斯,其他的算法也就改個名稱換個參數,差不多(大概吧)
sklearn只認numpy里的數組,強轉一下,扔進去就完事了,筆者第一次學習,也沒分訓練組和測試組,只體驗了一下流程。
from data_get import *
import numpy as np
from sklearn.naive_bayes import GaussianNB
safe, dangerous = data_get()
clf = GaussianNB()
train = np.asarray(safe + dangerous)
target = np.asarray(len(safe)*[0] + len(dangerous)*[1])
clf.fit(train, target)
六、完整代碼
之前省略了挺多正則處理還有讀寫文件,全扔這里了,希望對你有幫助。
data_get.py
# -*— codeing = utf-8 -*-
from androguard.core.bytecodes import apk
import re
import os
def get_permissions_one(filename):
app = apk.APK(filename)
permission = app.get_permissions()
with open(re.sub(r'.apk', '', filename) + '.txt', 'w', encoding='UTF-8')as f:
for temp in permission:
f.write(temp + '\n')
# 對單個文件拆包出權限,並寫入txt文件
def get_safe_permissions():
print('開始讀取安全文件')
list = list_dir_read_apk('安全文件')
for file in list:
get_permissions_one(file)
print('讀取完畢!')
# 讀取安全文件並記錄其權限
def get_dangerous_permissions():
print('開始讀取危險文件')
list = list_dir_read_apk('危險文件')
for file in list:
get_permissions_one(file)
print('讀取完畢!')
# 讀取危險文件並記錄其權限
def list_dir_read_apk(file_dir):
dir_list = os.listdir(file_dir)
file = []
for cur_file in dir_list:
path = os.path.join(file_dir, cur_file)
if os.path.isfile(path):
if re.findall(r'.apk', path):
file.append(path)
if os.path.isdir(path):
# 遞歸讀取所有照片夾子目錄內容
list_dir_read_apk(path)
return file
# 讀取目標文件夾內所有apk文件,並記錄每一個的地址
def list_dir_read_txt(file_dir):
dir_list = os.listdir(file_dir)
file = []
for cur_file in dir_list:
path = os.path.join(file_dir, cur_file)
if os.path.isfile(path):
if re.findall(r'.txt', path):
file.append(path)
if os.path.isdir(path):
# 遞歸讀取所有照片夾子目錄內容
list_dir_read_apk(path)
return file
# 讀取目標文件夾內所有txt文件,並記錄每一個的地址
def get_ready():
power = []
with open('帶安卓權限簡述.txt', 'r')as f:
for line in f.readlines():
line = line.strip('\n') # 去掉列表中每一個元素的換行符
power.append(line)
return power
# 讀入所有權限文件,寫入集合文件,方便搜索
def power_compare(filename):
standard = get_ready()
list = list_dir_read_txt(filename)
apk = []
for txt in list:
with open(txt, 'r')as f:
temp = [0] * 120
for line in f.readlines():
line = line.strip('\n') # 去掉列表中每一個元素的換行符
for i, power in enumerate(standard):
if line == power:
temp[i] = 1
apk.append(temp)
return apk
# 比較權限,並寫入數組
def data_get():
apk_safe = power_compare('安全文件')
apk_dangerous = power_compare('危險文件')
return apk_safe, apk_dangerous
# 獲得數據
data_set.py
# -*— codeing = utf-8 -*-
from data_get import *
import numpy as np
from sklearn.naive_bayes import GaussianNB
safe, dangerous = data_get()
clf = GaussianNB()
train = np.asarray(safe + dangerous)
target = np.asarray(len(safe)*[0] + len(dangerous)*[1])
clf.fit(train, target)
七、參考文獻
文獻 | 鏈接 |
---|---|
類似項目 | https://www.jianshu.com/p/670023af50f6 |
androguard官方文檔 | https://docs.koodous.com/yara/androguard/ |
apk例子 | https://www.unb.ca/cic/datasets/invesandmal2019.html |
一個牛逼的完整的項目,以后有機會復現 | https://aistudio.baidu.com/aistudio/projectdetail/1562926?shared=1 |
一開始想自制數據集,后來發現沒那么麻煩 | https://zhuanlan.zhihu.com/p/354146564 |
sklearn官方文檔,沒看懂 | https://sklearn.apachecn.org/docs/master/37.html |
類似項目,寫的很好,沒看懂 | https://www.jianshu.com/p/0bf2eb488afa |