ATX Go、Python 语言解析安卓 APK 包

codeskyblue · 2017年07月04日 · 最后由 hantaohuang 回复于 2018年08月27日 · 5587 次阅读

Go 语言解析 APK

Github 上有一个非常棒的 Go 语言的库 https://github.com/shogo82148/androidbinary
虽然 Star 数量有点少,不过代码质量高的惊人。维护人是一位来自日本的shogo82148 对于项目的 Issue 处理的很及时。

使用这个库可以解析 apk 文件中的AndroidManifest.xml以及resources.arsc ,原本解析这些文件需要非常了解这些文件的结构,处理起来非常复杂,但是借助这个库,分析起来就很容易。

例子

举例说明下

package main

import (
    "github.com/shogo82148/androidbinary/apk"
)

func main() {
    pkg, _ := apk.OpenFile("your-android-app.apk")
    defer pkg.Close()

    icon, _ := apk.Icon(nil) // returns the icon of APK as image.Image
    pkgName := pkg.PackageName() // returns the pakcage name
    mainActivity, _ = pkg.MainAcitivty()
}

就这么点代码就可以获取到应用的 packageName 以及应用图标(图标其实最难解析),但是借助这个库,实现起来就很容易。

再次贴一下这个项目的地址 https://github.com/shogo82148/androidbinary

Python 解析 APK

解析 apk 的 Python 库有很多,但是并没有出现一个特别强的,可以一统天下的库。

就用目前我感觉最好的一个库作为例子。

pip install AxmlParserPY==0.0.3

保存下面的代码为 apkparse.py

#!/usr/bin/env python
# coding: utf-8

import zipfile
from xml.dom import minidom
from axmlparserpy.axmlprinter import AXMLPrinter


class Manifest(object):
    def __init__(self, content):
        self._dom = minidom.parseString(content)
        self._permissions = None

    @property
    def package_name(self):
        return self._dom.documentElement.getAttribute('package')

    @property
    def version_code(self):
        return self._dom.documentElement.getAttribute("android:versionCode")

    @property
    def version_name(self):
        return self._dom.documentElement.getAttribute("android:versionName")

    @property
    def permissions(self):
        if self._permissions is not None:
            return self._permissions

        self._permissions = []
        for item in self._dom.getElementsByTagName("uses-permission"):
            self._permissions.append(str(item.getAttribute("android:name")))
        return self._permissions

    @property
    def main_activity(self):
        """
        Returns:
            the name of the main activity
        """
        x = set()
        y = set()

        for item in self._dom.getElementsByTagName("activity"):
            for sitem in item.getElementsByTagName("action"):
                val = sitem.getAttribute("android:name")
                if val == "android.intent.action.MAIN":
                    x.add(item.getAttribute("android:name"))

            for sitem in item.getElementsByTagName("category"):
                val = sitem.getAttribute("android:name")
                if val == "android.intent.category.LAUNCHER":
                    y.add(item.getAttribute("android:name"))

        z = x.intersection(y)
        if len(z) > 0:
            return z.pop()
        return None


def parse_apk(filename):
    '''
    Returns:
        Manifest(Class)
    '''
    with zipfile.ZipFile(filename, 'r') as file:
        manifest = file.read('AndroidManifest.xml')
    return Manifest(AXMLPrinter(manifest).getBuff())

if __name__ == '__main__':
    m = parse_apk("your-apk.apk")
    print m.version_code
附言 1  ·  2018年06月20日

最近又冒出来一个 python 库 apkutils https://github.com/mikusjelly/apkutils 也挺好用的感觉

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 4 条回复 时间 点赞

收藏

—— 来自 TesterHome 官方 安卓客户端

mark,感谢分享

给力!感谢 LZ 分享๑¯∀¯๑

稍微修正下你的代码:

package main

import (
    "fmt"
    "flag"
    "github.com/shogo82148/androidbinary/apk"
)

func main() {
    fileName := flag.String("filename", "", "pkg filename")
    flag.Parse()

    pkg, _ := apk.OpenFile(*fileName)
    defer pkg.Close()
    res := ""

    pkgName := pkg.PackageName()
    res += pkgName
    res += " "
    verCode := pkg.VersionCode()
    verCodeStr := fmt.Sprintf("%d", verCode)
    res += verCodeStr
    res += " "
    verName := pkg.VersionName()
    res += verName
    res += " "
    appName, _ := pkg.Label(nil)
    res += appName

    fmt.Println(res)
}
1楼 已删除
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册