前言
上一篇文章写了如何使用Python写一个简单的爬虫,批量抓取APK的下载链接。这篇文章记录下如何批量拆包APK文件并提取想要的信息。
准备工作
Androguard环境部署:Androguard下载
在上一篇文章提到的准备工作的基础上,这篇文章需要加入Androguard作为环境。Androguard是一款开源的Android应用程序分析工具,使用Python编写。众多功能模块以Python包的形式存在。
使用方法:首先将GitHub上的Androguard项目下载下来。
下载Androguard.png
下载完成后得到一个压缩包,解压后进入目录,把Androguard目录下所有的文件拷贝至Python的根目录下,合并同名文件夹即可。
检查环境是否部署成功:
打开cmd命令行,输入python进入交互状态。输入from androguard.core.bytecodes import apk, dvm
如下图所示没有提示任何错误信息即可。
检查环境.png
注意:在cmd下直接调python命令行需要将Python加入到环境变量中。
基础知识
首先APK文件可以用普通解压缩的方式拆包,如下图。
解压完毕.png
熟悉安卓开发的人肯定对解压完毕后的文件很熟悉。这里主要介绍部分文件的作用。
1.assets文件:这里存放一些资源文件入图片等,一半情况下解压缩完毕后是可以直接看到这些图片的。
assets.png
2.lib文件:这里存放安卓开发中使用到的库文件
库文件.png
3.AndroidManifest文件:这是我们这次需要关注的重点。一个安卓应用需要申请的权限信息,以及Activity等组件的注册信息都需要在AndroidMainfest.xml文件中声明。但是直接解压后的AndroidManifest文件查看确是如下这种情况:
乱码.png
没错,是乱码。这就说明仅仅使用将APK解压缩的形式去获得我们关心的信息是不可行的。
使用Python获取APK信息
到此为止,相信大家对APK的结构有了一定了解。下面以获取APP申请权限为例子使用Python完成APK的拆包提取信息。
首先附上Androguard开发文档:Androguard开发API
Androguard是开源的,有兴趣的朋友可以去阅读源码。这里不过多赘述Androguard实现原理,我们从目的入手,直接使用Androguard。
首先在新建的Python工程中引包
from androguard.core.bytecodes import apk, dvm
接着调用API
app.get_permissions()
没错,Androguard就是这么强大,一个API就完成了拆包提权操作。那么为了实现批量拆包提权(以及提取其他信息),我们必须自己编写一个Python脚本。
思路很明了,利用Python写一个遍历文件夹中所有文件的脚本,对每个apk文件执行相应的操作即可。为了让脚本清晰,这里把调取API和遍历文件夹放在两个脚本中。
首先附上调用Androguard中API获取各种信息的代码:
__author__ = 'Administrator'#coding=utf-8from androguard.core.bytecodes import apk, dvmfrom androguard.core.analysis import analysisimport reglobal count count = 1def get_permissions(path, filename): str = "Permission:" app = apk.APK(path) permission = app.get_permissions() file = permission print permission writeToTxt(str, file, filename) return permissiondef 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 methodsdef 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 providersdef 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 packnamedef 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 activitysdef 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 receiversdef 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 servicesdef 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 += 1def 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函数将调用API所得到的结果保存在txt文件中,以便查看和日后使用。get_XXXX函数就是获取apk文件中对应的信息,其中get_permissions获取apk中申请的权限,get_apis获取一些api调用信息,顾名思义,get_XXX就获取XXX。
再看如何遍历,这里使用Python 的os.walk遍历目录:
os.walk(top, topdown=True, onerror=None, followlinks=False) 可以得到一个三元tupple(dirpath, dirnames, filenames), 第一个为起始路径,第二个为起始路径下的文件夹,第三个是起始路径下的文件。dirpath代表目录的路径,dirnames包含了dirpath下所有子目录的名字。filenames 包含了非目录文件的名字。遍历存放众多APK的文件夹,对每个APK文件进行相应操作,代码如下:
__author__ = 'Administrator'#-*- coding:GBK -*-import osimport os.pathimport sysimport subprocessimport 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()
上面这个脚本引入文章中第一个脚本作为模块,共同实现批量拆包提取特征并输出到txt文件中的功能。这里用正则表达式对提取出的权限特征进行处理,去掉冗余部分,仅保留关键字段,并把每个apk文件对应的权限特征输出到各自的txt文本中。
程序运行.png
这里APK用以编号,以方便后面查找对比。输出的最终结果如下图:
处理前.png
输出的txt.png
将权限信息取冗余后,写入到txt文件中,以tab键进行分离,方便后面使用。
txt中权限.png
总结
到此为止,我们就把安卓中的权限信息提取出来了。这为后面使用机器学习方式对安卓应用进行检测提供了基本的数据。在接下来的文章中将会进一步介绍如何使用Python实现机器学习的方式检测安卓恶意应用。
作者:CaptainXero
链接:https://www.jianshu.com/p/670023af50f6
共同学习,写下你的评论
评论加载中...
作者其他优质文章