1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
import os import re import random import sys
_classMap = {} _fileClassMap = {} _reservedClassSet = set() _re_className = re.compile('L[a-zA-Z_0-9/\$]+;')
def getFilenameSuffix(filename): i = filename.rfind('.') if i > 0: return filename[i:] return ''
def convertClassName(cls, sourceName): segs = cls[1:-1].split('/') baseName = segs[-1] if '$' in baseName: baseName = sourceName + '$' + baseName.split('$', 1)[1] else: baseName = sourceName segs[-1] = baseName return 'L'+ '/'.join(segs) + ';'
def getFileNameFromClass(cls, suffix = '.smali'): segs = cls[1:-1].split('/') return segs[-1] + suffix
def readClassSourceName(smalifd): smalifd.seek(0, os.SEEK_CUR) cls, source = None, None
for line in smalifd: if len(line.strip('\r\n')) == 0: break segs = line.split(' ') if segs[0] == '.class': cls = segs[-1].strip('\r\n') elif segs[0] == '.source': s = segs[-1].strip('\r\n"') return cls, source
def findClassName(smalifile): cls, source = None, None for line in open(smalifile, 'r'): if len(line.strip('\r\n')) == 0: break segs = line.split(' ') if segs[0] == '.class': cls = segs[-1].strip('\r\n') elif segs[0] == '.source': s = segs[-1].strip('\r\n"') if s.endswith('.java'): source = s[:-5] if source is not None: newCls = convertClassName(cls, source) if newCls != cls: _classMap[cls] = newCls _fileClassMap[smalifile] = cls _reservedClassSet.add(cls.lower())
def clsrepl(matchobj): cls = matchobj.group(0) if cls in _classMap: return _classMap[cls] return cls
def updateSmaliContent(smalifile): content = open(smalifile, 'rb').read() open(smalifile, 'wb').write(_re_className.sub(clsrepl, content))
def renameSmaliFile(smalifile): if smalifile in _fileClassMap: newCls = _classMap[_fileClassMap[smalifile]] newPath = os.path.join(os.path.dirname(smalifile), getFileNameFromClass(newCls)) try: os.rename(smalifile, newPath) except Exception as e: print smalifile, ' -> ', newPath print e raise e
def handleWalkError(err): print 'Error When Access ', err.filename print err
def processSmali(smali_root): smali_root = os.path.abspath(smali_root) for root, dirs, files in os.walk(smali_root, onerror=handleWalkError): if not files: continue for f in files: if f.endswith('.smali'): findClassName(os.path.join(root, f)) for k in _classMap.keys(): newCls = _classMap[k] if newCls.lower() in _reservedClassSet and '$' not in k: newCls = newCls[:-1] + '$' + k[1:-1].split('/')[-1] + ';'
while newCls.lower() in _reservedClassSet: newCls = newCls[:-1] + str(random.randint(0, 9)) + ';' _classMap[k] = newCls _reservedClassSet.add(newCls.lower())
for root, dirs, files in os.walk(smali_root, onerror=handleWalkError): if not files: continue for f in files: if f.endswith('.smali'): fpath = os.path.join(root, f) updateSmaliContent(fpath) renameSmaliFile(fpath)
if __name__ == '__main__': if len(sys.argv) == 1: print 'Please provide root directory for smali' sys.exit(2) smali_root = sys.argv[1] print 'Begine to process *.smali under ', smali_root processSmali(smali_root) print 'Done'
|