Python之利用機(jī)器學(xué)習(xí)檢測安卓惡意軟件實(shí)現(xiàn)(一)

前言

上一篇文章寫了如何使用Python寫一個(gè)簡單的爬蟲缨恒,批量抓取APK的下載鏈接臣嚣。這篇文章記錄下如何批量拆包APK文件并提取想要的信息颅停。

準(zhǔn)備工作

  • Androguard環(huán)境部署:Androguard下載
  • 在上一篇文章提到的準(zhǔn)備工作的基礎(chǔ)上,這篇文章需要加入Androguard作為環(huán)境具温。Androguard是一款開源的Android應(yīng)用程序分析工具蚕涤,使用Python編寫。眾多功能模塊以Python包的形式存在铣猩。
  • 使用方法:首先將GitHub上的Androguard項(xiàng)目下載下來揖铜。
下載Androguard.png

下載完成后得到一個(gè)壓縮包,解壓后進(jìn)入目錄达皿,把Androguard目錄下所有的文件拷貝至Python的根目錄下天吓,合并同名文件夾即可。

  • 檢查環(huán)境是否部署成功:
    打開cmd命令行峦椰,輸入python進(jìn)入交互狀態(tài)龄寞。輸入from androguard.core.bytecodes import apk, dvm如下圖所示沒有提示任何錯(cuò)誤信息即可。
檢查環(huán)境.png

注意:在cmd下直接調(diào)python命令行需要將Python加入到環(huán)境變量中汤功。

基礎(chǔ)知識

首先APK文件可以用普通解壓縮的方式拆包物邑,如下圖。

解壓完畢.png

熟悉安卓開發(fā)的人肯定對解壓完畢后的文件很熟悉滔金。這里主要介紹部分文件的作用色解。

  • 1.assets文件:這里存放一些資源文件入圖片等,一半情況下解壓縮完畢后是可以直接看到這些圖片的餐茵。
assets.png
  • 2.lib文件:這里存放安卓開發(fā)中使用到的庫文件
庫文件.png
  • 3.AndroidManifest文件:這是我們這次需要關(guān)注的重點(diǎn)科阎。一個(gè)安卓應(yīng)用需要申請的權(quán)限信息,以及Activity等組件的注冊信息都需要在AndroidMainfest.xml文件中聲明忿族。但是直接解壓后的AndroidManifest文件查看確是如下這種情況:
亂碼.png

沒錯(cuò)萧恕,是亂碼。這就說明僅僅使用將APK解壓縮的形式去獲得我們關(guān)心的信息是不可行的肠阱。

使用Python獲取APK信息

到此為止,相信大家對APK的結(jié)構(gòu)有了一定了解朴读。下面以獲取APP申請權(quán)限為例子使用Python完成APK的拆包提取信息屹徘。

  • 首先附上Androguard開發(fā)文檔:Androguard開發(fā)API
  • Androguard是開源的,有興趣的朋友可以去閱讀源碼衅金。這里不過多贅述Androguard實(shí)現(xiàn)原理噪伊,我們從目的入手簿煌,直接使用Androguard。
  • 首先在新建的Python工程中引包from androguard.core.bytecodes import apk, dvm
  • 接著調(diào)用APIapp.get_permissions()
  • 沒錯(cuò)鉴吹,Androguard就是這么強(qiáng)大姨伟,一個(gè)API就完成了拆包提權(quán)操作。那么為了實(shí)現(xiàn)批量拆包提權(quán)(以及提取其他信息)豆励,我們必須自己編寫一個(gè)Python腳本夺荒。
  • 思路很明了,利用Python寫一個(gè)遍歷文件夾中所有文件的腳本良蒸,對每個(gè)apk文件執(zhí)行相應(yīng)的操作即可技扼。為了讓腳本清晰,這里把調(diào)取API和遍歷文件夾放在兩個(gè)腳本中嫩痰。
    首先附上調(diào)用Androguard中API獲取各種信息的代碼:
__author__ = 'Administrator'
#coding=utf-8
from androguard.core.bytecodes import apk, dvm
from androguard.core.analysis import analysis
import re
global count
count = 1

def get_permissions(path, filename):
    str = "Permission:"
    app = apk.APK(path)
    permission = app.get_permissions()
    file = permission
    print permission
    writeToTxt(str, file, filename)
    return permission

def get_apis(path, filename):
  app = apk.APK(path)
  app_dex = dvm.DalvikVMFormat(app.get_dex())
  app_x = analysis.newVMAnalysis(app_dex)
  methods = set()
  cs = [cc.get_name() for cc in app_dex.get_classes()]

  for method in app_dex.get_methods():
    g = app_x.get_method(method)
    if method.get_code() == None:
      continue

    for i in g.get_basic_blocks().get():
      for ins in i.get_instructions():
        output = ins.get_output()
        match = re.search(r'(L[^;]*;)->[^\(]*\([^\)]*\).*', output)
        if match and match.group(1) not in cs:
          methods.add(match.group())

  methods = list(methods)
  methods.sort()
  print "methods:"+"\n"
  print methods
  str = "Methods:"
  file = methods
  writeToTxt(str, file, filename)
  return methods
def get_providers(path, filename):
    app = apk.APK(path)
    providers = app.get_providers()
    print "providers:"+"\n"
    print providers
    str = "Providers:"
    file = providers
    writeToTxt(str, file, filename)
    return providers
def get_package(path, filename):
    app = apk.APK(path)
    packname = app.get_package()
    print "packageName:"+"\n"
    print packname
    str = "PackageName:"
    file = packname
    writeToTxt(str, file, filename)
    return packname
def get_activities(path, filename):
    app = apk.APK(path)
    activitys = app.get_activities()
    print "ActivityName:"+"\n"
    print activitys
    str = "Activitys:"
    file = activitys
    writeToTxt(str, file, filename)
    return activitys
def get_receivers(path, filename):
    app = apk.APK(path)
    receivers = app.get_receivers()
    print "Receivers:"+"\n"
    print receivers
    str = "Receivers:"
    file = receivers
    writeToTxt(str, file, filename)
    return receivers
def get_services(path, filename):
    app = apk.APK(path)
    services = app.get_services()
    print "Services:"+"\n"
    print services
    str = "Services:"
    file = services
    writeToTxt(str, file, filename)
    return services
def writeToTxt(str, file, filename):
    global count
    fm = open('%d'%count+'.txt', 'w')
    #fm.write(str)
    #fm.write("\n")
    for i in file:
        tmp = i.split('.')
        final = tmp[-1]
        fm.write(final)
        fm.write("\t")
    fm.close()
    count += 1

def main(path, apkname):
  get_permissions(path, apkname)
  #get_apis(path, apkname)
  #get_providers(path, apkname)
  #get_package(path, apkname)
  #get_activities(path, apkname)
  #get_receivers(path, apkname)
  #get_services(path, apkname)

if __name__ == '__main__':
    path = "D:/sample/Good"
    filename = "sampleInfo.txt"
    main(path, filename)

  • 上面代碼中剿吻,witeToTex函數(shù)將調(diào)用API所得到的結(jié)果保存在txt文件中,以便查看和日后使用串纺。get_XXXX函數(shù)就是獲取apk文件中對應(yīng)的信息丽旅,其中g(shù)et_permissions獲取apk中申請的權(quán)限,get_apis獲取一些api調(diào)用信息纺棺,顧名思義榄笙,get_XXX就獲取XXX。
  • 再看如何遍歷五辽,這里使用Python 的os.walk遍歷目錄:
    os.walk(top, topdown=True, onerror=None, followlinks=False) 可以得到一個(gè)三元tupple(dirpath, dirnames, filenames), 第一個(gè)為起始路徑办斑,第二個(gè)為起始路徑下的文件夾,第三個(gè)是起始路徑下的文件杆逗。dirpath代表目錄的路徑乡翅,dirnames包含了dirpath下所有子目錄的名字。filenames 包含了非目錄文件的名字罪郊。
  • 遍歷存放眾多APK的文件夾蠕蚜,對每個(gè)APK文件進(jìn)行相應(yīng)操作,代碼如下:
__author__ = 'Administrator'
#-*- coding:GBK -*-
import os
import os.path
import sys
import subprocess
import getFeatures

rootdir = "D:/Sample/Good//"
destdir = "D:/Sample/workSample/badDone//"
command = "java -jar D://apktool.jar"
class Packages:
    def __init__(self, srcdir, desdir):
        self.sdir = srcdir
        self.ddir = desdir
    def check(self):
        print("--------------------starting unpackage!---------------------")
        for dirpath, dirnames, filenames in os.walk(rootdir):
            for filename in filenames:
                thefile = os.path.join(dirpath, filename)
                apkfile = os.path.split(thefile)[1]
                apkname = os.path.splitext(apkfile)[0]
                print apkfile
                try:
                    if os.path.splitext(thefile)[1] == ".apk":
                        # name = os.path.splitext(thefile)[0]
                        str1= '"'+thefile+'"'
                        str2= '"'+destdir + os.path.splitext(filename)[0]+'"'
                        # cmdExtract = r'%s d -f %s %s'% (command, str2, str1)
                        getFeatures.main(thefile, apkname)
                        print "******************well done******************"
                except IOError, err:
                        print err
                        sys.exit()

if __name__ == "__main__":
    dir=Packages(rootdir, 'e:/')
    dir.check()
  • 上面這個(gè)腳本引入文章中第一個(gè)腳本作為模塊悔橄,共同實(shí)現(xiàn)批量拆包提取特征并輸出到txt文件中的功能靶累。這里用正則表達(dá)式對提取出的權(quán)限特征進(jìn)行處理,去掉冗余部分癣疟,僅保留關(guān)鍵字段挣柬,并把每個(gè)apk文件對應(yīng)的權(quán)限特征輸出到各自的txt文本中。
程序運(yùn)行.png
  • 這里APK用以編號睛挚,以方便后面查找對比邪蛔。輸出的最終結(jié)果如下圖:
處理前.png
輸出的txt.png
  • 將權(quán)限信息取冗余后,寫入到txt文件中扎狱,以tab鍵進(jìn)行分離侧到,方便后面使用勃教。
txt中權(quán)限.png

總結(jié)

到此為止,我們就把安卓中的權(quán)限信息提取出來了匠抗。這為后面使用機(jī)器學(xué)習(xí)方式對安卓應(yīng)用進(jìn)行檢測提供了基本的數(shù)據(jù)故源。在接下來的文章中將會進(jìn)一步介紹如何使用Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)的方式檢測安卓惡意應(yīng)用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末汞贸,一起剝皮案震驚了整個(gè)濱河市绳军,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌著蛙,老刑警劉巖删铃,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異踏堡,居然都是意外死亡猎唁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門顷蟆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诫隅,“玉大人,你說我怎么就攤上這事帐偎≈鹞常” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵削樊,是天一觀的道長豁生。 經(jīng)常有香客問我,道長漫贞,這世上最難降的妖魔是什么甸箱? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮迅脐,結(jié)果婚禮上芍殖,老公的妹妹穿的比我還像新娘。我一直安慰自己谴蔑,他們只是感情好豌骏,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著隐锭,像睡著了一般窃躲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钦睡,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天框舔,我揣著相機(jī)與錄音,去河邊找鬼。 笑死刘绣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挣输。 我是一名探鬼主播纬凤,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼撩嚼!你這毒婦竟也來了停士?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤完丽,失蹤者是張志新(化名)和其女友劉穎恋技,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逻族,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜻底,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了聘鳞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片薄辅。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖抠璃,靈堂內(nèi)的尸體忽然破棺而出站楚,到底是詐尸還是另有隱情,我是刑警寧澤搏嗡,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布窿春,位于F島的核電站,受9級特大地震影響采盒,放射性物質(zhì)發(fā)生泄漏旧乞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一纽甘、第九天 我趴在偏房一處隱蔽的房頂上張望良蛮。 院中可真熱鬧,春花似錦悍赢、人聲如沸决瞳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽皮胡。三九已至,卻和暖如春赏迟,著一層夾襖步出監(jiān)牢的瞬間屡贺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甩栈,地道東北人泻仙。 一個(gè)月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像量没,于是被迫代替她去往敵國和親玉转。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容