Beispiel #1
0
    def __init__(self,
                 vm,
                 bin_dex2jar="dex2jar.sh",
                 bin_jad="jad",
                 tmp_dir="/tmp/"):
        """
        Use JAD on wine

        :param vm:
        :param bin_dex2jar:
        :param bin_jad:
        :param tmp_dir:
        """
        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        cmd = Popen([bin_dex2jar, fdname],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname)

        pathclasses = fdname + "dex2jar/"
        cmd = Popen(["unzip", fdname + "_dex2jar.jar", "-d", pathclasses],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname + "_dex2jar.jar")

        for root, dirs, files in os.walk(pathclasses, followlinks=True):
            if files:
                for f in files:
                    real_filename = root
                    if real_filename[-1] != "/":
                        real_filename += "/"
                    real_filename += f

                    cmd = Popen(["wine", bin_jad, "-o", "-d",
                                     root, real_filename],
                                    stdout=PIPE,
                                    stderr=STDOUT)
                    stdout, stderr = cmd.communicate()

        for i in vm.get_classes():
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".jad"
            if os.path.isfile(fname):
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(pathclasses)
Beispiel #2
0
    def __init__(self,
                 vm,
                 bin_ded="ded.sh",
                 tmp_dir="/tmp/"):
        """
        DED is an old, probably deprecated, decompiler
        http://siis.cse.psu.edu/ded/

        .. deprecated:: 3.3.5
            DED is not supported by androguard anymore!

        It is now replaced by DARE.

        :param vm: `DalvikVMFormat` object
        :param bin_ded:
        :param tmp_dir:
        """
        warnings.warn("DED is deprecated since 3.3.5.", DeprecationWarning)

        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        dirname = tempfile.mkdtemp(prefix=fdname + "-src")
        cmd = Popen([bin_ded, "-c", "-o", "-d", dirname, fdname],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname)

        findsrc = None
        for root, dirs, files in os.walk(dirname + "/optimized-decompiled/"):
            if dirs:
                for f in dirs:
                    if f == "src":
                        findsrc = root
                        if findsrc[-1] != "/":
                            findsrc += "/"
                        findsrc += f
                        break
            if findsrc is not None:
                break

        for i in vm.get_classes():
            fname = findsrc + "/" + i.get_name()[1:-1] + ".java"
            # print fname
            if os.path.isfile(fname):
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(dirname)
    def __init__(self,
                 vm,
                 bin_ded="ded.sh",
                 tmp_dir="/tmp/"):
        """
        DED is an old, probably deprecated, decompiler
        http://siis.cse.psu.edu/ded/

        .. deprecated:: 3.3.5
            DED is not supported by androguard anymore!

        It is now replaced by DARE.

        :param vm: `DalvikVMFormat` object
        :param bin_ded:
        :param tmp_dir:
        """
        warnings.warn("DED is deprecated since 3.3.5.", DeprecationWarning)

        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        dirname = tempfile.mkdtemp(prefix=fdname + "-src")
        cmd = Popen([bin_ded, "-c", "-o", "-d", dirname, fdname],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname)

        findsrc = None
        for root, dirs, files in os.walk(dirname + "/optimized-decompiled/"):
            if dirs:
                for f in dirs:
                    if f == "src":
                        findsrc = root
                        if findsrc[-1] != "/":
                            findsrc += "/"
                        findsrc += f
                        break
            if findsrc is not None:
                break

        for i in vm.get_classes():
            fname = findsrc + "/" + i.get_name()[1:-1] + ".java"
            # print fname
            if os.path.isfile(fname):
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(dirname)
Beispiel #4
0
    def __init__(self,
                 vm,
                 path_dex2jar="./decompiler/dex2jar/",
                 bin_dex2jar="dex2jar.sh",
                 path_jad="./decompiler/jad/",
                 bin_jad="jad",
                 tmp_dir="/tmp/"):
        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        fd = os.fdopen(fd, "w+b")
        fd.write(vm.get_buff())
        fd.flush()
        fd.close()

        compile = Popen([path_dex2jar + bin_dex2jar, fdname],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = compile.communicate()
        os.unlink(fdname)

        pathclasses = fdname + "dex2jar/"
        compile = Popen(["unzip", fdname + "_dex2jar.jar", "-d", pathclasses],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = compile.communicate()
        os.unlink(fdname + "_dex2jar.jar")

        for root, dirs, files in os.walk(pathclasses, followlinks=True):
            if files != []:
                for f in files:
                    real_filename = root
                    if real_filename[-1] != "/":
                        real_filename += "/"
                    real_filename += f

                    compile = Popen([
                        "wine", path_jad + bin_jad, "-o", "-d", root,
                        real_filename
                    ],
                                    stdout=PIPE,
                                    stderr=STDOUT)
                    stdout, stderr = compile.communicate()

        for i in vm.get_classes():
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".jad"
            if os.path.isfile(fname) == True:
                fd = open(fname, "r")
                self.classes[i.get_name()] = fd.read()
                fd.close()
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(pathclasses)
Beispiel #5
0
    def __init__(self,
                 vm,
                 bin_dex2jar="dex2jar.sh",
                 bin_jad="jad",
                 tmp_dir="/tmp/"):
        """
        Use JAD on wine

        :param vm:
        :param bin_dex2jar:
        :param bin_jad:
        :param tmp_dir:
        """
        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        cmd = Popen([bin_dex2jar, fdname], stdout=PIPE, stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname)

        pathclasses = fdname + "dex2jar/"
        cmd = Popen(["unzip", fdname + "_dex2jar.jar", "-d", pathclasses],
                    stdout=PIPE,
                    stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname + "_dex2jar.jar")

        for root, dirs, files in os.walk(pathclasses, followlinks=True):
            if files:
                for f in files:
                    real_filename = root
                    if real_filename[-1] != "/":
                        real_filename += "/"
                    real_filename += f

                    cmd = Popen(
                        ["wine", bin_jad, "-o", "-d", root, real_filename],
                        stdout=PIPE,
                        stderr=STDOUT)
                    stdout, stderr = cmd.communicate()

        for i in vm.get_classes():
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".jad"
            if os.path.isfile(fname):
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(pathclasses)
Beispiel #6
0
    def __init__(self,
                 vm,
                 path_dex2jar="./decompiler/dex2jar/",
                 bin_dex2jar="dex2jar.sh",
                 path_fernflower="./decompiler/fernflower/",
                 bin_fernflower="fernflower.jar",
                 options_fernflower={"dgs": '1', "asc": '1'},
                 tmp_dir="/tmp/"):
        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        compile = Popen([path_dex2jar + bin_dex2jar, fdname],
                        stdout=PIPE, stderr=STDOUT)
        stdout, stderr = compile.communicate()
        os.unlink(fdname)

        pathclasses = fdname + "dex2jar/"
        compile = Popen(["unzip", fdname + "_dex2jar.jar", "-d",
                         pathclasses], stdout=PIPE, stderr=STDOUT)
        stdout, stderr = compile.communicate()
        os.unlink(fdname + "_dex2jar.jar")

        for root, dirs, files in os.walk(pathclasses, followlinks=True):
            if files != []:
                for f in files:
                    real_filename = root
                    if real_filename[-1] != "/":
                        real_filename += "/"
                    real_filename += f

                    l = ["java", "-jar", path_fernflower + bin_fernflower]

                    for option in options_fernflower:
                        l.append("-%s:%s" %
                                 (option, options_fernflower[option]))
                    l.append(real_filename)
                    l.append(root)

                    compile = Popen(l, stdout=PIPE, stderr=STDOUT)
                    stdout, stderr = compile.communicate()

        for i in vm.get_classes():
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".java"
            if os.path.isfile(fname) == True:
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(pathclasses)
Beispiel #7
0
    def __init__(self,
                 vm,
                 path_dex2jar="./decompiler/dex2jar/",
                 bin_dex2jar="dex2jar.sh",
                 path_fernflower="./decompiler/fernflower/",
                 bin_fernflower="fernflower.jar",
                 options_fernflower={"dgs": '1', "asc": '1'},
                 tmp_dir="/tmp/"):
        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        fd = os.fdopen(fd, "w+b")
        fd.write(vm.get_buff())
        fd.flush()
        fd.close()

        compile = Popen([path_dex2jar + bin_dex2jar, fdname], stdout=PIPE, stderr=STDOUT)
        stdout, stderr = compile.communicate()
        os.unlink(fdname)

        pathclasses = fdname + "dex2jar/"
        compile = Popen(["unzip", fdname + "_dex2jar.jar", "-d", pathclasses], stdout=PIPE, stderr=STDOUT)
        stdout, stderr = compile.communicate()
        os.unlink(fdname + "_dex2jar.jar")

        for root, dirs, files in os.walk(pathclasses, followlinks=True):
            if files != []:
                for f in files:
                    real_filename = root
                    if real_filename[-1] != "/":
                        real_filename += "/"
                    real_filename += f

                    l = ["java", "-jar", path_fernflower + bin_fernflower]

                    for option in options_fernflower:
                        l.append("-%s:%s" % (option, options_fernflower[option]))
                    l.append(real_filename)
                    l.append(root)

                    compile = Popen(l, stdout=PIPE, stderr=STDOUT)
                    stdout, stderr = compile.communicate()

        for i in vm.get_classes():
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".java"
            if os.path.isfile(fname) == True:
                fd = open(fname, "r")
                self.classes[i.get_name()] = fd.read()
                fd.close()
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(pathclasses)
Beispiel #8
0
    def __init__(self,
                 vm,
                 path="./decompiler/ded/",
                 bin_ded="ded.sh",
                 tmp_dir="/tmp/"):
        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        fd = os.fdopen(fd, "w+b")
        fd.write(vm.get_buff())
        fd.flush()
        fd.close()

        dirname = tempfile.mkdtemp(prefix=fdname + "-src")
        compile = Popen([path + bin_ded, "-c", "-o", "-d", dirname, fdname],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = compile.communicate()
        os.unlink(fdname)

        findsrc = None
        for root, dirs, files in os.walk(dirname + "/optimized-decompiled/"):
            if dirs != []:
                for f in dirs:
                    if f == "src":
                        findsrc = root
                        if findsrc[-1] != "/":
                            findsrc += "/"
                        findsrc += f
                        break
            if findsrc != None:
                break

        for i in vm.get_classes():
            fname = findsrc + "/" + i.get_name()[1:-1] + ".java"
            #print fname
            if os.path.isfile(fname) == True:
                fd = open(fname, "r")
                self.classes[i.get_name()] = fd.read()
                fd.close()
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(dirname)
Beispiel #9
0
    def __init__(self,
                 vm,
                 path="./decompiler/ded/",
                 bin_ded="ded.sh",
                 tmp_dir="/tmp/"):
        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        dirname = tempfile.mkdtemp(prefix=fdname + "-src")
        compile = Popen([path + bin_ded, "-c", "-o", "-d", dirname, fdname],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = compile.communicate()
        os.unlink(fdname)

        findsrc = None
        for root, dirs, files in os.walk(dirname + "/optimized-decompiled/"):
            if dirs != []:
                for f in dirs:
                    if f == "src":
                        findsrc = root
                        if findsrc[-1] != "/":
                            findsrc += "/"
                        findsrc += f
                        break
            if findsrc != None:
                break

        for i in vm.get_classes():
            fname = findsrc + "/" + i.get_name()[1:-1] + ".java"
            #print fname
            if os.path.isfile(fname) == True:
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(dirname)
    def __init__(self, vm, path_dex2jar = "./decompiler/dex2jar/", bin_dex2jar = "dex2jar.sh", path_jad="./decompiler/jad/", bin_jad="jad", tmp_dir="/tmp/") :
        self.classes = {}
        self.classes_failed = []
        
        pathtmp = tmp_dir
        if not os.path.exists(pathtmp) :
            os.makedirs( pathtmp )

        fd, fdname = tempfile.mkstemp( dir=pathtmp )
        fd = os.fdopen(fd, "w+b")
        fd.write( vm.get_buff() )
        fd.flush()
        fd.close()
       
        compile = Popen([ path_dex2jar + bin_dex2jar, fdname ], stdout=PIPE, stderr=STDOUT)        
        stdout, stderr = compile.communicate()
        os.unlink( fdname )

        pathclasses = fdname + "dex2jar/"
        compile = Popen([ "unzip", fdname + "_dex2jar.jar", "-d", pathclasses ], stdout=PIPE, stderr=STDOUT)        
        stdout, stderr = compile.communicate()
        os.unlink( fdname + "_dex2jar.jar" )

        for root, dirs, files in os.walk( pathclasses, followlinks=True ) :
            if files != [] :
                for f in files :
                    real_filename = root
                    if real_filename[-1] != "/" :
                        real_filename += "/"
                    real_filename += f
                    
                    compile = Popen([ path_jad + bin_jad, "-o", "-d", root, real_filename ], stdout=PIPE, stderr=STDOUT)
                    stdout, stderr = compile.communicate()

        for i in vm.get_classes() :
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".jad"
            if os.path.isfile(fname) == True :
                fd = open(fname, "r")
                self.classes[ i.get_name() ] = fd.read() 
                fd.close()
            else :
                self.classes_failed.append( i.get_name() )
    
        rrmdir( pathclasses )
Beispiel #11
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
Beispiel #12
0
def export_apps_to_format(filename,
                          s,
                          output,
                          methods_filter=None,
                          jar=None,
                          decompiler_type=None,
                          form=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)

    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 = "%s%s%s" % (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(method.get_class_name())
            filename_class = os.path.join(output, filename_class)
            create_directory(filename_class)

            print("Dump %s %s %s ..." % (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 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(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()
Beispiel #13
0
    def __init__(self, vm, vmx, jadx="jadx", keepfiles=False):
        """
        DecompilerJADX is a wrapper for the jadx decompiler:
        https://github.com/skylot/jadx

        Note, that jadx need to write files to your local disk.

        :param vm: `DalvikVMFormat` object
        :param vmx: `Analysis` object
        :param jadx: path to the jadx executable
        :param keepfiles: set to True, if you like to keep temporary files
        """
        self.vm = vm
        self.vmx = vmx
        # Dictionary to store classnames: sourcecode
        self.classes = {}

        # Result directory:
        # TODO need to remove the folder correctly!
        tmpfolder = tempfile.mkdtemp()

        # We need to decompile the whole dex file, as we do not have an API...
        # dump the dex file into a temp file
        # THIS WILL NOT WORK ON WINDOWS!!!
        # See https://stackoverflow.com/q/15169101/446140
        # Files can not be read, only if they specify temp file. But jadx does not do that...
        #
        # We need to trick jadx by setting the suffix, otherwise the file will not be loaded
        with tempfile.NamedTemporaryFile(suffix=".dex") as tf:
            tf.write(vm.get_buff())

            cmd = [
                jadx, "-d", tmpfolder, "--escape-unicode", "--no-res", tf.name
            ]
            log.debug("Call JADX with the following cmdline: {}".format(
                " ".join(cmd)))
            x = Popen(cmd, stdout=PIPE, stderr=PIPE)
            stdout, _ = x.communicate()
            # Looks like jadx does not use stderr
            log.info("Output of JADX during decompilation")
            for line in stdout.decode("UTF-8").splitlines():
                log.info(line)

            if x.returncode != 0:
                rrmdir(tmpfolder)
                raise JADXDecompilerError(
                    "Could not decompile file. Args: {}".format(" ".join(cmd)))

        # Next we parse the folder structure for later lookup
        # We read the content of each file here, so we can later delete the folder
        # We check here two ways, first we iterate all files and see if the class exists
        # in androguard
        # then, we iterate all classes in androguard and check if the file exists.

        andr_class_names = {x.get_name()[1:-1]: x for x in vm.get_classes()}

        # First, try to find classes for the files we have
        for root, dirs, files in os.walk(tmpfolder):
            for f in files:
                if not f.endswith(".java"):
                    log.warning(
                        "found a file in jadx folder which is not a java file: {}"
                        .format(f))
                    continue
                # as the path begins always with `self.res` (hopefully), we remove that length
                # also, all files should end with .java
                path = os.path.join(root, f)[len(tmpfolder) + 1:-5]
                path = path.replace(os.sep, "/")

                # Special care for files without package
                # All files that have no package set, will get the
                # package `defpackage` automatically
                if path.startswith("defpackage"):
                    path = path[len("defpackage/"):]

                if path in andr_class_names:
                    with open(os.path.join(root, f), "rb") as fp:
                        # Need to convert back to the "full" classname
                        self.classes["L{};".format(path)] = fp.read().decode(
                            "UTF-8")
                else:
                    log.warning(
                        "Found a class called {}, which is not found by androguard!"
                        .format(path))

        # Next, try to find files for the classes we have
        for cl in andr_class_names:
            fname = self._find_class(cl, tmpfolder)
            if fname:
                if "L{};".format(cl) not in self.classes:
                    with open(fname, "rb") as fp:
                        # TODO need to snip inner class from file
                        self.classes["L{};".format(cl)] = fp.read().decode(
                            "UTF-8")
                else:
                    # Class was already found...
                    pass
            else:
                log.warning(
                    "Found a class called {} which is not decompiled by jadx".
                    format(cl))

        # check if we have good matching
        if len(self.classes) == len(andr_class_names):
            log.debug(
                "JADX looks good, we have the same number of classes: {}".
                format(len(self.classes)))
        else:
            log.info(
                "Looks like JADX is missing some classes or "
                "we decompiled too much: decompiled: {} vs androguard: {}".
                format(len(self.classes), len(andr_class_names)))

        if not keepfiles:
            rrmdir(tmpfolder)
Beispiel #14
0
    def __init__(self,
                 vm,
                 bin_dex2jar="dex2jar.sh",
                 bin_fernflower="fernflower.jar",
                 options_fernflower={"dgs": '1',
                                     "asc": '1'},
                 tmp_dir="/tmp/"):
        """
        Decompiler interface for Fernflower
        Fernflower is a java decompiler by IntelliJ:
        https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine

        As it can not decompile Dalvik code directly, the DEX is first
        decompiled as a JAR file.


        :param vm: `DalvikVMFormtat` object
        :param bin_dex2jar:
        :param bin_fernflower:
        :param options_fernflower:
        :param tmp_dir:
        """
        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        cmd = Popen([bin_dex2jar, fdname],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname)

        pathclasses = fdname + "dex2jar/"
        cmd = Popen(["unzip", fdname + "_dex2jar.jar", "-d", pathclasses],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname + "_dex2jar.jar")

        for root, dirs, files in os.walk(pathclasses, followlinks=True):
            if files:
                for f in files:
                    real_filename = root
                    if real_filename[-1] != "/":
                        real_filename += "/"
                    real_filename += f

                    l = ["java", "-jar", bin_fernflower]

                    for option in options_fernflower:
                        l.append("-%s:%s" %
                                 (option, options_fernflower[option]))
                    l.append(real_filename)
                    l.append(root)

                    cmd = Popen(l, stdout=PIPE, stderr=STDOUT)
                    stdout, stderr = cmd.communicate()

        for i in vm.get_classes():
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".java"
            if os.path.isfile(fname):
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(pathclasses)
Beispiel #15
0
    def __init__(self,
                 vm,
                 bin_dex2jar="dex2jar.sh",
                 bin_fernflower="fernflower.jar",
                 options_fernflower={
                     "dgs": '1',
                     "asc": '1'
                 },
                 tmp_dir="/tmp/"):
        """
        Decompiler interface for Fernflower
        Fernflower is a java decompiler by IntelliJ:
        https://github.com/JetBrains/intellij-community/tree/master/plugins/java-decompiler/engine

        As it can not decompile Dalvik code directly, the DEX is first
        decompiled as a JAR file.


        :param vm: `DalvikVMFormtat` object
        :param bin_dex2jar:
        :param bin_fernflower:
        :param options_fernflower:
        :param tmp_dir:
        """
        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        cmd = Popen([bin_dex2jar, fdname], stdout=PIPE, stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname)

        pathclasses = fdname + "dex2jar/"
        cmd = Popen(["unzip", fdname + "_dex2jar.jar", "-d", pathclasses],
                    stdout=PIPE,
                    stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname + "_dex2jar.jar")

        for root, dirs, files in os.walk(pathclasses, followlinks=True):
            if files:
                for f in files:
                    real_filename = root
                    if real_filename[-1] != "/":
                        real_filename += "/"
                    real_filename += f

                    l = ["java", "-jar", bin_fernflower]

                    for option in options_fernflower:
                        l.append("-%s:%s" %
                                 (option, options_fernflower[option]))
                    l.append(real_filename)
                    l.append(root)

                    cmd = Popen(l, stdout=PIPE, stderr=STDOUT)
                    stdout, stderr = cmd.communicate()

        for i in vm.get_classes():
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".java"
            if os.path.isfile(fname):
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(pathclasses)
Beispiel #16
0
    def __init__(self, vm, vmx, jadx="jadx", keepfiles=False):
        """
        DecompilerJADX is a wrapper for the jadx decompiler:
        https://github.com/skylot/jadx

        Note, that jadx need to write files to your local disk.

        :param vm: `DalvikVMFormat` object
        :param vmx: `Analysis` object
        :param jadx: path to the jadx executable
        :param keepfiles: set to True, if you like to keep temporary files
        """
        self.vm = vm
        self.vmx = vmx
        # Dictionary to store classnames: sourcecode
        self.classes = {}

        # Result directory:
        # TODO need to remove the folder correctly!
        tmpfolder = tempfile.mkdtemp()

        # We need to decompile the whole dex file, as we do not have an API...
        # dump the dex file into a temp file
        # THIS WILL NOT WORK ON WINDOWS!!!
        # See https://stackoverflow.com/q/15169101/446140
        # Files can not be read, only if they specify temp file. But jadx does not do that...
        #
        # We need to trick jadx by setting the suffix, otherwise the file will not be loaded
        with tempfile.NamedTemporaryFile(suffix=".dex") as tf:
            tf.write(vm.get_buff())

            cmd = [jadx, "-d", tmpfolder, "--escape-unicode", "--no-res", tf.name]
            log.debug("Call JADX with the following cmdline: {}".format(" ".join(cmd)))
            x = Popen(cmd, stdout=PIPE, stderr=PIPE)
            stdout, _ = x.communicate()
            # Looks like jadx does not use stderr
            log.info("Output of JADX during decompilation")
            for line in stdout.decode("UTF-8").splitlines():
                log.info(line)

            if x.returncode != 0:
                rrmdir(tmpfolder)
                raise JADXDecompilerError("Could not decompile file. Args: {}".format(" ".join(cmd)))

        # Next we parse the folder structure for later lookup
        # We read the content of each file here, so we can later delete the folder
        # We check here two ways, first we iterate all files and see if the class exists
        # in androguard
        # then, we iterate all classes in androguard and check if the file exists.

        andr_class_names = {x.get_name()[1:-1]: x for x in vm.get_classes()}

        # First, try to find classes for the files we have
        for root, dirs, files in os.walk(tmpfolder):
            for f in files:
                if not f.endswith(".java"):
                    log.warning("found a file in jadx folder which is not a java file: {}".format(f))
                    continue
                # as the path begins always with `self.res` (hopefully), we remove that length
                # also, all files should end with .java
                path = os.path.join(root, f)[len(tmpfolder) + 1:-5]
                path = path.replace(os.sep, "/")

                # Special care for files without package
                # All files that have no package set, will get the
                # package `defpackage` automatically
                if path.startswith("defpackage"):
                    path = path[len("defpackage/"):]

                if path in andr_class_names:
                    with open(os.path.join(root, f), "rb") as fp:
                        # Need to convert back to the "full" classname
                        self.classes["L{};".format(path)] = fp.read().decode("UTF-8")
                else:
                    log.warning("Found a class called {}, which is not found by androguard!".format(path))

        # Next, try to find files for the classes we have
        for cl in andr_class_names:
            fname = self._find_class(cl, tmpfolder)
            if fname:
                if "L{};".format(cl) not in self.classes:
                    with open(fname, "rb") as fp:
                        # TODO need to snip inner class from file
                        self.classes["L{};".format(cl)] = fp.read().decode("UTF-8")
                else:
                    # Class was already found...
                    pass
            else:
                log.warning("Found a class called {} which is not decompiled by jadx".format(cl))

        # check if we have good matching
        if len(self.classes) == len(andr_class_names):
            log.debug("JADX looks good, we have the same number of classes: {}".format(len(self.classes)))
        else:
            log.info("Looks like JADX is missing some classes or "
                 "we decompiled too much: decompiled: {} vs androguard: {}".format(len(self.classes),
                                                                                   len(andr_class_names)))

        if not keepfiles:
            rrmdir(tmpfolder)
Beispiel #17
0
    def __init__(self,
                 vm,
                 bin_dex2jar="dex2jar.sh",
                 bin_jad="jad",
                 tmp_dir="/tmp/"):
        """
        Decompiler interface for JAD
        JAD is not a native Dalvik decompiler, therefore dex2jar is required.

        .. deprecated:: 3.3.5
            JAD is not supported anymore in androguard!

        :param vm:
        :param bin_dex2jar:
        :param bin_jad:
        :param tmp_dir:
        """
        warnings.warn("JAD is deprecated since 3.3.5.", DeprecationWarning)

        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        cmd = Popen([bin_dex2jar, fdname], stdout=PIPE, stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname)

        pathclasses = fdname + "dex2jar/"
        cmd = Popen(["unzip", fdname + "_dex2jar.jar", "-d", pathclasses],
                    stdout=PIPE,
                    stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname + "_dex2jar.jar")

        for root, dirs, files in os.walk(pathclasses, followlinks=True):
            if files:
                for f in files:
                    real_filename = root
                    if real_filename[-1] != "/":
                        real_filename += "/"
                    real_filename += f

                    cmd = Popen([bin_jad, "-o", "-d", root, real_filename],
                                stdout=PIPE,
                                stderr=STDOUT)
                    stdout, stderr = cmd.communicate()

        for i in vm.get_classes():
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".jad"
            if os.path.isfile(fname):
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(pathclasses)
Beispiel #18
0
    def __init__(self,
                 vm,
                 bin_dex2jar="dex2jar.sh",
                 bin_jad="jad",
                 tmp_dir="/tmp/"):
        """
        Decompiler interface for JAD
        JAD is not a native Dalvik decompiler, therefore dex2jar is required.

        .. deprecated:: 3.3.5
            JAD is not supported anymore in androguard!

        :param vm:
        :param bin_dex2jar:
        :param bin_jad:
        :param tmp_dir:
        """
        warnings.warn("JAD is deprecated since 3.3.5.", DeprecationWarning)

        self.classes = {}
        self.classes_failed = []

        pathtmp = tmp_dir
        if not os.path.exists(pathtmp):
            os.makedirs(pathtmp)

        fd, fdname = tempfile.mkstemp(dir=pathtmp)
        with os.fdopen(fd, "w+b") as fd:
            fd.write(vm.get_buff())
            fd.flush()

        cmd = Popen([bin_dex2jar, fdname],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname)

        pathclasses = fdname + "dex2jar/"
        cmd = Popen(["unzip", fdname + "_dex2jar.jar", "-d", pathclasses],
                        stdout=PIPE,
                        stderr=STDOUT)
        stdout, stderr = cmd.communicate()
        os.unlink(fdname + "_dex2jar.jar")

        for root, dirs, files in os.walk(pathclasses, followlinks=True):
            if files:
                for f in files:
                    real_filename = root
                    if real_filename[-1] != "/":
                        real_filename += "/"
                    real_filename += f

                    cmd = Popen([bin_jad, "-o", "-d", root,
                                     real_filename],
                                    stdout=PIPE,
                                    stderr=STDOUT)
                    stdout, stderr = cmd.communicate()

        for i in vm.get_classes():
            fname = pathclasses + "/" + i.get_name()[1:-1] + ".jad"
            if os.path.isfile(fname):
                self.classes[i.get_name()] = read(fname, binary=False)
            else:
                self.classes_failed.append(i.get_name())

        rrmdir(pathclasses)
Beispiel #19
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()
Beispiel #20
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"
                with open(current_filename_class, "w") as fd:
                    fd.write(current_class.get_source())
                dump_classes.append(method.get_class_name())

            print "bytecodes ...",
            bytecode_buff = dvm.get_bytecodes_method(vm, vmx, method)
            with open(filename + ".ag", "w") as fd:
                fd.write(bytecode_buff)
            print
Beispiel #21
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