apkutils

repository·master·Indexed 41 days ago

https://github.com/kin9-0rz/apkutils

A Python library and CLI tool for parsing Android-related file formats, including APK, Dex, AXML, ARSC, and ELF. Version 2.0.5 provides programmatic access via the APK class to extract manifest information, analyze DEX bytecode with cross-references (XREF), retrieve digital certificates, and manage ZIP archives.

Tokens
10.8K
Snippets
57
Records
58
Agent score
50%

What's inside apkutils

  1. Understand DexFile structure and ID tables

    master

    A DexFile object acts as a container for the parsed DEX structure. It maintains several SizeOff objects that point to the start offset and size of various ID tables:

    • string_ids
    • type_ids
    • proto_ids
    • field_ids
    • method_ids
    • class_defs
    • data
    • link (SizeOff containing size and off for the link section)
    • map_off (offset for the mapping section)
  2. Use APK_Intersection to analyze overlaps between multiple APKs

    master

    The APK_Intersection class is used to find commonalities (intersections) across a collection of APK objects. It provides methods to compare manifest contents, DEX strings, opcodes, resources, and files to identify shared characteristics between different APKs.

    To use it, initialize the class with a list of APK objects (which must implement specific getter methods like get_mini_mani(), get_strings(), etc.).

    ```python
    from apkutils.intersection import APK_Intersection
    
    # Assuming 'apk_list' is a list of APK objects already instantiated
    intersection_engine = APK_Intersection(apk_list)
    
    # Example: Get common strings across all APKs
    common_strings = intersection_engine.intersect_dex_string()
    
    # Example: Get common manifest components (activities, services, etc.)
    # Returns (words_dict, nums_dict, words2_set)
    words, nums, words2 = intersection_engine.intersect_manifest()
    ```埋
  3. Initialize an APK object

    master

    You can create an APK instance using several methods depending on your source data:

    • APK.from_file(path): Load an APK from a file path.
    • APK.from_bytes(_bytes): Load an APK from raw bytes.
    • APK.from_io(_io): Load an APK from a file-like object (io.BytesIO).

    Note that the APK class supports the context manager pattern (with statement) to ensure the underlying file handle is closed automatically.

    from apkutils.apk import APK
    
    # Using a file path
    with APK.from_file("path/to/app.apk") as apk:
        print(apk.package_name)
    
    # Using bytes
    with APK.from_bytes(raw_data) as apk:
        print(apk.get_manifest())
  4. Use the APK class in Python

    master

    The APK class is the primary entry point for programmatic access to APK, Dex, ARSC, AXML, and ELF parsing.

    Important Note on Parsing: Parsing is performed on-demand. Calling parse_manifest() will only parse the manifest and will not parse Dex files or icons. To extract resources like the manifest, ARSC, application name, or icons, you must use the resource parsing methods.

    from apkutils import APK
    
    # Option 1: Manual lifecycle management
    apk = APK.from_file(file_path).parse_manifest()
    manifest = apk.get_manifest()
    apk.close()
    
    # Option 2: Using a context manager (recommended)
    with APK.from_file(file_path) as apk:
        manifest = apk.get_manifest()
  5. Use the APK class for parsing

    master

    Use the APK class to load and inspect APK files.

    Important Note: To retrieve the manifest, ARSC, application name, or icons, you must call .parse_resource() after loading the file.

    Starting from version 1.3.0, the library does not parse the manifest, icons, or Dex files by default to improve performance; these must be parsed on demand.

    from apkutils import APK
    
    # Method 1: Manual close
    apk = APK.from_file(file_path).parse_resource()
    manifest = apk.get_manifest()
    apk.close()
    
    # Method 2: Using a context manager (recommended)
    with APK.from_file(file_path) as apk:
        # Note: parse_resource() is required for manifest/resources
        apk.parse_resource()
        manifest = apk.get_manifest()
  6. Reference apkutils CLI commands

    master

    The following commands are available via the apkutils CLI:

    Commands:
      arsc      打印arsc (Print ARSC)
      certs     打印证书 (Print certificates)
      files     打印文件 (Print files)
      manifest  打印清单 (Print manifest)
      mtds      获取指定方法中的所有字符串 (Get all strings in a specific method)
      strings   打印Dex中的字符串 (Print strings in Dex)
      unzip     解压文件,默认显示zip文件 (Unzip files, defaults to zip)
      xref      获取方法的引用方法 (Get method references)
  7. Transform DEX class names to Python attributes

    master

    Use FormatClassToPython to convert a DEX-style typed class name into a string suitable for use as a Python attribute. This replaces slashes and dollar signs with underscores.

    Example: Lfoo/bar/foo/Barfoo$InnerClass; $\rightarrow$ Lfoo_bar_foo_Barfoo_InnerClass.

    from apkutils.axml.bytecode import FormatClassToPython
    
    python_attr = FormatClassToPython('Lfoo/bar/foo/Barfoo$InnerClass;')
    print(python_attr)  # Output: 'Lfoo_bar_foo_Barfoo_InnerClass'
  8. Transform Java class names to DEX/Typed formats

    master

    Use FormatClassToJava to convert a standard dot-separated Java class name into the specific descriptor format used in DEX files (e.g., java.lang.Object $\rightarrow$ Ljava/lang/Object;).

    from apkutils.axml.bytecode import FormatClassToJava
    
    # Convert dot notation to DEX descriptor
    dex_name = FormatClassToJava('java.lang.Object')
    print(dex_name)  # Output: 'Ljava/lang/Object;'
  9. Open a file within a ZIP archive

    master

    The open(name, mode="r", pwd=None) method returns a file-like object for the specified member. Supported modes are "r", "U", or "rU". If the file is encrypted, pwd must be provided as bytes.

    with zf.open("large_file.bin", mode="r") as f:
        content = f.read()