Exemple #1
0
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))
Exemple #2
0
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()
Exemple #3
0
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
Exemple #4
0
    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()
Exemple #5
0
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