ASTDecryptStrings.py
# JEB script - demo AST API # Decrypt and replace strings # See www.android-decompiler.com/blog import sys import os import time from jeb.api import IScript from jeb.api import EngineOption from jeb.api.ui import View from jeb.api.dex import Dex from jeb.api.ast import Class, Field, Method, Call, Constant, StaticField, NewArray class ASTDecryptStrings(IScript): def run(self, jeb): self.jeb = jeb self.dex = self.jeb.getDex() self.cstbuilder = Constant.Builder(jeb) self.csig = 'MainActivity' self.encbytes = [] self.mname_decrypt = None # the encryption keys could be determined by analyzing the decryption method self.keys = [409, 62, -8] r = jeb.decompileClass(self.csig) if not r: print 'Could not find class "%s"' % csig return c = jeb.getDecompiledClassTree(self.csig) wanted_flags = Dex.ACC_PRIVATE|Dex.ACC_STATIC|Dex.ACC_FINAL for f in c.getFields(): fsig = f.getSignature() if fsig.endswith(':[B'): fd = self.dex.getFieldData(fsig) if fd.getAccessFlags() & wanted_flags == wanted_flags: print 'Found field:', fsig findex = fd.getFieldIndex() for mindex in self.dex.getFieldReferences(findex): mname = self.dex.getMethod(mindex).getName(False) if mname != '': self.mname_decrypt = mname for m2 in c.getMethods(): if m2.getName() == ' ': s0 = m2.getBody().get(0) if isinstance(s0.getLeft(), StaticField) and s0.getLeft().getField().getSignature() == f.getSignature(): array = s0.getRight() if isinstance(array, NewArray): for v in array .getInitialValues(): self.encbytes.append(v.getByte()) break break if len(self.encbytes) == 0: print 'Encrypted strings byte array not found' return if not self.mname_decrypt: print 'Decryption method was not found' return for m in c.getMethods(): print 'Decrypting strings in method: %s' % m.getName() self.decryptMethodStrings(m) def decryptMethodStrings(self, m): block = m.getBody() i = 0 while i < block.size(): stm = block.get(i) self.checkElement(block, stm) i += 1 def checkElement(self, parent, e): if isinstance(e, Call): mname = e.getMethod().getName() if mname == self.mname_decrypt: v = [] for arg in e.getArguments(): if isinstance(arg, Constant): v.append(arg.getInt()) if len(v) == 3: decrypted_string = self.decrypt(v[0], v[1], v[2]) parent.replaceSubElement(e, self.cstbuilder.buildString(decrypted_string)) print ' Decrypted string: %s' % repr(decrypted_string) for subelt in e.getSubElements(): if isinstance(subelt, Class) or isinstance(subelt, Field) or isinstance(subelt, Method): continue self.checkElement(e, subelt) def decrypt(self, length, curChar, pos): length += self.keys[0] curChar += self.keys[1] r = '' for i in range(length): r += chr(curChar & 0xFF) if pos >= len(self.encbytes): break curEncodedChar = self.encbytes[pos] pos += 1 curChar = curChar + curEncodedChar + self.keys[2] return r