Python之利用機器學習檢測安卓惡意軟件實現(二)

前言

繼續昨天的話題,使用Python實現機器學習算法對安卓APP進行檢測。準備工作已經差不多了,那么這篇文章就來詳細記錄如何將機器學習算法應用到安卓惡意軟件檢測上以及如何實現常見機器學習算法。

準備工作

  • Anaconda:Anaconda下載
  • Anaconda是一款Python科學計算的環境包,包含了眾多的科學計算庫和原生Python環境。這里我使用的是Python2的64位的Windows版。將安裝包下載后,僅需要進行安裝即可。相應的包和庫都會自動集成,很方便。
  • 利用上一篇文章對惡意軟件和正常軟件進行處理后生成的包含權限信息的txt文件各500條。
  • 這里正常軟件樣本采用之前文章中介紹的爬蟲下載即可,惡意軟件為了安全起見不提供下載方式,但在文章最后提供處理過后的txt實驗數據。需要注意的是正常的樣本收集過后要經過幾次查殺篩選,排除潛藏在正常軟件中的惡意軟件。
下載Anaconda.png
  • 驗證環境:首先確保將安裝后的Anaconda中的python加入到環境變量中。接著cmd下調用Python并執行import numpy,如下圖沒有報錯即可:
驗證環境.png

基本思路

  • 首先我們這次試用樸素貝葉斯作為分類核心算法。
  • 采取先訓練分類器,再使用分類器對位置樣本進行分類。

樸素貝葉斯

樸素貝葉斯是機器學習中最常見不過的一種算法,它簡單實用且在數據量較少的情況下依然有著出色的表現。這里不再贅訴樸素貝葉斯的原理,提供幾個鏈接供參考。

實現算法

話不多說,接下來開始用Python實現樸素貝葉斯算法。

  • 我們使用權限(permission)作為特征,所以首先構建一個包含所有權限項的無重復列表。如:【權限1,權限2,……,權限n】
  • 這里我是用了一個簡單直接的方法,讀遍所有的txt文件中的每個項,只要有之前不存在的項就追加到list中。其實可以去安卓官網查看安卓開發者可以申請到的全部權限,直接構建出list。
構建list.png
  • 接著需要將每個txt文件處理成向量的形式。舉個例子,如果樣本1對應的權限項為【權限1,權限3,權限5,權限7】,則他的對應向量就是【1,0,1,0,1,0,1,0,0,0】——》假設全部權限的list長度為10項。
處理每條txt.png
  • 接著就是訓練函數,其基本思想總結為如下偽代碼:
    計算每個類別中文檔數目
對于每個txt文檔:
    對于每個類別:
        如果權限項出現在文檔中則增加該詞條計數值
        增加所有權限項計數值
    對于每個類別:
        將該權限項數目除以總數得到條件概率
返回條件概率```
舉個例子,首先初始化一個全為0的list,長度等于所有不重復權限項的數量和(假設為5)。【0,0,0,0,0】,接著針對正常的樣本,逐條輸入。假設第一條樣本為【1,1,0,0,1,】,第二條樣本為【1,1,1,1,1】,第三條為【0,0,0,0,0】則經過兩次輸入,我們的list變成【2,2,1,1,2】,除以總數3得到P=【0.67 ,0.67 ,0.33 ,0.33 ,0.67】。那么根據樸素貝葉斯算法,認為每個權限項都是獨立的,則假設待測樣本為【1,0,0,1,0】,那么他屬于正常樣本的概率為P=1*0.67*1*0.33=0.2211
* 上面的例子針對正常樣本和惡意樣本都要做。分類算法較簡單,只需要計算出P正常和P惡意,然后比較哪個概率大。我們就將待測樣本分類到概率大的一類中。
* 測試指標:我們使用檢測率,就是分類正確的概率。在500條正常樣本和500條惡意樣本中,隨機選出400個正常樣本和400個惡意樣本作為訓練集,訓練出分類器。然后用剩下的200個樣本作為未知待測樣本,對其進行檢測。輸出分類錯誤的情況以及準確率。

#實現中注意事項
1. 由于要計算多個概率的乘積以獲得待測樣本屬于某個類別的概率,一旦其中一個概率為0,則最后的結果必然為0.為了降低這種影響,可以將所有權限項出現的次數初始化為1,分母初始化為2.
2. 計算很多比較小的數相乘,很容易造成下溢出,影響檢測的結果。所以我們利用對乘積取熙然對數的方式:ln(a * b) = ln(a) + ln(b),這樣不會有任何損失。

# 執行結果截圖
* 這里執行10次取平均值,可以看到效果還是很不錯的,大概準確率有9成。并且誤報當中大部分是把好的APP判斷成了惡意的。

![檢測結果.png](http://upload-images.jianshu.io/upload_images/1863312-8efb3d95f311025b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

#完整代碼
```code
__author__ = 'Captainxero'
from numpy import *
import numpy as np

global p1
global p0
global numBad2Good
global numGood2Bad
global rateBad2Good
global rateGood2Bad
global Accuracy_Rate
Accuracy_Rate = 0
numBad2Good = 0
numGood2Bad = 0


def createVocabList(dataSet):
    vocabSet = set([])  #create empty set
    for document in dataSet:
        vocabSet = vocabSet | set(document) #union of the two sets
    return list(vocabSet)

def setOfWords2Vec(vocabList, inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        else: print "the word: %s is not in my Vocabulary!" % word
    return returnVec

def trainNB0(trainMatrix,trainCategory):
    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    p0Num = ones(numWords); p1Num = ones(numWords)      #change to ones()
    p0Denom = 2.0; p1Denom = 2.0                        #change to 2.0
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = np.log(p1Num/p1Denom)         #change to log()
    p0Vect = np.log(p0Num/p0Denom)          #change to log()
    return p0Vect, p1Vect, pAbusive

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    global p1
    global p0
    p1 = sum(vec2Classify * p1Vec) + np.log(pClass1)    #element-wise mult
    p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
    if p1 > p0:
        return 1
    else:
        return 0

def bagOfWords2VecMN(vocabList, inputSet):
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] += 1
    return returnVec

def textParse(bigString):    #input is big string, #output is word list5
    import re
    listOfTokens = re.split(r'\W*', bigString)
    # return [tok.lower() for tok in listOfTokens if len(tok) > 2]
    return [tok for tok in listOfTokens if len(tok) > 2]
def spamTest():
    global numBad2Good
    global numGood2Bad
    global Accuracy_Rate

    docList=[]; classList = []; fullText =[]
    for i in range(1,501):
        wordList = textParse(open('D:/Sample/tmp/badSRC/%d.txt' % i).read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(1)
        wordList = textParse(open('D:/Sample/tmp/goodSRC/%d.txt' % i).read())
        docList.append(wordList)
        fullText.extend(wordList)
        classList.append(0)
    vocabList = createVocabList(docList)#create vocabulary
    trainingSet = range(500); testSet=[]           #create test set
    for i in range(100):#random for testSet
        randIndex = int(random.uniform(0,len(trainingSet)))
        testSet.append(trainingSet[randIndex])
        del(trainingSet[randIndex])
    trainMat=[]; trainClasses = []
    for docIndex in trainingSet:#train the classifier (get probs) trainNB0
        trainMat.append(bagOfWords2VecMN(vocabList, docList[docIndex]))
        trainClasses.append(classList[docIndex])
    p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
    errorCount = 0;  GoodToBad = 0;BadToGood = 0
    for docIndex in testSet:        #classify the remaining items
        wordVector = bagOfWords2VecMN(vocabList, docList[docIndex])
        # if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
        if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:
            if classifyNB(array(wordVector),p0V,p1V,pSpam) != 1:
                GoodToBad += 1
                numGood2Bad += 1
                # print 'GoodToBad:', docList[docIndex]
                # print 'GoodToBad: NO.',docIndex
                # print 'P-Good:', p0
                # print 'P-Bad :', p1
                # print 'Miss  :', p0-p1
                # print ''
            else:
                BadToGood += 1
                numBad2Good += 1
                # print 'BadToGood', docList[docIndex]
                # print 'P-Good:', p0
                # print 'P-Bad: ', p1
                # print 'Miss  :', p0-p1
                # print 'BadToGood: NO.',docIndex
                # print ''
            errorCount += 1

            # print "classification error",docList[docIndex]
    # print 'the error rate is: ',float(errorCount)/len(testSet)
    Accuracy_Rate = Accuracy_Rate+((1-float(errorCount)/len(testSet))*100)
    print 'Accuracy Rate:%d%% '%((1-float(errorCount)/len(testSet))*100)
    # print 'GoodToBad:', GoodToBad
    # print 'BadToGood:', BadToGood
    #return vocabList,fullText
if __name__ == "__main__":
    for i in range(0,10):
        spamTest()
    print 'Accuracy_Rate',(Accuracy_Rate/10)
    print 'BadToGood: ', (numBad2Good/10)
    print 'GoodToBad: ', (numGood2Bad/10)

總結

  • 對于手機惡意軟件的檢測,90%左右的概率離具體實用還差很多。這篇文章主要就是記錄與分享下學習中經歷。
  • 寫的時候側重了實現,更多的是給出了代碼。有興趣的朋友不妨親自體驗,至于惡意軟件沒有這個問題,在這里附上我除了過得樣本數據。
    實驗數據下載
  • 推薦一本書《機器學習實戰》Petet Harrington著,我的代碼是學習了這本書后改進利用到安卓APP檢測的。
  • 系列文章到此還沒結束,后面還會結合樸素貝葉斯和其他機器學習算法,提高檢測精確度。
  • 實在是表達能力不行,講得不清楚見諒。還是那句話,有興趣的話不妨實際運行下程序,再結合樸素貝葉斯算法就能理解了。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 注:題中所指的『機器學習』不包括『深度學習』。本篇文章以理論推導為主,不涉及代碼實現。 前些日子定下了未來三年左右...
    我偏笑_NSNirvana閱讀 40,092評論 12 145
  • 這個題目取得比較奇怪,原因是:雖然號稱數學是世界上最簡潔的語言,但是太多的公式難免看的人心慌;其次公式在hexo+...
    Helen_Cat閱讀 2,660評論 0 13
  • 【博客的主要內容主要是自己的學習筆記,并結合個人的理解,供各位在學習過程中參考,若有疑問,歡迎提出;若有侵權,請告...
    Paullu閱讀 2,272評論 0 11
  • 一.樸素貝葉斯 1.分類理論 樸素貝葉斯是一種基于貝葉斯定理和特征條件獨立性假設的多分類的機器學習方法,所...
    wlj1107閱讀 3,126評論 0 5
  • 時光將歲月的臉拉長,直至我看不清你們所有的模樣。 在人來人往的走道,我曾奮力舞蹈,旋轉、跳躍,不敢有絲毫怠慢。 當...
    靜和queen閱讀 206評論 0 4