Package: smali
PySmaliPySmali 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 theJesusFreke/smalirepository.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 thetestsfolder (tests/tests.tar.xz).If you run into a smali file that does not parse or unparse properly, please submit anew issuewith the complete smali file(s) attached as aziporgzarchive.RequirementsPython 3.8 or newerInstallationpipinstallsmaliSimple ExampleimporttimefromsmaliimportSmaliFilefromsmali.statementsimportStatementsmali_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)withopen('/path/to/file.smali','w')asf:f.write(str(smali_file))Status[UPCOMING] v0.4.0Complete parsing of body statements[UPCOMING] v0.3.0StatementandBlocksearching by method and field namesSimplifiedStatementandBlockextraction and insertionv0.2.5Removed all dependencies and reorganized utility codev0.2.4Complete parsing and unparsing of non-body statements validated by current test suiteMethodologyThe smali file is ingested on a line by line basisEach line is parsed into one or moreStatementinstances.super Ljava/lang/Object;would become a singleStatementinstancevalue = { LFormat31c; }would become 4Statementinstancesvalue,{,LFormat31c;,}EachStatementinstance is subclassed based on its typeE.g.FieldStatementorMethodStatementAStatementcan have zero or moreStatementAttributesthat indicate its intent and formatE.g.BLOCK_START,ASSIGNMENT_LHS, orNO_BREAKMultipleStatementinstances can be joined into aBlockand nested where appropriateABlockexample would be a smali method, comprised of beginning, body, and endStatementinstancesAStatementparses its source line, split by whitespaceParsing 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 matchingEndStatement.The first pass builds a flat list ofStatementinstances from the input lines.AStatementthat can be either aBlockstart or a solo line is marked with theMAYBE_BLOCK_STARTattributeIf anEndStatementis generated, and matches a previously markedStatement, the markedStatementis switched fromMAYBE_BLOCK_STARTtoBLOCK_START.After the first pass, any remainingStatementinstances that are still marked withMAYBE_BLOCK_STARTare switched toSINGLE_LINE,The second pass iterates over the flat list ofStatementinstances and groups them intoBlockinstances and nesting when appropriate based on theSINGLE_LINEandBLOCK_STARTattributes.Unparsing is done in a single passEachStatementstringifies itself using its own local informationTheSmaliFileinstance uses the attributes of eachStatementto stitch lines together and indent blocks where necessaryLicenseUNLICENSEOSS AttributionJesusFreke/smalibyBen GruverLicensed Under:Various LicensesTestsSmali files used as tests in thetests/tests.tar.xzarchive have been obtained from the following projects:AndroidAndroidXFacebookFasterXMLGoogleJavaJavaXOkHttpSmali