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
StatementandBlocksearching by method and field names- Simplified
StatementandBlockextraction 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
Statementinstances.super Ljava/lang/Object;would become a singleStatementinstancevalue = { LFormat31c; }would become 4Statementinstancesvalue,{,LFormat31c;,}
- Each
Statementinstance is subclassed based on its type- E.g.
FieldStatementorMethodStatement
- E.g.
- A
Statementcan have zero or moreStatementAttributesthat indicate its intent and format- E.g.
BLOCK_START,ASSIGNMENT_LHS, orNO_BREAK
- E.g.
- Multiple
Statementinstances can be joined into aBlockand nested where appropriate- A
Blockexample would be a smali method, comprised of beginning, body, and endStatementinstances
- A
- A
Statementparses 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
Statementinstances from the input lines. - A
Statementthat can be either aBlockstart or a solo line is marked with theMAYBE_BLOCK_STARTattribute - If an
EndStatementis generated, and matches a previously markedStatement, the markedStatementis switched fromMAYBE_BLOCK_STARTtoBLOCK_START. - After the first pass, any remaining
Statementinstances that are still marked withMAYBE_BLOCK_STARTare switched toSINGLE_LINE, - The second pass iterates over the flat list of
Statementinstances and groups them intoBlockinstances and nesting when appropriate based on theSINGLE_LINEandBLOCK_STARTattributes.
- The first pass builds a flat list of
- Unparsing is done in a single pass
- Each
Statementstringifies itself using its own local information - The
SmaliFileinstance uses the attributes of eachStatementto stitch lines together and indent blocks where necessary
- Each
License
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
- FasterXML
- Java
- JavaX
- OkHttp
- Smali
Metadata
Release files for smali 0.2.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| smali-0.2.5.tar.gz | 13.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| smali-0.2.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.1 kB
Release files / smali-0.2.5.tar.gz
| Download URL | smali-0.2.5.tar.gz |
|---|---|
| Size | 13.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8bf6a5ead52552748e3314af472ca139bdff6600e861aa27c334b7b12c828a0b
|
|
BLAKE2b-256 checksum How to use checksums |
4ba08cd067a054e4c2839bc2457b1736b62e22a304372b832f698122415a17c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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
|
Release files / smali-0.2.5-py3-none-any.whl
| Download URL | smali-0.2.5-py3-none-any.whl |
|---|---|
| Size | 14.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b0c7046e57e386d82cdd8893001be510165900ca93dec99773f226d9e16e85d8
|
|
BLAKE2b-256 checksum How to use checksums |
0cae3795fa8c3bef7fc76b1031644e26f692595cc20b90fbc4be815b0ba65b28
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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
|