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

前言

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

準備工作

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

基本思路

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

樸素貝葉斯

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

實現(xiàn)算法

話不多說瞒斩,接下來開始用Python實現(xiàn)樸素貝葉斯算法破婆。

  • 我們使用權限(permission)作為特征,所以首先構建一個包含所有權限項的無重復列表胸囱。如:【權限1祷舀,權限2,……烹笔,權限n】
  • 這里我是用了一個簡單直接的方法裳扯,讀遍所有的txt文件中的每個項,只要有之前不存在的項就追加到list中谤职。其實可以去安卓官網(wǎng)查看安卓開發(fā)者可以申請到的全部權限饰豺,直接構建出list。
構建list.png
  • 接著需要將每個txt文件處理成向量的形式允蜈。舉個例子冤吨,如果樣本1對應的權限項為【權限1蒿柳,權限3,權限5锅很,權限7】其馏,則他的對應向量就是【1,0,1,0,1,0,1,0,0,0】——》假設全部權限的list長度為10項凤跑。
處理每條txt.png
  • 接著就是訓練函數(shù)爆安,其基本思想總結為如下偽代碼:
    計算每個類別中文檔數(shù)目
對于每個txt文檔:
    對于每個類別:
        如果權限項出現(xiàn)在文檔中則增加該詞條計數(shù)值
        增加所有權限項計數(shù)值
    對于每個類別:
        將該權限項數(shù)目除以總數(shù)得到條件概率
返回條件概率```
舉個例子,首先初始化一個全為0的list仔引,長度等于所有不重復權限項的數(shù)量和(假設為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】夫否,除以總數(shù)3得到P=【0.67 ,0.67 ,0.33 ,0.33 ,0.67】彻犁。那么根據(jù)樸素貝葉斯算法,認為每個權限項都是獨立的凰慈,則假設待測樣本為【1,0,0,1,0】汞幢,那么他屬于正常樣本的概率為P=1*0.67*1*0.33=0.2211
* 上面的例子針對正常樣本和惡意樣本都要做。分類算法較簡單微谓,只需要計算出P正常和P惡意森篷,然后比較哪個概率大。我們就將待測樣本分類到概率大的一類中豺型。
* 測試指標:我們使用檢測率仲智,就是分類正確的概率。在500條正常樣本和500條惡意樣本中姻氨,隨機選出400個正常樣本和400個惡意樣本作為訓練集坎藐,訓練出分類器。然后用剩下的200個樣本作為未知待測樣本哼绑,對其進行檢測岩馍。輸出分類錯誤的情況以及準確率。

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

# 執(zhí)行結果截圖
* 這里執(zhí)行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%左右的概率離具體實用還差很多他爸。這篇文章主要就是記錄與分享下學習中經歷。
  • 寫的時候側重了實現(xiàn)果善,更多的是給出了代碼诊笤。有興趣的朋友不妨親自體驗,至于惡意軟件沒有這個問題巾陕,在這里附上我除了過得樣本數(shù)據(jù)讨跟。
    實驗數(shù)據(jù)下載
  • 推薦一本書《機器學習實戰(zhàn)》Petet Harrington著,我的代碼是學習了這本書后改進利用到安卓APP檢測的鄙煤。
  • 系列文章到此還沒結束晾匠,后面還會結合樸素貝葉斯和其他機器學習算法,提高檢測精確度馆类。
  • 實在是表達能力不行混聊,講得不清楚見諒。還是那句話乾巧,有興趣的話不妨實際運行下程序句喜,再結合樸素貝葉斯算法就能理解了。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末沟于,一起剝皮案震驚了整個濱河市咳胃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌旷太,老刑警劉巖展懈,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異供璧,居然都是意外死亡存崖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門睡毒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來来惧,“玉大人,你說我怎么就攤上這事演顾」┎螅” “怎么了隅居?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長葛虐。 經常有香客問我胎源,道長,這世上最難降的妖魔是什么屿脐? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任涕蚤,我火速辦了婚禮,結果婚禮上摄悯,老公的妹妹穿的比我還像新娘赞季。我一直安慰自己愧捕,他們只是感情好奢驯,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著次绘,像睡著了一般瘪阁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上邮偎,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天管跺,我揣著相機與錄音,去河邊找鬼禾进。 笑死豁跑,一個胖子當著我的面吹牛最筒,可吹牛的內容都是我干的阐斜。 我是一名探鬼主播缚甩,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼叔扼,長吁一口氣:“原來是場噩夢啊……” “哼尾抑!你這毒婦竟也來了伐坏?” 一聲冷哼從身側響起逝慧,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤截驮,失蹤者是張志新(化名)和其女友劉穎婆瓜,沒想到半個月后快集,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡廉白,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年个初,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猴蹂。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡院溺,死狀恐怖,靈堂內的尸體忽然破棺而出晕讲,到底是詐尸還是另有隱情覆获,我是刑警寧澤马澈,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站弄息,受9級特大地震影響痊班,放射性物質發(fā)生泄漏。R本人自食惡果不足惜摹量,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一涤伐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缨称,春花似錦凝果、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至当凡,卻和暖如春山害,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沿量。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工浪慌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朴则。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓权纤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乌妒。 傳聞我的和親對象是個殘疾皇子汹想,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內容

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