基於python深度學習的apk風險預測腳本
基於python深度學習的apk風險預測腳本
為了有效判斷Androidapk有無惡意操作,利用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、微信等)後發現,由於Android有各類延申的os,而不同軟體又有各自生態,有各種各樣許可權。筆者認為太多的許可權會導致最後的模型不準確,固選擇直接從網上找了個Android許可權大全,進行正則提取。大全網址
import re
with open("帶Android許可權.txt", "r", encoding='utf-8') as f: # 打開文件
data = f.read() # 讀取文件
temp = re.findall(r'android.permission.(.+?),', data)
print(len(temp))
with open('帶Android許可權簡述.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('帶Android許可權簡述.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)
七、參考文獻
| 文獻 | 鏈接 |
|---|---|
| 類似項目 | //www.jianshu.com/p/670023af50f6 |
| androguard官方文檔 | //docs.koodous.com/yara/androguard/ |
| apk例子 | //www.unb.ca/cic/datasets/invesandmal2019.html |
| 一個牛逼的完整的項目,以後有機會復現 | //aistudio.baidu.com/aistudio/projectdetail/1562926?shared=1 |
| 一開始想自製數據集,後來發現沒那麼麻煩 | //zhuanlan.zhihu.com/p/354146564 |
| sklearn官方文檔,沒看懂 | //sklearn.apachecn.org/docs/master/37.html |
| 類似項目,寫的很好,沒看懂 | //www.jianshu.com/p/0bf2eb488afa |


