Skip to content

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

axml-parser

Android binary XML (AXML) and resource (ARSC) parser in pure Rust, with optional Python bindings (PyO3). Port of androguard/axml.

Features

  • AXML — decode binary AndroidManifest.xml (and other compiled XML) to text, with package / version / permissions
  • ARSC — parse resources.arsc, resolve resource IDs to Java names and string values
  • CLI — axml and arsc binaries
  • Python — same API via pip install / maturin develop

Install

Rust

cargo add axml-parser

Python (from source)

Requires a Rust toolchain and Python ≥ 3.9.

python3 -m venv .venv && source .venv/bin/activate
pip install maturin
maturin develop --features python

Or build a wheel:

maturin build --release --features python
pip install target/wheels/axml_parser-*.whl

CLI

# Decode binary AndroidManifest.xml
cargo run --bin axml -- -i tests/AXML/AndroidManifest.xml

# With metadata (real output from tests/AXML/AndroidManifest-Chinese.xml)
cargo run --bin axml -- -i tests/AXML/AndroidManifest-Chinese.xml -v
# Valid: true
# Package: com.hotel
# Version: {"Name": "1.7.2", "Code": "8"}
# Permissions: ["android.permission.WAKE_LOCK", "android.permission.INTERNET", ...]

cargo run --bin arsc -- -i tests/ARSC/TestActivity_resources.arsc -v
# Packages: ["tests.androguard"]

Rust API (real example)

Using the fixtures under tests/:

use axml_parser::{ARSCParser, AXMLPrinter};

fn main() {
    // --- AXML: AndroidManifest.xml ---
    let data = std::fs::read("tests/AXML/AndroidManifest-Chinese.xml").unwrap();
    let ap = AXMLPrinter::new(&data);
    assert!(ap.is_valid());
    assert_eq!(ap.package(), "com.hotel");
    assert_eq!(ap.androidversion().get("Code").map(String::as_str), Some("8"));
    assert_eq!(ap.androidversion().get("Name").map(String::as_str), Some("1.7.2"));
    // permissions include INTERNET, SEND_SMS, ACCESS_FINE_LOCATION, ...
    let xml = String::from_utf8_lossy(&ap.get_xml(true));
    assert!(xml.contains(r#"package="com.hotel""#));

    // --- ARSC: resources.arsc ---
    let arsc_data = std::fs::read("tests/ARSC/TestActivity_resources.arsc").unwrap();
    let arsc = ARSCParser::new(&arsc_data).unwrap();
    assert_eq!(arsc.get_packages_names(), vec!["tests.androguard".to_string()]);
    assert_eq!(arsc.resolve_id(0x7F040001).as_deref(), Some("R.string.app_name"));
    assert_eq!(
        arsc.id_to_string_value().get(&0x7F040001).map(String::as_str),
        Some("TestsAndroguardApplication")
    );
    assert_eq!(
        arsc.id_to_string_value().get(&0x7F040000).map(String::as_str),
        Some("Hello World, TestActivity! kikoololmodif")
    );

    let (res_id, pkg) = ARSCParser::parse_id("@7F040001").unwrap();
    assert_eq!(res_id, 0x7F040001);
    assert!(pkg.is_none());
}

Run the ARSC dump example:

cargo run --example arsc_dump
# packages: ["tests.androguard"]
# 0x7F040001 -> R.string.app_name
# 0x7F040001 = "TestsAndroguardApplication"
# resolve 0x7F040001: Some("R.string.app_name")

Python API (real example)

After maturin develop --features python:

from axml_parser import AXMLPrinter, ARSCParser, decode_axml

# --- AXML ---
ap = AXMLPrinter.from_file("tests/AXML/AndroidManifest-Chinese.xml")
assert ap.is_valid() is True
assert ap.package == "com.hotel"
assert ap.androidversion == {"Code": "8", "Name": "1.7.2"}
assert "android.permission.INTERNET" in ap.permissions
print(ap.get_xml()[:80])
# <?xml version="1.0" encoding="UTF-8"?><manifest xmlns:android="http://schemas...

xml, meta = decode_axml("tests/AXML/AndroidManifest.xml")
assert meta["package"] == "org.t0t0.androguard.TC"

# --- ARSC ---
arsc = ARSCParser.from_file("tests/ARSC/TestActivity_resources.arsc")
assert arsc.get_packages_names() == ["tests.androguard"]
assert arsc.resolve_id(0x7F040001) == "R.string.app_name"
assert arsc.id_to_string_value()[0x7F040001] == "TestsAndroguardApplication"
assert arsc.id_to_string_value()[0x7F040000] == "Hello World, TestActivity! kikoololmodif"
assert ARSCParser.parse_id("@7F040001") == (0x7F040001, None)

Python surface

Symbol Role
AXMLPrinter(bytes) / .from_file(path) Decode binary XML
.package, .androidversion, .permissions Manifest metadata
.get_xml(pretty=True) Decoded XML string
ARSCParser(bytes) / .from_file(path) Parse resources.arsc
.resolve_id(id), .id_to_string_value() Resource lookup
ARSCParser.parse_id("@…") Parse @DEADBEEF / @pkg:DEADBEEF
decode_axml(path) Convenience → (xml, meta_dict)
encode_xml(xml_bytes) Encode plain XML → binary AXML

Testing

cargo test

Python smoke check (with venv + maturin install):

python -c "from axml_parser import AXMLPrinter; print(AXMLPrinter.from_file('tests/AXML/AndroidManifest.xml').package)"
# org.t0t0.androguard.TC

License

Apache-2.0 (same as androguard/axml).

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages