Welcome to Pyaxml’s documentation 0.0.16!
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 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:
# Read AXML and get XML object
axml, _ = pyaxml.AXML.from_axml(f.read())
xml = axml.to_xml()
android_name = "{http://schemas.android.com/apk/res/android}name"
# Find and replace the activity name
for activity in xml.findall(f"./application/activity/[@{android_name}='{activity_name}']"):
activity.attrib[android_name] = new_activity_name
# Reencode XML to AXML
axml_object = pyaxml.axml.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()
Explanation of the Key Steps
Reading the AXML File:
pyaxml.AXML.from_axml(f.read()): This method reads the AXML file and returns an AXML object, which contains the protobuf representation of the AXML. You can then modify this object as needed.
Modifying AXML:
to_xml(): Converts the AXML object to XML format. This transformation allows for easier manipulation of the data, enabling operations such as searching and updating elements using standard XML tools.
Finding and Replacing the Activity Name:
xml.findall(): This method searches through the XML structure for specific elements. In this case, it looks for activities in the AndroidManifest.xml that match the specified activity_name and updates their name to new_activity_name.
Reencoding XML to AXML:
from_xml(xml): Converts the modified XML back into the AXML format.
Writing the Output:
pack(): Packs the AXML object into its binary form, ready to be written back to the file. The modified AXML data is written to the specified output file.
These methods can be applied to handle various aspects of AXML objects and are crucial for tasks involving AXML modification.
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()