ObadDecrypt.py
# JEB script - demo AST API # Obad, Part 1: Decrypt Obad strings before performing unreflection # 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 ObadDecrypt(IScript): def run(self, jeb): self.jeb = jeb self.dex = self.jeb.getDex() self.cstbuilder = Constant.Builder(jeb) self.csig = 'Lcom/android/system/admin/OclIIOlC;' self.encbytes = [] self.mname_decrypt = None # the encryption keys could be determined by analyzing the decryption method self.keys = [33, 96, -2] # (added to 'length', added to 'curChar', delta) 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[2], v[0], v[1]) 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