def Test(ctx): assert isinstance(ctx, IClientContext) input_path = r"D:\tmp\2\project\about_dex_diff\code\xmly\libFace3D.so" unit = ctx.open(input_path) assert isinstance(unit, IUnit) prj = ctx.getMainProject() assert isinstance(prj, IRuntimeProject) # 获取INativeCodeUnit并执行解析 nativeCodeUnit = prj.findUnit(INativeCodeUnit) assert isinstance(nativeCodeUnit, INativeCodeUnit) bool = nativeCodeUnit.process() # 获取INativeDecompilerUnit并执行解析 nativeDecompilerUnit = DecompilerHelper.getDecompiler(nativeCodeUnit) assert isinstance(nativeDecompilerUnit, INativeDecompilerUnit) bool = nativeDecompilerUnit.process() # 获取函数对应顶层ICElement nativeSourceUnit = nativeDecompilerUnit.decompile("sub_11110") assert isinstance(nativeSourceUnit, INativeSourceUnit) rootElement = nativeSourceUnit.getRootElement() # print rootElement # 输出 displayTree(rootElement, 0)
def detect_first_getters(unit, fields): getters = {} decompiler = DecompilerHelper.getDecompiler(unit) for flag_name, field in fields.iteritems(): sig = field.getSignature(False) for xref in xrefs_for(unit, field): method = unit.getMethod(xref) if method.data and method.data.codeItem and \ method.data.codeItem.instructions and method.data.codeItem.instructions.size() <= 20: decompiled_method = decompile_dex_method( decompiler, method) if not decompiled_method or decompiled_method.body.size( ) != 1: continue statement = decompiled_method.body.get(0) if isinstance(statement, IJavaReturn): last_call = extract_last_function_call( statement.expression) if last_call and len(last_call.arguments) == 1: src = last_call.getArgument(0) if isinstance(src, IJavaStaticField ) and src.field.signature == sig: new_name = method.getName( False) + "_" + flag_name if new_name != method.getName(True): method.name = new_name getters[flag_name] = method return getters
def decompileCodeUnit(self, codeUnit): # make sure the code unit is processed if not codeUnit.isProcessed(): if not codeUnit.process(): print('The code unit cannot be processed!') return decomp = DecompilerHelper.getDecompiler(codeUnit) if not decomp: print('There is no decompiler available for code unit %s' % codeUnit) return outdir = os.path.join(self.outputDir, codeUnit.getName() + '_decompiled') print('Output folder: %s' % outdir) if isinstance(codeUnit, INativeCodeUnit): for m in codeUnit.getMethods(): a = m.getAddress() print('Decompiling: %s' % a) srcUnit = decomp.decompile(a) if srcUnit: self.exportSourceUnit(srcUnit, outdir) else: allClasses = codeUnit.getClasses() for c in allClasses: # do not decompile inner classes if (c.getGenericFlags() & ICodeItem.FLAG_INNER) == 0: a = c.getAddress() print('Decompiling: %s' % a) srcUnit = decomp.decompile(a) if srcUnit: self.exportSourceUnit(srcUnit, outdir)
def detect_second_getters(unit, getters): secondary_getters = {} decompiler = DecompilerHelper.getDecompiler(unit) for flag_name, getter_method in getters.iteritems(): sig = getter_method.getSignature(False).split(';->')[1] for xref in xrefs_for(unit, getter_method): method = unit.getMethod(xref) if method.getSignature(False) == sig: continue if method.data and method.data.codeItem and \ method.data.codeItem.instructions and method.data.codeItem.instructions.size() <= 20: decompiled_method = decompile_dex_method( decompiler, method) if not decompiled_method or decompiled_method.body.size( ) != 1: continue statement = decompiled_method.body.get(0) if isinstance(statement, IJavaReturn): last_call = extract_last_function_call( statement.expression) if last_call and len(last_call.arguments) <= 1: if last_call.methodSignature.split( ';->')[1] == sig: new_name = method.getName( False) + "_" + flag_name if new_name != method.getName(True): method.name = new_name secondary_getters[flag_name] = method return secondary_getters
def decompileForCodeUnit(self, codeUnit): decomp = DecompilerHelper.getDecompiler(codeUnit) if not decomp: print('There is no decompiler available for code unit %s' % codeUnit) return outdir = os.path.join(self.outputDir, codeUnit.getName() + '_decompiled') print('Output folder: %s' % outdir) if isinstance(codeUnit, INativeCodeUnit): methods = codeUnit.getMethods() for m in methods: a = m.getAddress() srcUnit = decomp.decompile(a) if srcUnit: self.exportSourceUnit(srcUnit, outdir) else: allClasses = codeUnit.getClasses() for c in allClasses: # do not decompile inner classes if (c.getGenericFlags() & ICodeItem.FLAG_INNER) == 0: a = c.getAddress() srcUnit = decomp.decompile(a) if srcUnit: self.exportSourceUnit(srcUnit, outdir)
def tryDetermineGoodName(self, clzElement): decomp = DecompilerHelper.getDecompiler(self.targetUnit) javaunit = decomp.decompile(clzElement.getAddress()) clzElement = javaunit.getClassElement() if not isFuckingName(clzElement.getName()): return clzElement.getName() ssupers = clzElement.getImplementedInterfaces() supers = [] supers.extend(ssupers) # do not directly append on returned list! superSig = clzElement.getSupertype().getSignature() supers.append(clzElement.getSupertype()) for superItem in supers: sig = superItem.getSignature() if sig == "Ljava/lang/Object;": continue if not isFuckingName(sig): return sig resolvedType = self.targetUnit.getClass(sig) if resolvedType: # this is a concret class guessedName = self.tryDetermineGoodName(resolvedType) if guessedName: return guessedName else: # this is a SDK class return sig return None
def run(self, ctx): # retrieve JEB's engines from the provided IClientContext engctx = ctx.getEnginesContext() if not engctx: print('Back-end engines not initialized') return # retrieve the current project (must exist) projects = engctx.getProjects() if projects: project = projects[0] else: argv = ctx.getArguments() if len(argv) < 1: print('No project found, please provide an input contract file') return self.inputFile = argv[0] print('Processing ' + self.inputFile + '...') # create a project project = engctx.loadProject('Project') # load and process the artifact artifact = Artifact('Artifact', FileInput(File(self.inputFile))) project.processArtifact(artifact) project = engctx.getProjects()[0] # retrieve the primary code unit (must be the result of an EVM contract analysis) units = RuntimeProjectUtil.findUnitsByType(project, INativeCodeUnit, False) if not units: print('No native code unit found') return unit = units[0] print('Native code unit: %s' % unit) # GlobalAnalysis is assumed to be on (default) decomp = DecompilerHelper.getDecompiler(unit) if not decomp: print('No decompiler unit found') return # retrieve a handle on the method we wish to examine method = unit.getInternalMethods().get(0)#('sub_1001929') src = decomp.decompile(method.getName(True)) if not src: print('Routine was not decompiled') return print(src) decompTargets = src.getDecompilationTargets() print(decompTargets) decompTarget = decompTargets.get(0) ircfg = decompTarget.getContext().getCfg() # CFG object reference, see package com.pnfsoftware.jeb.core.units.code.asm.cfg print("+++ IR-CFG for %s +++" % method) print(ircfg.formatSimple())
def decompileForCodeUnit(self, codeUnit): decomp = DecompilerHelper.getDecompiler(codeUnit) allClasses = codeUnit.getClasses() if allClasses == None: return for c in allClasses: # do not decompile inner classes if (c.getGenericFlags() & ICodeItem.FLAG_INNER) == 0: a = c.getAddress() srcUnit = decomp.decompile(a)
def Test(ctx): assert isinstance(ctx,IClientContext) input_path = r"D:\tmp\2\project\about_dex_diff\code\jsq\jsq.dex" sign = "Lcom/BestCalculatorCN/MyCalculator;->m(Lcom/BestCalculatorCN/MyCalculator;)Z" unit = ctx.open(input_path); assert isinstance(unit,IUnit) prj = ctx.getMainProject(); assert isinstance(prj,IRuntimeProject) dexUnit = prj.findUnit(IDexUnit); assert isinstance(dexUnit,IDexUnit) # 发现使用DecompilationContext时,才能出现javablock,不然block为0,没有进行解析 dexDecompilerUnit = DecompilerHelper.getDecompiler(dexUnit); assert isinstance(dexDecompilerUnit,IDexDecompilerUnit) opt = DecompilationOptions.Builder().newInstance().flags(IDecompilerUnit.FLAG_NO_DEFERRED_DECOMPILATION).build() bool = dexDecompilerUnit.decompileAllClasses(DecompilationContext(opt)) print(bool) javaMethod = dexDecompilerUnit.getMethod(sign,False); assert isinstance(javaMethod,IJavaMethod) displayTree(javaMethod)
def decompileCodeUnit(self, codeUnit): # make sure the code unit is processed if not codeUnit.isProcessed(): if not codeUnit.process(): print('The code unit cannot be processed!') return decomp = DecompilerHelper.getDecompiler(codeUnit) if not decomp: print('There is no decompiler available for code unit %s' % codeUnit) return outdir = os.path.join(self.outputDir, codeUnit.getName() + '_decompiled') print('Output folder: %s' % outdir ) # created only if necessary, i.e. some contents was exported if not ( (isinstance(codeUnit, INativeCodeUnit) and self.decompileNative) or (isinstance(codeUnit, IDexUnit) and self.decompileDex)): print('Skipping code unit: %s' % UnitUtil.buildFullyQualifiedUnitPath(codeUnit)) return # DecompilerExporter object exp = decomp.getExporter() exp.setOutputFolder(IO.createFolder(outdir)) # limit to 1 minute max per method exp.setMethodTimeout(1 * 60000) # limit to 15 minutes (total) exp.setTotalTimeout(15 * 60000) # set a callback to output real-time information about what's being decompiled class DecompCallback(ProgressCallbackAdapter): def message(self, msg): print('%d/%d: %s' % (self.getCurrent(), self.getTotal(), msg)) exp.setCallback(DecompCallback()) # decompile & export if not exp.export(): cnt = len(exp.getErrors()) i = 1 for sig, err in exp.getErrors().items(): print('%d/%d DECOMPILATION ERROR: METHOD %s: %s' % (i, cnt, sig, err)) i += 1
def decompileCodeUnit(self, codeUnit): # make sure the code unit is processed if not codeUnit.isProcessed(): if not codeUnit.process(): print('The code unit cannot be processed!') return decomp = DecompilerHelper.getDecompiler(codeUnit) if not decomp: print('There is no decompiler available for code unit %s' % codeUnit) return outdir = os.path.join(self.outputDir, codeUnit.getName() + '_decompiled') print('Output folder: %s' % outdir) if self.decompileNative and isinstance(codeUnit, INativeCodeUnit): for m in codeUnit.getMethods(): a = m.getAddress() print('Decompiling: %s' % a) srcUnit = decomp.decompile(a) if srcUnit: self.exportSourceUnit(srcUnit, outdir) elif self.decompileDex and isinstance(codeUnit, IDexUnit): exp = DexDecompilerExporter(decomp) exp.setOutputFolder(IO.createFolder(outdir)) # limit to 1 minute max per method exp.setMethodTimeout(1 * 60000) # limit to 15 minutes (total) exp.setTotalTimeout(15 * 60000) # set a callback to output real-time information about what's being decompiled from com.pnfsoftware.jeb.util.base import ProgressCallbackAdapter class DecompCallback(ProgressCallbackAdapter): def message(__self__, msg): print(msg) exp.setCallback(DecompCallback()) # decompile & export if not exp.export(): cnt = len(exp.getErrors()) i = 1 for sig, err in exp.getErrors().items(): print('%d/%d DECOMPILATION ERROR: METHOD %s: %s' % (i, cnt, sig, err)) i += 1
def run(self, ctx): # retrieve the current project or create one and load the input file prj = ctx.getMainProject() if not prj: argv = ctx.getArguments() if len(argv) < 1: print('No project found, please provide an input binary') return self.inputFile = argv[0] print('Processing ' + self.inputFile + '...') ctx.open(self.inputFile) prj.getMainProject() # retrieve the primary code unit (must be the result of an EVM contract analysis) unit = prj.findUnit(INativeCodeUnit) if not unit: print('No native code unit found') return print('Native code unit: %s' % unit) # GlobalAnalysis is assumed to be on (default) decomp = DecompilerHelper.getDecompiler(unit) if not decomp: print('No decompiler unit found') return # retrieve a handle on the method we wish to examine method = unit.getInternalMethods().get(0) ctx = DecompilationContext(IDecompilerUnit.FLAG_KEEP_IR) decm = decomp.decompile(method, ctx) if not decm: print('Routine was not decompiled') return # IDecompiledMethod print(decm) ircfg = decm.getIRContext().getCfg() # CFG object reference, see package com.pnfsoftware.jeb.core.units.code.asm.cfg print("+++ IR-CFG for %s +++" % method) print(ircfg.format())
def run(self, ctx): self.ctx = ctx f = ctx.getFocusedFragment() if not f: print( 'Set the focus on a UI fragment, and position the caret somewhere in the method you would like to decompile.' ) return addr = f.getActiveAddress() unit = f.getUnit() if not isinstance(unit, ICodeUnit): print('Not a code unit: %s' % unit) return m = unit.getMethod(addr) if not m: print('Not a method at address: %s' % addr) return decomp = DecompilerHelper.getDecompiler(unit) if not decomp: print('Cannot acquire decompiler for unit: %s' % decomp) return # *** decompilation Options and Context are optional *** # here, we're creating an Options object to: # - override the decompiler settings (if any), and cap method decompilation to 30 seconds # - prevent the decompilation of inner classes or any deferred decompilations: we decompile the target and only the target opt = DecompilationOptions.Builder.newInstance().flags( IDecompilerUnit.FLAG_NO_INNER_DECOMPILATION | IDecompilerUnit.FLAG_NO_DEFERRED_DECOMPILATION).maxTimePerMethod( 30000).build() if not decomp.decompileMethod(m.getSignature(), DecompilationContext(opt)): print('Failed decompiling method') return text = decomp.getDecompiledMethodText(m.getSignature()) #print(text) r = ctx.displayText("Decompiled Method: %s" % m.getName(), text, True)
def detect_fields(unit, init_methods): using_methods = set() for method in init_methods: for xref in xrefs_for(unit, method): using_methods.add(unit.getMethod(xref)) signatures = {method.getSignature(False) for method in init_methods} decompiler = DecompilerHelper.getDecompiler(unit) fields = {} for method in using_methods: cls = method.classType.implementingClass decompiled_method = decompile_dex_method(decompiler, method) if not decompiled_method: continue def handle_non_compound(statement): if isinstance(statement, IJavaAssignment): left, right = statement.left, statement.right if isinstance(right, IJavaCall): if right.method.signature in signatures: name_element = right.getArgument(1) if isinstance( name_element, IJavaConstant) and name_element.isString(): name = name_element.getString() str_name = name.replace(":", "_") if isinstance(left, IJavaStaticField): field = left.field dex_field = cls.getField( False, field.name, field.type.signature) new_name = dex_field.getName( False) + "_" + str_name if new_name != dex_field.getName(True): dex_field.name = new_name fields[str_name] = dex_field AstTraversal(handle_non_compound).traverse_block( decompiled_method.body) return fields
def Test(ctx): assert isinstance(ctx, IClientContext) input_path = r"D:\tmp\2\project\about_dex_diff\code\jsq\jsq.dex" sign = "Lnet/cavas/show/aa;" unit = ctx.open(input_path) assert isinstance(unit, IUnit) prj = ctx.getMainProject() assert isinstance(prj, IRuntimeProject) dexUnit = prj.findUnit(IDexUnit) assert isinstance(dexUnit, IDexUnit) dexDecompilerUnit = DecompilerHelper.getDecompiler(dexUnit) assert isinstance(dexDecompilerUnit, IDexDecompilerUnit) opt = DecompilationOptions.Builder().newInstance().flags( IDecompilerUnit.FLAG_NO_DEFERRED_DECOMPILATION).build() bool = dexDecompilerUnit.decompileAllClasses(DecompilationContext(opt)) text = dexDecompilerUnit.getDecompiledClassText(sign) print("-------------------------------------") print text print("-------------------------------------")
def Test(ctx): assert isinstance(ctx, IClientContext) input_path = r"D:\tmp\2\project\about_dex_diff\code\jsq\jsq.dex" sign = "Lnet/cavas/show/bl;->handleMessage(Landroid/os/Message;)V" unit = ctx.open(input_path) assert isinstance(unit, IUnit) prj = ctx.getMainProject() assert isinstance(prj, IRuntimeProject) dexUnit = prj.findUnit(IDexUnit) assert isinstance(dexUnit, IDexUnit) dexDecompilerUnit = DecompilerHelper.getDecompiler(dexUnit) assert isinstance(dexDecompilerUnit, IDexDecompilerUnit) opt = DecompilationOptions.Builder().newInstance().flags( IDecompilerUnit.FLAG_NO_DEFERRED_DECOMPILATION).build() bool = dexDecompilerUnit.decompileAllClasses(DecompilationContext(opt)) print(bool) javaMethod = dexDecompilerUnit.getMethod(sign, False) assert isinstance(javaMethod, IJavaMethod) print("---------------- tree ----------------") displayTree(javaMethod)
def getDecompiledMethod(self, dex, msig): m = dex.getMethod(msig) if not m: return None c = m.getClassType() if not c: return None decomp = DecompilerHelper.getDecompiler(dex) if not decomp: return None csig = c.getSignature(False) javaUnit = decomp.decompile(csig) if not javaUnit: return None msig0 = m.getSignature(False) for m in javaUnit.getClassElement().getMethods(): if m.getSignature() == msig0: return m return None
def get_decompiled_method(dex, msig): m = dex.getMethod(msig) if not m: return None c = m.getClassType() if not c: return None decompiled = DecompilerHelper.getDecompiler(dex) if not decompiled: return None class_sig = c.getSignature(False) java_unit = decompiled.decompile(class_sig) if not java_unit: return None method_sig_0 = m.getSignature(False) for m in java_unit.getClassElement().getMethods(): if m.getSignature() == method_sig_0: return m return None
def run(self, ctx): # retrieve JEB's engines from the provided IClientContext engctx = ctx.getEnginesContext() if not engctx: print('Back-end engines not initialized') return # retrieve the current project (must exist) projects = engctx.getProjects() if projects: project = projects[0] else: argv = ctx.getArguments() if len(argv) < 1: print( 'No project found, please provide an input contract file') return self.inputFile = argv[0] print('Processing ' + self.inputFile + '...') # create a project project = engctx.loadProject('Project') # load and process the artifact artifact = Artifact('Artifact', FileInput(File(self.inputFile))) project.processArtifact(artifact) project = engctx.getProjects()[0] # retrieve the primary code unit (must be the result of an EVM contract analysis) units = RuntimeProjectUtil.findUnitsByType(project, INativeCodeUnit, False) if not units: print('No native code unit found') return unit = units[0] print('Native code unit: %s' % unit) # GlobalAnalysis is assumed to be on (default) decomp = DecompilerHelper.getDecompiler(unit) if not decomp: print('No decompiler unit found') return # retrieve a handle on the method we wish to examine method = unit.getInternalMethods().get(0) #('sub_1001929') src = decomp.decompile(method.getName(True)) if not src: print('Routine was not decompiled') return print(src) decompTargets = src.getDecompilationTargets() print(decompTargets) decompTarget = decompTargets.get(0) ircfg = decompTarget.getContext().getCfg() # CFG object reference, see package com.pnfsoftware.jeb.core.units.code.asm.cfg print("+++ IR-CFG for %s +++" % method) print(ircfg.formatSimple())
def run(self, ctx): # retrieve JEB's engines from the provided IClientContext engctx = ctx.getEnginesContext() if not engctx: print('Back-end engines not initialized') return # retrieve the current project (must exist) projects = engctx.getProjects() if projects: project = projects[0] else: argv = ctx.getArguments() if len(argv) < 1: print('No project found, please provide an input contract file') return self.inputFile = argv[0] print('Processing ' + self.inputFile + '...') if not self.inputFile.endswith('.evm-bytecode'): print('Warning: it is recommended your contract file has the evm-bytecode extension in order to guarantee processing by the EVM modules') # create a project project = engctx.loadProject('EVMProject') # load and process the artifact artifact = Artifact('EVMArtifact', FileInput(File(self.inputFile))) project.processArtifact(artifact) project = engctx.getProjects()[0] # retrieve the primary code unit (must be the result of an EVM contract analysis) units = RuntimeProjectUtil.findUnitsByType(project, INativeCodeUnit, False) if not units: print('No native code unit found') return unit = units[0] print('EVM unit: %s' % unit) # GlobalAnalysis is assumed to be on: the contract is already decompiled # we retrieve a handle on the EVM decompiler ... decomp = DecompilerHelper.getDecompiler(unit) if not decomp: print('No decompiler unit found') return # ... and retrieve a handle on the decompiled contract's INativeSourceUnit src = decomp.decompile("DecompiledContract") print(src) #targets = src.getDecompilationTargets() #print(targets) # let's get the contract's AST astDecompClass = src.getRootElement() # the commented line below will output the entire decompiled source code #print(astDecompClass) # here, we walk the AST tree and print the type of each element in the tree print("*** AST of contract") self.displayASTTree(astDecompClass) # now, let's retrieve the individual methods implemented in the contract methods = unit.getInternalMethods() for method in methods: # retrieve the INativeSourceUnit of the method r = decomp.decompileMethod(method) print("*** AST for method: %s" % method.getName(True)) self.displayASTTree(r.getRootElement()) # list of INativeDecompilationTarget for a decompiled method decompTargets = r.getDecompilationTargets() if decompTargets: # get the first (generally, only) target object decompTarget = decompTargets.get(0) # an INativeDecompilationTarget object aggregates many useful objects resulting from the decompilation of a method # here, we retrieve the most refined CFG of the Intermediate Representation for the method ircfg = decompTarget.getContext().getCfg() # CFG object reference, see package com.pnfsoftware.jeb.core.units.code.asm.cfg print("++++ IR-CFG for method: %s" % method.getName(True)) print(ircfg.formatSimple()) # end of demo, we have enough with one method, uncomment to print out the AST and IR of all methods break
def run(self, ctx): prj = ctx.getMainProject() if not prj: argv = ctx.getArguments() if len(argv) < 1: print('Please provide an input contract file') return self.inputFile = argv[0] print('Processing ' + self.inputFile + '...') if not self.inputFile.endswith('.evm-bytecode'): print( 'Warning: it is recommended your contract file has the evm-bytecode extension in order to guarantee processing by the EVM modules' ) ctx.open(self.inputFile) prj = ctx.getMainProject() # retrieve the primary code unit (must be the result of an EVM contract analysis) unit = prj.findUnit(INativeCodeUnit) print('EVM unit: %s' % unit) # GlobalAnalysis is assumed to be on: the contract is already decompiled # we retrieve a handle on the EVM decompiler ... decomp = DecompilerHelper.getDecompiler(unit) if not decomp: print('No decompiler unit found') return # ... and retrieve a handle on the decompiled contract's INativeSourceUnit src = decomp.decompile("DecompiledContract") print(src) #targets = src.getDecompilationTargets() #print(targets) # let's get the contract's AST astDecompClass = src.getRootElement() # the commented line below will output the entire decompiled source code #print(astDecompClass) # here, we walk the AST tree and print the type of each element in the tree print("*** AST of contract") self.displayASTTree(astDecompClass) # now, let's retrieve the individual methods implemented in the contract methods = unit.getInternalMethods() for method in methods: # retrieve the INativeSourceUnit of the method r = decomp.decompileMethod(method) print("*** AST for method: %s" % method.getName(True)) self.displayASTTree(r.getRootElement()) # list of INativeDecompilationTarget for a decompiled method decompTargets = r.getDecompilationTargets() if decompTargets: # get the first (generally, only) target object decompTarget = decompTargets.get(0) # an INativeDecompilationTarget object aggregates many useful objects resulting from the decompilation of a method # here, we retrieve the most refined CFG of the Intermediate Representation for the method ircfg = decompTarget.getContext().getCfg() # CFG object reference, see package com.pnfsoftware.jeb.core.units.code.asm.cfg print("++++ IR-CFG for method: %s" % method.getName(True)) print(ircfg.formatSimple()) # end of demo, we have enough with one method, uncomment to print out the AST and IR of all methods break