Esempio n. 1
0
    def __init__(self,
                 opener: str,
                 closers: List[str],
                 classname: str,
                 reference_dx: Analysis = None,
                 cg_filter: DiGraph = None):
        if reference_dx:
            self.classname = classname
            opener_analyses = reference_dx.find_methods(methodname=opener,
                                                        classname=classname)
            self.openers = [x for x in opener_analyses]

            self.closers = []
            for closer in closers:
                closer_gen = reference_dx.find_methods(methodname=closer,
                                                       classname=classname)
                self.closers.extend([x for x in closer_gen])

            # optionally filter out uninteresting openers based on
            # if they exist in a given call graph
            if cg_filter:
                self.openers = list(
                    filter(lambda x: cg_filter.has_node(x.method),
                           self.openers))

        self.opener_path_generators = []
        self.closer_path_generators = []
        self.lifecycles = []
        self.opener_paths = []
        self.closer_paths = []
def get_apis(path):

    application = APK(path)
    application_dex = DalvikVMFormat(application.get_dex())
    application_x = Analysis(application_dex)

    methods = set()
    cs = [cc.get_name() for cc in application_dex.get_classes()]

    for method in application_dex.get_methods():
        g = application_x.get_method(method)

        if method.get_code() == None:
            continue

        for i in g.get_basic_blocks().get():
            for ins in i.get_instructions():

                output = ins.get_output()
                match = re.search(r'(L[^;]*;)->[^\(]*\([^\)]*\).*', output)
                if match and match.group(1) not in cs:
                    methods.add(match.group())

    methods = list(methods)
    return methods
Esempio n. 3
0
    def addAPK(self, filename, data):
        """
        Add an APK file to the Session and run analysis on it.

        :param filename: (file)name of APK file
        :param data: binary data of the APK file
        :return: a tuple of SHA256 Checksum and APK Object
        """
        digest = hashlib.sha256(data).hexdigest()
        log.debug("add APK:%s" % digest)
        apk = APK(data, True)
        self.analyzed_apk[digest] = [apk]
        self.analyzed_files[filename].append(digest)
        self.analyzed_digest[digest] = filename

        dx = Analysis()
        self.analyzed_vms[digest] = dx

        for dex in apk.get_all_dex():
            # we throw away the output... FIXME?
            self.addDEX(filename, dex, dx, postpone_xref=True)

        # Postponed
        dx.create_xref()

        log.debug("added APK:%s" % digest)
        return digest, apk
Esempio n. 4
0
    def __analyse_ip__(self, a: apk.APK, dx: Analysis):
        print("analysing ip disclosure")
        # private address
        priv: [str] = []
        privRe = re.compile(PRIVADDR)
        # ipv4
        ipv4: [str] = []
        rs: [StringAnalysis] = dx.find_strings(IPV4ADDR)
        for result in rs:
            result: StringAnalysis = result
            val = result.get_value()
            if privRe.match(val):
                priv.append(val)
            else:
                ipv4.append(val)
        self.ipv4 = ipv4

        # ipv6
        ipv6: [str] = []
        rs: [StringAnalysis] = dx.find_strings(IPV6ADDR)
        for result in rs:
            result: StringAnalysis = result
            val = result.get_value()
            if privRe.match(val):
                priv.append(val)
            else:
                ipv6.append(val)
        self.ipv6 = ipv6
        self.private_ip = priv
        pass
Esempio n. 5
0
    def addDEY(self, filename, data, dx=None):
        """
        Add an ODEX file to the session and run the analysis
        """
        digest = hashlib.sha256(data).hexdigest()
        log.debug("add DEY:%s" % digest)
        d = DalvikOdexVMFormat(data)
        log.debug("added DEY:%s" % digest)

        self.analyzed_files[filename].append(digest)
        self.analyzed_digest[digest] = filename

        self.analyzed_dex[digest] = d

        if self.export_ipython:
            d.create_python_export()

        if dx is None:
            dx = Analysis()

        dx.add(d)
        dx.create_xref()

        for d in dx.vms:
            # TODO: allow different decompiler here!
            d.set_decompiler(DecompilerDAD(d, dx))
            d.set_vmanalysis(dx)

        self.analyzed_vms[digest] = dx

        return digest, d, dx
Esempio n. 6
0
    def find_method_used(self):
        """
            funzione per ricercare i metodi che sono usati 
            all'interno dell'apk, tanto lenta
        """
        used_jadx = False
        if used_jadx:

            # Create DalvikVMFormat Object
            self.dalvik_format = DalvikVMFormat(self.apk)
            # Create Analysis Object
            self.analysis_object = Analysis(self.dalvik_format)
            # Load the decompiler
            # Make sure that the jadx executable is found in $PATH
            # or use the argument jadx="/path/to/jadx" to point to the executable
            decompiler = DecompilerJADX(self.dalvik_format,
                                        self.analysis_object)

            # propagate decompiler and analysis back to DalvikVMFormat
            self.dalvik_format.set_decompiler(decompiler)
            self.dalvik_format.set_vmanalysis(self.analysis_object)

            # Now you can do stuff like:
            list_method_analysis = self.analysis_object.get_methods()
            for method_analys in list_method_analysis:
                method_name = method_analys.get_method().get_name()
                # print(method_encoded.get_method().get_source())
                self.method[method_name] = list(method_analys.get_xref_from())

        elif self.use_analyze:
            # return apk, list dex , object analysis
            apk, self.dalvik_format, self.analysis_object = AnalyzeAPK(
                self.name_apk)

            for method_analys in self.analysis_object.get_methods():
                method_name = method_analys.get_method().get_name()
                # from method_name get list dove esso viene chiamato
                self.method[method_name] = list(method_analys.get_xref_from())

        elif self.use_smaliparser:
            # use smali parser, apktool and grep invece di Androguard
            dir_apk_tool = "temp_dir_" + self.name_only_apk + "/"
            list_method_to_analyze = self.conf["method_smali_parser"]
            self.method_2_value, self.all_url = smaliparser.start(
                dir_apk_tool, list_method_to_analyze)

        else:  # TODO to make faster analysis but not work well
            self.dalvik_format = DalvikVMFormat(self.apk)
            for encoded_method in self.dalvik_format.get_methods():
                method_analysis = MethodClassAnalysis(encoded_method)

                method_name = method_analysis.get_method().get_name()
                # print(method_name)
                # from method_name get list dove esso viene chiamato
                self.method[method_name] = list(
                    method_analysis.get_xref_from())
Esempio n. 7
0
class CFG():
    def __init__(self, filename):
        self.filename = filename
        try:
            self.a = APK(filename)
            self.d = DalvikVMFormat(self.a.get_dex())
            self.d.create_python_export()
            self.dx = Analysis(self.d)
        except zipfile.BadZipfile:
            # if file is not an APK, may be a dex object
            _, self.d, self.dx = AnalyzeDex(self.filename)

        self.d.set_vmanalysis(self.dx)
        self.dx.create_xref()
        self.cfg = self.build_cfg()

    def get_cg(self):
        return self.cfg

    def get_cfg(self):
        return self.dx.get_call_graph()

    def build_cfg(self):
        """ Using NX and Androguard, build a directed graph NX object so that:
            - node names are analysis.MethodClassAnalysis objects
            - each node has a label that encodes the method behavior
        """
        cfg = self.get_cfg()  ##/////////My changes///////////////
        for n in cfg.nodes:
            instructions = []
            # print(n)
            try:
                ops = n.get_instructions()
                for i in ops:
                    instructions.append(i.get_name())
                # print(ops)
                encoded_label = self.color_instructions(instructions)
                # print("No Exception")
            except AttributeError:
                encoded_label = np.array([0] * 15)
            cfg.node[n]["label"] = encoded_label
        return cfg

    def color_instructions(self, instructions):
        """ Node label based on coloring technique by Kruegel """

        h = [0] * len(INSTRUCTION_CLASS_COLOR)
        for i in instructions:
            h[INSTRUCTION_SET_COLOR[i]] = 1
        return np.array(h)

    def get_classes_from_label(self, label):
        classes = [
            INSTRUCTION_CLASSES[i] for i in range(len(label)) if label[i] == 1
        ]
        return classes
Esempio n. 8
0
    def __init__(self, filename):
        self.filename = filename
        try:
            self.a = APK(filename)
            self.d = DalvikVMFormat(self.a.get_dex())
            self.d.create_python_export()
            self.dx = Analysis(self.d)
        except zipfile.BadZipfile:
            # if file is not an APK, may be a dex object
            _, self.d, self.dx = AnalyzeDex(self.filename)

        self.d.set_vmanalysis(self.dx)
        self.dx.create_xref()
        self.fcg = self.build_fcg()
Esempio n. 9
0
def AnalyzeAPK(_file, session=None, raw=False):
    """
    Analyze an android application and setup all stuff for a more quickly
    analysis!
    If session is None, no session is used at all. This is the default
    behaviour.
    If you like to continue your work later, it might be a good idea to use a
    session.
    A default session can be created by using :meth:`~get_default_session`.

    :param _file: the filename of the android application or a buffer which represents the application
    :type _file: string (for filename) or bytes (for raw)
    :param session: A session (default: None)
    :param raw: boolean if raw bytes are supplied instead of a filename
    :rtype: return the :class:`~androguard.core.bytecodes.apk.APK`, list of :class:`~androguard.core.bytecodes.dvm.DalvikVMFormat`, and :class:`~androguard.core.analysis.analysis.Analysis` objects
    """
    log.debug("AnalyzeAPK")


    if session:
        log.debug("Using existing session {}".format(session))
        if raw:
            data = _file
            filename = hashlib.md5(_file).hexdigest()
        else:
            with open(_file, "rb") as fd:
                data = fd.read()
                filename = _file

        digest = session.add(filename, data)
        return session.get_objects_apk(filename, digest)
    else:
        log.debug("Analysing without session")
        a = APK(_file, raw=raw)
        # FIXME: probably it is not necessary to keep all DalvikVMFormats, as
        # they are already part of Analysis. But when using sessions, it works
        # this way...
        d = []
        dx = Analysis()
        for dex in a.get_all_dex():
            df = DalvikVMFormat(dex, using_api=a.get_target_sdk_version())
            dx.add(df)
            d.append(df)
            df.set_decompiler(decompiler.DecompilerDAD(d, dx))

        dx.create_xref()

        return a, d, dx
Esempio n. 10
0
def link_callbacks(mca: MethodClassAnalysis, dx: Analysis, ast: Dict, cg: nx.DiGraph):
    android_api_callbacks = get_cb_methods()
    invoked_callback_registers = get_callback_list(mca, dx, ast, android_callback_interfaces)

    def is_android_api_callback(callback_tuple):
        _, interface = callback_tuple
        if interface in android_api_callbacks:
            return True
        return False

    invoked_callback_registers = filter(is_android_api_callback, invoked_callback_registers)

    found_methods = list()
    for cb_typ, cb_interface in invoked_callback_registers:
        java_interface: JavaInterface = android_api_callbacks[cb_interface]
        interface_method: JavaMethod

        # Try to find the analysis for the interface methods.
        # This should be successful if an interface method is
        # used by any user code, but I'll need to verify edge cases.
        for interface_method in java_interface.methods:
            gen = dx.find_methods(
                classname=cb_typ, methodname=".*{}.*".format(interface_method.name)
            )
            analysis: MethodClassAnalysis
            found = False
            for item in gen:
                analysis = item
                found = True
            if found:
                found_methods.append(analysis.method)

    for method_enc in found_methods:
        print("adding edge: ", mca.name, " -> ", method_enc.name)
        cg.add_edge(mca.method, method_enc)
Esempio n. 11
0
    def __analyse_sql__(self, a: apk.APK, dx: Analysis):
        print("analysing sqlite")
        # raw query
        methods = dx.find_methods("Landroid/database/sqlite/.*",
                                  "execSQL|rawQuery")
        raw_query_injects: [(ClassAnalysis, EncodedMethod)] = []

        # cipher key hardcoded
        encrypts: [(ClassAnalysis, EncodedMethod)] = []
        # check whether variables/user inputs are involved in SQL statements (filter out constant values)
        for m in methods:
            # raw_query_injects.append(m)
            # 1. should implement code tracing variables
            # 2. find encryption entry. Hint: db.execSQL("PRAGMA key = 'secretkey'");
            m: MethodClassAnalysis = m
            p_list: [(ClassAnalysis, object, int)] = m.get_xref_from()
            for (p_class, p_method, _) in p_list:
                if type(p_method) is ExternalMethod:
                    continue
                p_method: EncodedMethod = p_method
                item = (p_class, p_method)
                if "PRAGMA key" in p_method.get_source():
                    if item not in encrypts:  # may contain hardcoded keys
                        encrypts.append(item)
                elif item not in raw_query_injects:  # may leak
                    raw_query_injects.append(item)

                break

        self.sql_raw_query_inject_methods = raw_query_injects
        self.sql_encrypt_secret_hardcoded_methods = encrypts
        pass
Esempio n. 12
0
    def __analyse_insecure_secure_random__(self, a: apk.APK, dx: Analysis):
        print("analysing insecure random")
        # find java.util.Random
        self.insecure_randoms: [(ClassAnalysis, EncodedMethod)] = []
        methods = dx.find_methods("Ljava/util/Random|Lkotlin/random/Random",
                                  r"next\s*")

        for m in methods:
            # check its parent method to find wrong parameters
            m: MethodClassAnalysis = m
            p_list: [(ClassAnalysis, object, int)] = m.get_xref_from()

            for (p_class, p_method, _) in p_list:
                # find first parent method
                p_class: ClassAnalysis = p_class
                class_name: str = p_class.name

                # jump out of kotlin packages
                if p_method is ExternalMethod or class_name.startswith(
                        'Lkotlin'):
                    continue
                item = (p_class, p_method)
                if item not in self.insecure_randoms:
                    self.insecure_randoms.append(item)
                break
        pass
Esempio n. 13
0
    def __analyse_insecure_hash_function__(self, a: apk.APK, dx: Analysis):
        print("analysing insecure hash function")
        # find all md4, rc2, rc4, md5, sha-1
        self.weak_hash: [(ClassAnalysis, EncodedMethod)] = []

        # find general weak hash
        methods = dx.find_methods("Ljava/security/MessageDigest",
                                  "getInstance")
        reWeakHash = re.compile(r'md5|md4|rc2|sha-1', re.IGNORECASE)
        for m in methods:
            # check its parent method to find wrong parameters
            m: MethodClassAnalysis = m
            p_list: [(ClassAnalysis, object, int)] = m.get_xref_from()
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue

                # iterate parent methods
                p_method: EncodedMethod = p_method
                # find wrong encryption options
                for ins in p_method.get_instructions():
                    ins: Instruction = ins
                    if ins.get_name() != 'const-string':
                        continue

                    output = ins.get_output()
                    item = (p_class, p_method)
                    if reWeakHash.search(output):
                        if item not in self.weak_hash:
                            self.weak_hash.append(item)
                        break

        methods = dx.find_methods(
            "Lorg/apache/commons/codec/digest/DigestUtils", "md5|sha")
        for m in methods:
            # check its parent method to find wrong parameters
            m: MethodClassAnalysis = m
            p_list: [(ClassAnalysis, object, int)] = m.get_xref_from()
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue
                item = (p_class, p_method)
                if item not in self.weak_hash:
                    self.weak_hash.append((p_class, p_method))
                break

        pass
Esempio n. 14
0
def extract_features(file_path):
    a = APK(file_path)
    d = DalvikVMFormat(a.get_dex())
    dx = Analysis(d)
    vm = dvm.DalvikVMFormat(a.get_dex())
    vmx = analysis.Analysis(vm)
    d.set_vmanalysis(dx)
    d.set_decompiler(DecompilerDAD(d, dx))
    return a.get_permissions()
Esempio n. 15
0
    def __init__(self, filename):
        self.filename = filename
        # print(os.path.exists(filename))
        # a,d,dx = AnalyzeAPK(filename)
        # print(dx.get_call_graph())

        try:
            self.a = APK(filename)
            self.d = DalvikVMFormat(self.a.get_dex())
            self.d.create_python_export()
            self.dx = Analysis(self.d)
        except zipfile.BadZipfile:
            # if file is not an APK, may be a dex object
            _, self.d, self.dx = AnalyzeDex(self.filename)

        self.d.set_vmanalysis(self.dx)
        self.dx.create_xref()
        self.fcg = self.build_fcg()
Esempio n. 16
0
    def addDEY(self, filename, data, dx=None):
        """
        Add an ODEX file to the session and run the analysis
        """
        digest = hashlib.sha256(data).hexdigest()
        log.debug("add DEY:%s" % digest)
        d = DalvikOdexVMFormat(data)
        log.debug("added DEY:%s" % digest)

        self.analyzed_files[filename].append(digest)
        self.analyzed_digest[digest] = filename

        self.analyzed_dex[digest] = d

        if self.export_ipython:
            d.create_python_export()

        if dx is None:
            dx = Analysis()

        dx.add(d)
        dx.create_xref()

        for d in dx.vms:
            # TODO: allow different decompiler here!
            d.set_decompiler(DecompilerDAD(d, dx))
            d.set_vmanalysis(dx)

        self.analyzed_vms[digest] = dx

        return digest, d, dx
Esempio n. 17
0
    def run(self):
        unique_apis = []

        for apk in self.apks_list:
            try:
                with ZipFile(apk) as zipfile:
                    # find .dex files inside apk
                    dexes = [dex for dex in zipfile.namelist() if dex.endswith('.dex')]
                    dx = Analysis()
                    # analyze every .dex
                    for dex in dexes:
                        with zipfile.open(dex) as dexfile:
                            d = DalvikVMFormat(dexfile.read())
                            dx.add(d)
                    # creates cross references between classes, methods, etc. for all the .dex
                    dx.create_xref()

                    # extracting android apis
                    apis = self.get_api_calls(dx)
                    not_unique = unique_apis + apis
                    unique_apis = list(np.unique(not_unique))
                    print('Process %d: %.1f%%' %
                          (self.process_id, ((self.apks_list.index(apk) + 1) / self.total_apks) * 100))
            except BadZipfile as e:
                print('Bad zip file =========> %s' % apk)
            except Exception as e:
                print('\n%s\n%s\n' % (apk, e))

        self.queue.put(unique_apis)
        print('----------------> Process %d is done!' % self.process_id)
Esempio n. 18
0
    def addDEX(self, filename, data, dx=None):
        """
        Add a DEX file to the Session and run analysis.

        :param filename: the (file)name of the DEX file
        :param data: binary data of the dex file
        :param dx: an existing Analysis Object (optional)
        :return: A tuple of SHA256 Hash, DalvikVMFormat Object and Analysis object
        """
        digest = hashlib.sha256(data).hexdigest()
        log.debug("add DEX:%s" % digest)

        log.debug("Parsing format ...")
        d = DalvikVMFormat(data)
        log.debug("added DEX:%s" % digest)

        self.analyzed_files[filename].append(digest)
        self.analyzed_digest[digest] = filename

        self.analyzed_dex[digest] = d

        if dx is None:
            dx = Analysis()

        dx.add(d)
        dx.create_xref()

        # TODO: If multidex: this will called many times per dex, even if already set
        for d in dx.vms:
            # TODO: allow different decompiler here!
            d.set_decompiler(DecompilerDAD(d, dx))
            d.set_vmanalysis(dx)
        self.analyzed_vms[digest] = dx

        if self.export_ipython:
            log.debug("Exporting in ipython")
            d.create_python_export()

        return digest, d, dx
Esempio n. 19
0
def extract_features(file_path):
    #result = []
    try:
        a = APK(file_path)
        d = DalvikVMFormat(a.get_dex())
        dx = Analysis(d)
        vm = dvm.DalvikVMFormat(a.get_dex())
        vmx = analysis.uAnalysis(vm)
        d.set_Analysis(dx)
        d.set_decompiler(DecompilerDAD(d, dx))
    except:
        return None
    return a.get_permissions()  #it will return permission
Esempio n. 20
0
    def __detect_su_detection__(self, dx: Analysis):
        print("analysing su detection")
        self.su_detections: [(ClassAnalysis, EncodedMethod)] = []

        # find methods that contains these su paths
        rs: [StringAnalysis] = dx.find_strings(r"/system/app/Superuser.apk|/system/bin/failsafe/su|/system/sd/xbin/su")
        for result in rs:
            result: StringAnalysis = result
            p_list: [(ClassAnalysis, object)] = result.get_xref_from()
            # find direct parent method who trigger this method
            for (p_class, p_method) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue

                item = (p_class, p_method)
                if item not in self.su_detections:
                    self.su_detections.append(item)
                break

        # RootTools or Root detection
        rss: [MethodClassAnalysis] = dx.find_methods("Lcom/stericson/RootTools/RootTools|Ldexguard/util/RootDetector",
                                                     "isAccessGiven|isDeviceRooted")
        for rst in rss:
            rst: MethodClassAnalysis = rst
            p_list: [(ClassAnalysis, object, int)] = rst.get_xref_from()
            # find direct parent method who trigger this method
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue

                item = (p_class, p_method)
                if item not in self.su_detections:
                    self.su_detections.append(item)
                break

        pass
Esempio n. 21
0
    def __detect_debug__(self, dx: Analysis):
        print("analysing debugging detection")
        self.debug_detections: [(ClassAnalysis, EncodedMethod)] = []
        rss: [MethodClassAnalysis] = dx.find_methods("Ldexguard/util/.*",
                                                     "isDebuggable|isDebuggerConnected|isRunningInEmulator|isSignedWithDebugKey")
        for rst in rss:
            rst: MethodClassAnalysis = rst
            p_list: [(ClassAnalysis, object, int)] = rst.get_xref_from()
            # find direct parent method who trigger this method
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue

                item = (p_class, p_method)
                if item not in self.su_detections:
                    self.debug_detections.append(item)
                break
        pass
Esempio n. 22
0
    def __analyse_insecure_webview_implementation(self, dx: Analysis):
        print("analysing insecure webview implementation")
        methods = dx.find_methods("Landroid/webkit/WebViewClient",
                                  "onReceivedSslError")
        self.webview_insecure_implementation: [(ClassAnalysis, EncodedMethod)
                                               ] = []
        for m in methods:
            # check its parent method to find wrong parameters
            m: MethodClassAnalysis = m
            p_list: [(ClassAnalysis, object, int)] = m.get_xref_from()
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue
                item = (p_class, p_method)
                if item not in self.webview_insecure_implementation:
                    self.webview_insecure_implementation.append(item)
                break

        pass
Esempio n. 23
0
    def __analyse_insecure_certificate_validation__(self, dx: Analysis):
        print("analysing insecure certificate validation")
        methods = dx.find_methods("Ljavax/net/ssl/.*",
                                  "setDefaultHostnameVerifier")
        self.insecure_certificate_validation: [(ClassAnalysis, EncodedMethod)
                                               ] = []
        for m in methods:
            # check its parent method to find wrong parameters
            m: MethodClassAnalysis = m
            p_list: [(ClassAnalysis, object, int)] = m.get_xref_from()
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue
                item = (p_class, p_method)
                if item not in self.insecure_certificate_validation:
                    self.insecure_certificate_validation.append(item)
                break

        pass
Esempio n. 24
0
    def __analyse_improper_encryption__(self, a: apk.APK, dx: Analysis):
        print("analysing improper encryption")

        # check improper encryption
        self.encryption_vuln_ecb: [(ClassAnalysis, EncodedMethod)] = []
        self.encryption_vuln_rsa_no_oaep: [(ClassAnalysis, EncodedMethod)] = []
        methods = dx.find_methods("Ljavax/crypto/Cipher", "getInstance")

        reECB = re.compile(
            r'AES/ECB', re.IGNORECASE
        )  # The App uses ECB mode in Cryptographic encryption algorithm.
        reRsaNoPadding = re.compile(
            r'rsa/.+/nopadding',
            re.IGNORECASE)  # This App uses RSA Crypto without OAEP padding.

        for m in methods:
            # check its parent method to find wrong parameters
            m: MethodClassAnalysis = m
            p_list: [(ClassAnalysis, object, int)] = m.get_xref_from()
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue

                # iterate parent methods
                p_method: EncodedMethod = p_method
                # find wrong encryption options
                for ins in p_method.get_instructions():
                    ins: Instruction = ins
                    if ins.get_name() != 'const-string':
                        continue

                    output = ins.get_output()
                    item = (p_class, p_method)
                    if reECB.search(output):
                        if item not in self.encryption_vuln_ecb:
                            self.encryption_vuln_ecb.append(item)
                        break
                    elif reRsaNoPadding.search(output):
                        if item not in self.encryption_vuln_rsa_no_oaep:
                            self.encryption_vuln_rsa_no_oaep.append(item)
                        break
        pass
Esempio n. 25
0
    def __detect_su_usage__(self, dx: Analysis):
        print("analysing root usage")
        # find out su root usage
        self.su_usages: [(ClassAnalysis, EncodedMethod)] = []
        # su packages
        rss: [MethodClassAnalysis] = dx.find_methods(
            "Lcom/noshufou/android/su/.*|Lcom/thirdparty/superuser/.*|Leu/chainfire/.*|Lcom/koushikdutta/superuser/.*")
        for rst in rss:
            rst: MethodClassAnalysis = rst
            p_list: [(ClassAnalysis, object, int)] = rst.get_xref_from()
            # find direct parent method who trigger this method
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue

                item = (p_class, p_method)
                if item not in self.su_usages:
                    self.su_usages.append(item)
                break
        pass
Esempio n. 26
0
    def __analyse_storage__(self, dx: Analysis):
        print("analysing storage issues")
        self.storage_issues: [(ClassAnalysis, EncodedMethod)] = []

        # storage
        rss = dx.find_methods(
            "Landroid/os/Environment|Ljava/io/File|Landroid/content/Context",
            r"getExternalStorage*|getExternalFilesDir|createTempFile|openFileOutput"
        )
        for m in rss:
            m: MethodClassAnalysis = m
            p_list: [(ClassAnalysis, object, int)] = m.get_xref_from()
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue

                # iterate parent methodsO
                item = (p_class, p_method)
                if item not in self.storage_issues:
                    self.storage_issues.append(item)
                break
Esempio n. 27
0
def AnalyzeAPK(_file, session=None, raw=False):
    """
    Analyze an android application and setup all stuff for a more quickly
    analysis!
    If session is None, no session is used at all. This is the default
    behaviour.
    If you like to continue your work later, it might be a good idea to use a
    session.
    A default session can be created by using :meth:`~get_default_session`.

    :param _file: the filename of the android application or a buffer which represents the application
    :type _file: string (for filename) or bytes (for raw)
    :param session: A session (default: None)
    :param raw: boolean if raw bytes are supplied instead of a filename
    :rtype: return the :class:`~androguard.core.bytecodes.apk.APK`, list of :class:`~androguard.core.bytecodes.dvm.DalvikVMFormat`, and :class:`~androguard.core.analysis.analysis.Analysis` objects
    """
    log.debug("AnalyzeAPK")

    if session:
        log.debug("Using existing session {}".format(session))
        if raw:
            data = _file
            filename = hashlib.md5(_file).hexdigest()
        else:
            with open(_file, "rb") as fd:
                data = fd.read()
                filename = _file

        digest = session.add(filename, data)
        return session.get_objects_apk(filename, digest)
    else:
        log.debug("Analysing without session")
        a = APK(_file, raw=raw)
        # FIXME: probably it is not necessary to keep all DalvikVMFormats, as
        # they are already part of Analysis. But when using sessions, it works
        # this way...
        d = []
        dx = Analysis()
        for dex in a.get_all_dex():
            df = DalvikVMFormat(dex, using_api=a.get_target_sdk_version())
            dx.add(df)
            d.append(df)
            df.set_decompiler(decompiler.DecompilerDAD(d, dx))

        dx.create_xref()

        return a, d, dx
Esempio n. 28
0
def parse_dx(dx: Analysis, fn_match=None, outfile=None):
    console = Console()
    out = {}
    out.update(JNI_COMMON)
    count = 0
    for cx in dx.get_internal_classes():
        methods = parse_class_def(cx.get_class())
        count += 1
        if not methods:
            continue
        cname = methods[0].jclass
        if fn_match and not fn_match(cname):
            continue
        for m in methods:
            out.update(m.as_dict)
    console.log(f"Parse {count} classes.")
    console.log(f"Found {len(out)} JNI methods.")
    if not outfile:
        console.print_json(data=out)
    else:
        with open(outfile, 'w') as f:
            json.dump(out, f, indent=2, ensure_ascii=False)
Esempio n. 29
0
    def __analyse_remote_webview_debugging__(self, a: apk.APK, dx: Analysis):
        print("analysing webview debugging options")
        # find WebView debug function
        methods = dx.find_methods("Landroid/webkit/WebView",
                                  "setWebContentsDebuggingEnabled")
        self.webview_debugs: [(ClassAnalysis, EncodedMethod)] = []
        for m in methods:
            # check its parent method to find wrong parameters
            m: MethodClassAnalysis = m
            p_list: [(ClassAnalysis, object, int)] = m.get_xref_from()
            for (p_class, p_method, _) in p_list:
                if type(p_method) is not EncodedMethod:
                    continue

                # iterate parent methods
                p_method: EncodedMethod = p_method
                # find wrong encryption options
                code: str = p_method.get_source()
                item = (p_class, p_method)
                if "setWebContentsDebuggingEnabled(1)" in code:
                    if item not in self.webview_debugs:
                        self.webview_debugs.append(item)
                    break
        pass
Esempio n. 30
0
    def __analyse_trackers__(self, a: apk.APK, dx: Analysis):
        print("analysing trackers")
        self.trackers: [{str: str}] = []  # [{name : website}]
        # load trackers. We use exodus tracker list: https://etip.exodus-privacy.eu.org/trackers/all
        with open(
                os.path.join(os.path.dirname(__file__),
                             "assets" + os.path.sep + 'trackers.json'),
                'r') as file:
            json_obj = json.load(file)
            trackers = json_obj['trackers']
            # check the code signature
            for item in trackers:
                name = item['name']
                website = item['website']
                code_signature: str = item['code_signature']
                code_signature = "L" + code_signature.replace('.', '/')
                if code_signature[-1] != '/':
                    code_signature = code_signature + '/'

                code_signature = code_signature + '.*'  # make the code signature as Lcom/example/.*
                results = dx.find_classes(code_signature, True)
                for _ in results:  # contains such tracker
                    self.trackers.append({name: website})
                    break
Esempio n. 31
0
def get_callback_list(mca: MethodClassAnalysis, dx: Analysis, ast: Dict, callback_interfaces: List):
    classname: str = mca.method.class_name
    methodname: str = mca.name
    method_ast = get_method_from_ast(methodname, classname, ast)
    if method_ast:
        method_ast_body = method_ast['body']
    else:
        return []
    method_invocs = get_method_invocations(method_ast_body)

    registered_callbacks = []
    for invoc in method_invocs:
        arg_types = get_method_arg_type(invoc)
        for typ in arg_types:
            cls: ClassAnalysis = dx.get_class_analysis(typ)
            if isinstance(cls, ClassAnalysis):
                for interface in cls.implements:
                    if interface in callback_interfaces:
                        print(
                            "Found registered resource: ", typ, "implements ", interface
                        )
                        registered_callbacks.append((typ, interface))

    return registered_callbacks
Esempio n. 32
0
    def addDEX(self, filename, data, dx=None, postpone_xref=False):
        """
        Add a DEX file to the Session and run analysis.

        :param filename: the (file)name of the DEX file
        :param data: binary data of the dex file
        :param dx: an existing Analysis Object (optional)
        :param postpone_xref: True if no xref shall be created, and will be called manually
        :return: A tuple of SHA256 Hash, DalvikVMFormat Object and Analysis object
        """
        digest = hashlib.sha256(data).hexdigest()
        log.debug("add DEX:%s" % digest)

        log.debug("Parsing format ...")
        d = DalvikVMFormat(data)
        log.debug("added DEX:%s" % digest)

        self.analyzed_files[filename].append(digest)
        self.analyzed_digest[digest] = filename

        self.analyzed_dex[digest] = d

        if dx is None:
            dx = Analysis()

        dx.add(d)
        if not postpone_xref:
            dx.create_xref()

        # TODO: If multidex: this will called many times per dex, even if already set
        for d in dx.vms:
            # TODO: allow different decompiler here!
            d.set_decompiler(DecompilerDAD(d, dx))
            d.set_vmanalysis(dx)
        self.analyzed_vms[digest] = dx

        if self.export_ipython:
            log.debug("Exporting in ipython")
            d.create_python_export()

        return digest, d, dx
Esempio n. 33
0
from androguard.core.bytecodes.apk import APK
from androguard.core.bytecodes.dvm import DalvikVMFormat
from androguard.core.analysis.analysis import Analysis
from androguard.decompiler.decompiler import DecompilerJADX
from androguard.core.androconf import show_logging
import logging

# Enable log output
show_logging(level=logging.DEBUG)

# Load our example APK
a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk")

# Create DalvikVMFormat Object
d = DalvikVMFormat(a)
# Create Analysis Object
dx = Analysis(d)

# Load the decompiler
# Set the path to the jadx executable!
decompiler = DecompilerJADX(d, dx, jadx="/home/vagrant/jadx/build/jadx/bin/jadx")

# propagate decompiler and analysis back to DalvikVMFormat
d.set_decompiler(decompiler)
d.set_vmanalysis(dx)

# Now you can do stuff like:
for m in d.get_methods()[:10]:
    print(m)
    print(decompiler.get_source_method(m))
def main():
    for path in samples():
        print(path)
        logging.error("Processing" + path)

        tests_apk = ["is_valid_APK", "get_filename", "get_app_name", "get_app_icon",
                 "get_package", "get_androidversion_code", "get_androidversion_name",
                 "get_files", "get_files_types", "get_files_crc32", "get_files_information",
                 "get_raw", "get_dex", "get_all_dex", "get_main_activity",
                 "get_activities", "get_services", "get_receivers", "get_providers",
                 "get_permissions", "get_details_permissions", "get_requested_aosp_permissions",
                 "get_requested_aosp_permissions_details", "get_requested_third_party_permissions",
                 "get_declared_permissions", "get_declared_permissions_details", "get_max_sdk_version",
                 "get_min_sdk_version", "get_target_sdk_version", "get_libraries", "get_android_manifest_axml",
                 "get_android_manifest_xml", "get_android_resources", "get_signature_name", "get_signature_names",
                 "get_signature", "get_signatures"]

        tests_dex = ["get_api_version", "get_classes_def_item", "get_methods_id_item", "get_fields_id_item",
                     "get_codes_item", "get_string_data_item",
                     "get_debug_info_item", "get_header_item", "get_class_manager", "show",
                     "save", "get_classes_names", "get_classes",
                     "get_all_fields", "get_fields", "get_methods", "get_len_methods",
                     "get_strings", "get_format_type", "create_python_export",
                     "get_BRANCH_DVM_OPCODES", "get_determineNext",
                     "get_determineException", "print_classes_hierarchy",
                     "list_classes_hierarchy", "get_format"]

        try:
            # Testing APK
            a = APK(path)
            for t in tests_apk:
                print(t)
                x = getattr(a, t)
                try:
                    x()
                except Exception as aaa:
                    print(aaa)
                    traceback.print_exc()
                    print(path, aaa, file=sys.stderr)
                    logging.exception("{} .. {}".format(path, t))


            # Testing DEX
            for dex in a.get_all_dex():
                d = DalvikVMFormat(dex)
                dx = Analysis(d)
                d.set_vmanalysis(dx)

                # Test decompilation
                for c in d.get_classes():
                    for m in c.get_methods():
                        mx = dx.get_method(m)
                        ms = DvMethod(mx)
                        try:
                            ms.process(doAST=True)
                        except Exception as aaa:
                            print(aaa)
                            traceback.print_exc()
                            print(path, aaa, file=sys.stderr)
                            logging.exception("{} .. {} .. {}".format(path, c.get_name(), m.get_name()))
                        ms2 = DvMethod(mx)
                        try:
                            ms2.process(doAST=False)
                        except Exception as aaa:
                            print(aaa)
                            traceback.print_exc()
                            print(path, aaa, file=sys.stderr)
                            logging.exception("{} .. {} .. {}".format(path, c.get_name(), m.get_name()))

                # Other tests
                for t in tests_dex:
                    print(t)
                    x = getattr(d, t)
                    try:
                        x()
                    except Exception as aaa:
                        print(aaa)
                        traceback.print_exc()
                        print(path, aaa, file=sys.stderr)
                        logging.exception("{} .. {}".format(path, t))

        except KeyboardInterrupt:
            raise
        except FileNotFoundError:
            pass
        except Exception as e:
            print(e)
            traceback.print_exc()
            print(path, e, file=sys.stderr)
            logging.exception(path)