Welcome to Pyaxml’s documentation 0.1.0!

PyAxml is a full python tool to play with AXML (Android XML) files. This tool is useful to decode and encode AXML files and manipulate AXML files over a Protocol Buffers object. It is designed to work with Python 3 and Rust only.

Some examples of the use of the tool is provided with the project:

  • copymanifest.py that allow to decode and reencode the original file

  • replace_activity_name.py to change the name an activity and replace by an other

If you want to see more example you can dig more on the project apkpatcher that use this library to add some useful permission and inject a library inside the target application. To have a better understanding about how is composed the AXML format a graphic is associated in drawio and svg format: format.drawio, format.drawio.svg

The link of the project https://gitlab.com/MadSquirrels/mobile/pyaxml

QuickStart

To get you started, here is a detailed example of how to replace an activity in an Android AXML file using Python. This script utilizes the pyaxml library to handle the AXML format.

import pyaxml
import click

@click.command()
@click.argument('input_file')
@click.argument('output_file')
@click.argument('activity_name')
@click.argument('new_activity_name')
def replace_activity(input_file, output_file, activity_name, new_activity_name):
   filename = input_file
   with open(filename, "rb") as f:
      axml = pyaxml.AXML.from_axml(f.read())
      xml = axml.to_xml()
      android_name = "{http://schemas.android.com/apk/res/android}name"
      for activity in xml.findall(f"./application/activity/[@{android_name}='{activity_name}']"):
            activity.attrib[android_name] = new_activity_name
      axml_object = pyaxml.AXML()
      axml_object.from_xml(xml)
   # Rewrite the file
   with open(output_file, "wb") as f:
      f.write(axml_object.pack())

if __name__ == "__main__":
   replace_activity()

To begin with a more simple example you can use the tool to only encode and decode AXML thanks to 3 available commands:

  • axml2xml: to decode AXML and print it in XML;

  • arsc2xml: to decode ARSC and print it in XML;

  • xml2axml: to encode XML in AXML.

# Python CLI
pyaxml axml2xml -i AndroidManifest.xml
pyaxml arsc2xml -i resources.arsc
pyaxml xml2axml -i AndroidManifest.xml -o AndroidManifest.axml

# Rust CLI (same commands, no Python required)
pyaxml-rs axml2xml -i AndroidManifest.xml
pyaxml-rs arsc2xml -i resources.arsc
pyaxml-rs xml2axml -i AndroidManifest.xml -o AndroidManifest.axml

AXML or ARSC

In Android application development, AXML and ARSC files are key components:

  • AXML (Android XML): Typically used for AndroidManifest.xml, which contains essential information about the application such as its components and permissions.

  • ARSC (Android Resource Synchronized Container): Contains compiled resources like strings, styles, and layouts.

To handle these file types, pyaxml provides distinct classes for each:

  • AXML: Manages AXML files, allowing for parsing and modification of XML data.

  • ARSC: Handles ARSC files, enabling the manipulation of compiled resource data.

When dealing with files whose type you might not be certain of, pyaxml offers a convenient solution:

  • AXML_guess: This class includes the from_axml method, which can automatically determine whether a file is an AXML or an ARSC file. Based on this determination, it returns an instance of either the AXML class or the ARSC class.

Example Usage

Here’s how you might use AXML_guess to handle files without knowing their exact type:

import pyaxml
import click

@click.command()
@click.argument('input_file')
def process_file(input_file):
   filename = input_file
   with open(filename, "rb") as f:
      guessed_object = pyaxml.AXML_guess.from_axml(data)

      if isinstance(guessed_object, pyaxml.AXML):
            print("Processing AXML file")
            # Handle AXML file
            xml = guessed_object.to_xml()
            # Perform operations on XML data
            # ...
      elif isinstance(guessed_object, pyaxml.ARSC):
            print("Processing ARSC file")
            # Handle ARSC file
            # Perform operations on ARSC data
            # ...
      else:
            print("Unknown file type")

   # Write the modified AXML to the output file
   with open(output_file, "wb") as f:
      f.write(guessed_object.pack())

if __name__ == "__main__":
   process_file()

Details

Indices and tables