def RunDecompiler(d, dx, decompiler_name): """ Run the decompiler on a specific analysis :param d: the DalvikVMFormat object :type d: :class:`DalvikVMFormat` object :param dx: the analysis of the format :type dx: :class:`VMAnalysis` object :param decompiler: the type of decompiler to use ("dad", "dex2jad", "ded") :type decompiler: string """ if decompiler_name is not None: log.debug("Decompiler ...") decompiler_name = decompiler_name.lower() # TODO put this into the configuration object and make it more dynamic # e.g. detect new decompilers and so on... if decompiler_name == "dex2jad": d.set_decompiler( decompiler.DecompilerDex2Jad(d, androconf.CONF["BIN_DEX2JAR"], androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_name == "dex2fernflower": d.set_decompiler( decompiler.DecompilerDex2Fernflower( d, androconf.CONF["BIN_DEX2JAR"], androconf.CONF["BIN_FERNFLOWER"], androconf.CONF["OPTIONS_FERNFLOWER"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_name == "ded": d.set_decompiler( decompiler.DecompilerDed(d, androconf.CONF["BIN_DED"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_name == "jadx": d.set_decompiler( decompiler.DecompilerJADX(d, dx, jadx=androconf.CONF["BIN_JADX"])) else: d.set_decompiler(decompiler.DecompilerDAD(d, dx))
def export_apps_to_format(filename, s, output, methods_filter=None, jar=None, decompiler_type=None, form=None): from androguard.misc import clean_file_name from androguard.core.bytecodes import dvm from androguard.core.bytecode import method2dot, method2format from androguard.decompiler import decompiler print("Dump information {} in {}".format(filename, output)) if not os.path.exists(output): print("Create directory %s" % output) os.makedirs(output) else: print("Clean directory %s" % output) androconf.rrmdir(output) os.makedirs(output) methods_filter_expr = None if methods_filter: methods_filter_expr = re.compile(methods_filter) dump_classes = [] for _, vm, vmx in s.get_objects_dex(): print("Decompilation ...", end=' ') sys.stdout.flush() if decompiler_type == "dex2jad": vm.set_decompiler(decompiler.DecompilerDex2Jad(vm, androconf.CONF["BIN_DEX2JAR"], androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_type == "dex2winejad": vm.set_decompiler(decompiler.DecompilerDex2WineJad(vm, androconf.CONF["BIN_DEX2JAR"], androconf.CONF["BIN_WINEJAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_type == "ded": vm.set_decompiler(decompiler.DecompilerDed(vm, androconf.CONF["BIN_DED"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_type == "dex2fernflower": vm.set_decompiler(decompiler.DecompilerDex2Fernflower(vm, androconf.CONF["BIN_DEX2JAR"], androconf.CONF["BIN_FERNFLOWER"], androconf.CONF["OPTIONS_FERNFLOWER"], androconf.CONF["TMP_DIRECTORY"])) print("End") if jar: print("jar ...", end=' ') filenamejar = decompiler.Dex2Jar(vm, androconf.CONF["BIN_DEX2JAR"], androconf.CONF["TMP_DIRECTORY"]).get_jar() shutil.move(filenamejar, os.path.join(output, "classes.jar")) print("End") for method in vm.get_methods(): if methods_filter_expr: msig = "{}{}{}".format(method.get_class_name(), method.get_name(), method.get_descriptor()) if not methods_filter_expr.search(msig): continue # Current Folder to write to filename_class = valid_class_name(str(method.get_class_name())) filename_class = os.path.join(output, filename_class) create_directory(filename_class) print("Dump {} {} {} ...".format(method.get_class_name(), method.get_name(), method.get_descriptor()), end=' ') filename = clean_file_name(os.path.join(filename_class, method.get_short_string())) buff = method2dot(vmx.get_method(method)) # Write Graph of method if form: print("%s ..." % form, end=' ') method2format(filename + "." + form, form, None, buff) # Write the Java file for the whole class if str(method.get_class_name()) not in dump_classes: print("source codes ...", end=' ') current_class = vm.get_class(method.get_class_name()) current_filename_class = valid_class_name(str(current_class.get_name())) current_filename_class = os.path.join(output, current_filename_class + ".java") with open(current_filename_class, "w") as fd: fd.write(current_class.get_source()) dump_classes.append(method.get_class_name()) # Write SMALI like code print("bytecodes ...", end=' ') bytecode_buff = dvm.get_bytecodes_method(vm, vmx, method) with open(filename + ".ag", "w") as fd: fd.write(bytecode_buff) print()
def export_apps_to_format(filename, a, output, methods_filter=None, jar=None, decompiler_type=None, format=None): print "Dump information %s in %s" % (filename, output) if not os.path.exists(output): print "Create directory %s" % output os.makedirs(output) else: print "Clean directory %s" % output androconf.rrmdir(output) os.makedirs(output) methods_filter_expr = None if methods_filter: methods_filter_expr = re.compile(methods_filter) output_name = output if output_name[-1] != "/": output_name = output_name + "/" dump_classes = [] for vm in a.get_vms(): print "Analysis ...", sys.stdout.flush() vmx = analysis.VMAnalysis(vm) print "End" print "Decompilation ...", sys.stdout.flush() if not decompiler_type: vm.set_decompiler(decompiler.DecompilerDAD(vm, vmx)) elif decompiler_type == "dex2jad": vm.set_decompiler( decompiler.DecompilerDex2Jad(vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_JAD"], androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_type == "dex2winejad": vm.set_decompiler( decompiler.DecompilerDex2WineJad( vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_JAD"], androconf.CONF["BIN_WINEJAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_type == "ded": vm.set_decompiler( decompiler.DecompilerDed(vm, androconf.CONF["PATH_DED"], androconf.CONF["BIN_DED"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_type == "dex2fernflower": vm.set_decompiler( decompiler.DecompilerDex2Fernflower( vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_FERNFLOWER"], androconf.CONF["BIN_FERNFLOWER"], androconf.CONF["OPTIONS_FERNFLOWER"], androconf.CONF["TMP_DIRECTORY"])) else: raise ("invalid decompiler !") print "End" if options.jar: print "jar ...", filenamejar = decompiler.Dex2Jar( vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["TMP_DIRECTORY"]).get_jar() shutil.move(filenamejar, output + "classes.jar") print "End" for method in vm.get_methods(): if methods_filter_expr: msig = "%s%s%s" % (method.get_class_name(), method.get_name(), method.get_descriptor()) if not methods_filter_expr.search(msig): continue filename_class = valid_class_name(method.get_class_name()) create_directory(filename_class, output) print "Dump %s %s %s ..." % (method.get_class_name(), method.get_name(), method.get_descriptor()), filename_class = output_name + filename_class if filename_class[-1] != "/": filename_class = filename_class + "/" descriptor = method.get_descriptor() descriptor = descriptor.replace(";", "") descriptor = descriptor.replace(" ", "") descriptor = descriptor.replace("(", "-") descriptor = descriptor.replace(")", "-") descriptor = descriptor.replace("/", "_") filename = filename_class + method.get_name() + descriptor if len(method.get_name() + descriptor) > 250: all_identical_name_methods = vm.get_methods_descriptor( method.get_class_name(), method.get_name()) pos = 0 for i in all_identical_name_methods: if i.get_descriptor() == method.get_descriptor(): break pos += 1 filename = filename_class + method.get_name() + "_%d" % pos buff = method2dot(vmx.get_method(method)) if format: print "%s ..." % format, method2format(filename + "." + format, format, None, buff) if method.get_class_name() not in dump_classes: print "source codes ...", current_class = vm.get_class(method.get_class_name()) current_filename_class = valid_class_name( current_class.get_name()) create_directory(filename_class, output) current_filename_class = output_name + current_filename_class + ".java" fd = open(current_filename_class, "w") fd.write(current_class.get_source()) fd.close() dump_classes.append(method.get_class_name()) print "bytecodes ...", bytecode_buff = dvm.get_bytecodes_method(vm, vmx, method) fd = open(filename + ".ag", "w") fd.write(bytecode_buff) fd.close() print
def run(self): if androconf.is_android_raw(self.raw) == "DEY": dex_object = dvm.DalvikOdexVMFormat(self.raw) else: dex_object = dvm.DalvikVMFormat(self.raw) ana_object = analysis.uVMAnalysis(dex_object) gvm_object = ganalysis.GVMAnalysis(ana_object, None) dex_object.set_vmanalysis(ana_object) dex_object.set_gvmanalysis(gvm_object) for i in androconf.CONF: if is_setting(i): androconf.CONF[i] = get_setting(i) decompiler_option = get_setting("DEFAULT_DECOMPILER", "dad") if decompiler_option == "dex2jad": dex_object.set_decompiler( decompiler.DecompilerDex2Jad(dex_object, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_JAD"], androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_option == "ded": dex_object.set_decompiler( decompiler.DecompilerDed(dex_object, androconf.CONF["PATH_DED"], androconf.CONF["BIN_DED"], androconf.CONF["TMP_DIRECTORY"])) else: dex_object.set_decompiler( decompiler.DecompilerDAD(dex_object, ana_object)) dex_object.create_xref() dex_object.create_dref() self.view.set_name("%s.ag" % (self.filename)) self.view.set_scratch(True) edit = self.view.begin_edit() self.view.sel().clear() self.view.set_syntax_file("Packages/ag-st/ag.tmLanguage") by_package = {} for current_class in dex_object.get_classes(): name = current_class.get_name() try: by_package[os.path.dirname(name)].append(current_class) except KeyError: by_package[os.path.dirname(name)] = [] by_package[os.path.dirname(name)].append(current_class) b_buffer = "" line = 0 AG_METHODS_LINE[self.view.id()] = {} AG_CLASSES_LINE[self.view.id()] = {} AG_FIELDS_LINE[self.view.id()] = {} for key in sorted(by_package.iterkeys()): b_buffer += "%s\n" % key line += 1 for c_class in sorted(by_package[key], key=lambda k: k.get_name()): b_buffer += "\t%s extends %s\n" % (c_class.get_name( )[1:-1], c_class.get_superclassname()[1:-1]) AG_CLASSES_LINE[self.view.id()][line] = c_class line += 1 for j in c_class.get_methods(): b_buffer += "\t\tmethod: %s %s [%s] size:%d\n" % ( j.get_name(), j.get_descriptor(), j.get_access_flags_string(), j.get_length()) AG_METHODS_LINE[self.view.id()][line] = j line += 1 b_buffer += "\n" line += 1 for j in c_class.get_fields(): b_buffer += "\t\tfield: %s %s [%s %s]" % ( j.get_name(), j.get_descriptor(), j.get_access_flags_string(), dvm.get_type(j.get_descriptor())) init_value = j.get_init_value() if init_value != None: b_buffer += " (%s)" % repr(str(init_value.get_value())) b_buffer += "\n" AG_FIELDS_LINE[self.view.id()][line] = j line += 1 b_buffer += "\n" line += 1 l = dex_object.get_classes_hierarchy() h_buffer = "" for i in l: h_buffer += i + "\n" b_buffer += h_buffer self.view.replace(edit, sublime.Region(0, self.view.size()), b_buffer) self.view.end_edit(edit) self.view.set_read_only(True) AG_DEX_VIEW[self.view.id()] = (dex_object, ana_object) FILENAMES[self.view.id()] = hashlib.sha1( dex_object.get_buff()).hexdigest()
def decompile(apkname, output): print "Dump information %s in %s" % (apkname, output) apk_vm_serial = [] a = Androguard([apkname]) decompiler_type = None if not os.path.exists(output): print "Create directory %s" % output os.makedirs(output) else: print "Clean directory %s" % output androconf.rrmdir(output) os.makedirs(output) output_dir = output if output_dir[-1] != "/": output_name = output_dir + "/" print "Output dir: %s" % output_dir for vm in a.get_vms(): vm_list = [] #vm_list = [vm, vmx] print "Analysis ...", sys.stdout.flush() vmx = analysis.VMAnalysis(vm) vm_list.append(vm) vm_list.append(vmx) print "End" print "Decompilation ...", sys.stdout.flush() if not decompiler_type: vm.set_decompiler(decompiler.DecompilerDAD(vm, vmx)) elif decompiler_type == "dex2jad": vm.set_decompiler( decompiler.DecompilerDex2Jad(vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_JAD"], androconf.CONF["BIN_JAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_type == "dex2winejad": vm.set_decompiler( decompiler.DecompilerDex2WineJad( vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_JAD"], androconf.CONF["BIN_WINEJAD"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_type == "ded": vm.set_decompiler( decompiler.DecompilerDed(vm, androconf.CONF["PATH_DED"], androconf.CONF["BIN_DED"], androconf.CONF["TMP_DIRECTORY"])) elif decompiler_type == "dex2fernflower": vm.set_decompiler( decompiler.DecompilerDex2Fernflower( vm, androconf.CONF["PATH_DEX2JAR"], androconf.CONF["BIN_DEX2JAR"], androconf.CONF["PATH_FERNFLOWER"], androconf.CONF["BIN_FERNFLOWER"], androconf.CONF["OPTIONS_FERNFLOWER"], androconf.CONF["TMP_DIRECTORY"])) else: raise ("invalid decompiler !") apk_vm_serial.append(vm_list) print "End" return apk_vm_serial