Skip to main content

A library for parsing and unparsing smali files for programatic modification

Project description

PySmali

PySmali is a Python library for parsing and unparsing smali files for programatic modification.

It is a line (not token) based parser. Its primary goal is for parsed files to maintain 100% equality with their original forms when reconstructed.

PySmali's main usage is for smali file patching. You are able to parse, search, extract, replace, and unparse blocks of a smali file.

Parsing is based on the ANTLR files found in the JesusFreke/smali repository.

Since this is a line, and not token, based parser, there are likely to be edge cases where PySmali fails to properly parse or unparse a file. There are currently 6,846 smali files that are used in the tests folder (tests/tests.tar.xz).

If you run into a smali file that does not parse or unparse properly, please submit a new issue with the complete smali file(s) attached as a zip or gz archive.

Requirements

  • Python 3.8 or newer

Installation

pip install smali

Simple Example

import time
from smali import SmaliFile
from smali.statements import Statement

smali_file = SmaliFile.parse_file('/path/to/file.smali')

new_lines = Statement.parse_lines(f'''
# This file was modified by PySmali
# Modified: {time.ctime()}
''')

smali_file.root.extend(new_lines)

with open('/path/to/file.smali', 'w') as f:
    f.write(str(smali_file))

Status

  • [UPCOMING] v0.4.0

    • Complete parsing of body statements
  • [UPCOMING] v0.3.0

    • Statement and Block searching by method and field names
    • Simplified Statement and Block extraction and insertion
  • v0.2.5

    • Removed all dependencies and reorganized utility code
  • v0.2.4

    • Complete parsing and unparsing of non-body statements validated by current test suite

Methodology

  • The smali file is ingested on a line by line basis
  • Each line is parsed into one or more Statement instances
    • .super Ljava/lang/Object; would become a single Statement instance
    • value = { LFormat31c; } would become 4 Statement instances
      • value, {, LFormat31c;, }
  • Each Statement instance is subclassed based on its type
    • E.g. FieldStatement or MethodStatement
  • A Statement can have zero or more StatementAttributes that indicate its intent and format
    • E.g. BLOCK_START, ASSIGNMENT_LHS, or NO_BREAK
  • Multiple Statement instances can be joined into a Block and nested where appropriate
    • A Block example would be a smali method, comprised of beginning, body, and end Statement instances
  • A Statement parses its source line, split by whitespace
  • Parsing is done in two passes. This is due to the fact that the same line can be the start of a block, or a solo line depending on the existence of a matching EndStatement.
    • The first pass builds a flat list of Statement instances from the input lines.
    • A Statement that can be either a Block start or a solo line is marked with the MAYBE_BLOCK_START attribute
    • If an EndStatement is generated, and matches a previously marked Statement, the marked Statement is switched from MAYBE_BLOCK_START to BLOCK_START.
    • After the first pass, any remaining Statement instances that are still marked with MAYBE_BLOCK_START are switched to SINGLE_LINE,
    • The second pass iterates over the flat list of Statement instances and groups them into Block instances and nesting when appropriate based on the SINGLE_LINE and BLOCK_START attributes.
  • Unparsing is done in a single pass
    • Each Statement stringifies itself using its own local information
    • The SmaliFile instance uses the attributes of each Statement to stitch lines together and indent blocks where necessary

License

UNLICENSE

OSS Attribution

JesusFreke/smali by Ben Gruver

Licensed Under: Various Licenses

Tests

Smali files used as tests in the tests/tests.tar.xz archive have been obtained from the following projects:

  • Android
  • AndroidX
  • Facebook
  • FasterXML
  • Google
  • Java
  • JavaX
  • OkHttp
  • Smali

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

smali-0.2.5.tar.gz (13.8 kB view details)

Uploaded Source

Built Distribution

smali-0.2.5-py3-none-any.whl (14.3 kB view details)

Uploaded Python 3

File details

Details for the file smali-0.2.5.tar.gz.

File metadata

  • Download URL: smali-0.2.5.tar.gz
  • Upload date:
  • Size: 13.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.24.0 setuptools/49.1.3 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.9.2

File hashes

Hashes for smali-0.2.5.tar.gz
Algorithm Hash digest
SHA256 8bf6a5ead52552748e3314af472ca139bdff6600e861aa27c334b7b12c828a0b
MD5 2be5fb5b61bc5e78f54d807e0c73581e
BLAKE2b-256 4ba08cd067a054e4c2839bc2457b1736b62e22a304372b832f698122415a17c7

See more details on using hashes here.

File details

Details for the file smali-0.2.5-py3-none-any.whl.

File metadata

  • Download URL: smali-0.2.5-py3-none-any.whl
  • Upload date:
  • Size: 14.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.24.0 setuptools/49.1.3 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.9.2

File hashes

Hashes for smali-0.2.5-py3-none-any.whl
Algorithm Hash digest
SHA256 b0c7046e57e386d82cdd8893001be510165900ca93dec99773f226d9e16e85d8
MD5 75b2d788892d1e1a3c4911908a9dcedc
BLAKE2b-256 0cae3795fa8c3bef7fc76b1031644e26f692595cc20b90fbc4be815b0ba65b28

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page