通过Python脚本读取apk信息

来源:互联网 发布:淘宝上传工具 编辑:程序博客网 时间:2024/06/03 03:33

       本文将主要介绍通过Python脚本检测apk信息的功能,介绍具体的实现之前,首先介绍一个Android SDK中的开发工具aapt。

       aapt即Android Asset Packaging Tool,我们可以在Android SDK的platform-tools目录下找到该工具。aapt可以查看、 创建、 更新ZIP格式的文档,也可将资源文件编译成二进制文件,Android IDE编译Android应用程序的时候就是使用aapt对资源进行打包的。当我们需要对apk进行分析的时候,aapt就派上用场了。

       下面首先将会介绍如何使用aapt以及aapt的基本功能。

1. 列出apk包的内容

 aapt l[ist] [-v] [-a] file.{zip,jar,apk}

-v 以table形式列出来

-a 详细列出内容 

 例如:aapt l <你的apk文件>,表示查看apk的内容

2. 查看apk一些信息

aapt d[ump] [--values] WHAT file.{apk} [asset [asset ...]]

badging          Print the label and icon for the app declared in APK
permissions      Print the permissions from the APK.
resources        Print the resource table from the APK.
configurations   Print the configurations in the APK.
xmltree          Print the compiled xmls in the given assets.
xmlstrings       Print the strings of the given compiled xml assets.

例如:aapt d permissions <apk文件>,这个就是显示这个apk所具有的权限。

执行aapt d badging mydemo.apk,会得到下面的结果(未截取全部内容)。可以看到其中包含了应用包名、版本号、permission等信息。


3. 编译android资源

 aapt p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] /
        [-0 extension [-0 extension ...]] [-g tolerance] [-j jarfile] /
        [--debug-mode] [--min-sdk-version VAL] [--target-sdk-version VAL] /
        [--app-version VAL] [--app-version-name TEXT] [--custom-package VAL] /
        [--rename-manifest-package PACKAGE] /
        [--rename-instrumentation-target-package PACKAGE] /
        [--utf16] [--auto-add-overlay] /
        [--max-res-version VAL] /
        [-I base-package [-I base-package ...]] /
        [-A asset-source-dir]  [-G class-list-file] [-P public-definitions-file] /
        [-S resource-sources [-S resource-sources ...]]         [-F apk-file] [-J R-file-dir] /
        [--product product1,product2,...] /
        [raw-files-dir [raw-files-dir] ...]

这个比较复杂,只解释几个关键参数。

-f 如果编译出来的文件已经存在,强制覆盖。

-m 使生成的包的目录放在-J参数指定的目录。

-J 指定生成的R.Java的输出目录

-S res文件夹路径

-A assert文件夹的路径

-M AndroidManifest.xml的路径

-I 某个版本平台的android.jar的路径

-F 具体指定apk文件的输出

例如:

一. 将工程的资源编译R.java文件

aapt package -m -J <R.java目录> -S <res目录> -I <android.jar目录>  -M <AndroidManifest.xml目录>

二. 将工程的资源编译到一个包里

aapt package -f  -S <res目录> -I <android.jar目录> -A<assert目录>  -M <AndroidManifest.xml目录> -F <输出的包目录>

4.  从apk中移除文件

aapt r[emove] [-v] file.{zip,jar,apk} file1 [file2 ...]

例如:aapt r <apk文件名> AndroidManifest.xml, 表示从apk中将AndroidManifest.xml移除

5. 添加文件到apk中

 aapt a[dd] [-v] file.{zip,jar,apk} file1 [file2 ...]

例如:aapt a <apk文件名> <要添加的文件路径>, 表示将文件添加到打包好的apk文件中

下面利用aapt工具来完成检测apk的功能,脚本的主要功能包括:

1)检测包名和版本号

2)检测apk使用了哪些权限

3)检测apk中是否包含某个文件

4)将一个文件插入apk中

脚本内容如下:

#!/usr/bin/env python# -*- coding: utf-8 -*-import osimport sysimport zipfileimport redef getAppBaseInfo(apkpath):    #检查版本号等信息    output = os.popen("./aapt d badging %s" % apkpath).read()    match = re.compile("package: name='(\S+)' versionCode='(\d+)' versionName='(\S+)' platformBuildVersionName='\S+'").match(output)    if not match:        raise Exception("can't get packageinfo")    packagename = match.group(1)    versionCode = match.group(2)    versionName = match.group(3)    print('packagename:' + packagename)    print('versionCode:' + versionCode)    print('versionName:' + versionName)    #获得所有的权限    outList = output.split('\n')    for line in outList:        if line.startswith('uses-permission:'):            print(line.split('=')[1])def getCurrentDirApk():    for dir in os.walk(os.curdir):        for filename in dir[2]:            if os.path.splitext(filename)[1] == '.apk':                print('find apk:', filename)                return filenamedef insertFile(apkName, f):    output = os.popen("./aapt a %s %s" % (apkName, f)).read()if __name__ == "__main__":    #获得apk名    if len(sys.argv) == 1:        apkName = getCurrentDirApk()    else:        apkName = sys.argv[1]    if not apkName:        print('can not find apk!!!')        exit()    getAppBaseInfo(apkName)    #向apk中插入文件    insertfile = 'insertfile.txt'    f = open(insertfile, "w+")    f.write('hello android')    f.close()    insertFile(apkName, insertfile)    print('======================')    #检查是否包含某个文件    z = zipfile.ZipFile(apkName)    for file in z.namelist():        if file == insertfile:            print('find ', insertfile, " in apk ", apkName)    z.close()
       下面分析一下这段Python代码。

       在程序的入口位置检测参数个数,如果参数个数为2,就把第二个参数当做apk,否则,调用getCurrentDirApk()方法在当前目录下搜索apk,如果没有找到apk,则直接退出程序。getCurrentDirApk()方法调用了os.walk()对当前目录进行遍历,找到第一个后缀为".apk"的文件,然后返回。

    if len(sys.argv) == 1:        apkName = getCurrentDirApk()    else:        apkName = sys.argv[1]    if not apkName:        print('can not find apk!!!')        exit()
def getCurrentDirApk():    for dir in os.walk(os.curdir):        for filename in dir[2]:            if os.path.splitext(filename)[1] == '.apk':                print('find apk:', filename)                return filename
       然后调用getAppBaseInfo()获取apk信息,包括获取包名、版本号和使用的权限。原理就是我们开头提到的aapt命令,然后拿到输出结果通过正则表达式进行匹配,匹配成功得到结果。而权限的获取是通过逐行遍历检测是否以'uses-permission:'开头,如果是的话就将后面的权限内容取出。

def getAppBaseInfo(apkpath):    #检查版本号等信息    output = os.popen("./aapt d badging %s" % apkpath).read()    match = re.compile("package: name='(\S+)' versionCode='(\d+)' versionName='(\S+)' platformBuildVersionName='\S+'").match(output)    if not match:        raise Exception("can't get packageinfo")    packagename = match.group(1)    versionCode = match.group(2)    versionName = match.group(3)    print('packagename:' + packagename)    print('versionCode:' + versionCode)    print('versionName:' + versionName)    #获得所有的权限    outList = output.split('\n')    for line in outList:        if line.startswith('uses-permission:'):            print(line.split('=')[1])
       最后还是通过aapt a 命令将一个文件插入apk包中,然后zipfile获得包内容,检测包中是否包含这个文件。
    #向apk中插入文件    insertfile = 'insertfile.txt'    f = open(insertfile, "w+")    f.write('hello android')    f.close()    insertFile(apkName, insertfile)    print('======================')    #检查是否包含某个文件    z = zipfile.ZipFile(apkName)    for file in z.namelist():        if file == insertfile:            print('find ', insertfile, " in apk ", apkName)    z.close()
def insertFile(apkName, f):    output = os.popen("./aapt a %s %s" % (apkName, f)).read()

       脚本执行结果如下:


       通过aapt命令我们完成了检测apk的功能,当然它可以完成的功能不只这么多,更多的功能可以自己去发掘。



完整示例下载


参考文章:http://blog.csdn.net/electricity/article/details/6540247

0 0