示例#1
0
    def each(self, target):
        self.results = dict()

        try:
            apk, vm, vm_analysis = AnalyzeAPK(target)

            # First, get basic information about the APK
            self.results['name'] = apk.get_app_name()
            self.results['package'] = apk.get_package()
            self.results['permissions'] = apk.get_permissions()
            self.results['main_activity'] = apk.get_main_activity()
            self.results['receivers'] = apk.get_receivers()
            self.results['services'] = apk.get_services()
            self.results['main_activity_content'] = vm.get_class("L{};".format(
                self.results['main_activity']).replace('.', '/')).get_source()
        except:
            apk = None
            vm, vm_analysis = AnalyzeDex(target)
            self.results['dex'] = True

        # Then, run all the APK Plugins in order to see if this is a known malware
        for plugin in APKPlugin.__subclasses__():
            plugin = plugin(target, apk, vm, vm_analysis)
            plugin.apply(self)

        return True
示例#2
0
class Apkinfo:
    def __init__(self, apk_path):
        print(f"Init {apk_path}")
        self.apk, self.dalvikvmformat, self.analysis = AnalyzeAPK(apk_path)
        # get package name and the main launch activity to start the app.
        self._packageName = self.apk.get_package()
        self._mainActivity = self.apk.get_main_activity()

    @property
    def package_name(self):
        return self._packageName

    @property
    def main_activity(self):
        return self._mainActivity

    def get_android_api(self):
        """
        Returns a list of Android APIs call.
        :return: (class_name, method_name)
        """
        method_analysis = self.analysis.get_android_api_usage()
        for meth in method_analysis:
            yield meth.class_name, meth.name

    def launch_activity(self):
        return f"{self._packageName}/{self._mainActivity}"
示例#3
0
    def each(self, target):
        self.results = dict(name=None,
                            files=[],
                            package=None,
                            permissions=[],
                            declared_permissions=[],
                            main_activity=None,
                            activities=[],
                            receivers=[],
                            services=[],
                            manifest=None,
                            libraries=[],
                            main_activity_content=None,
                            internal_classes=[])

        try:
            apk, vm, vm_analysis = AnalyzeAPK(target)

            # First, get basic information about the APK
            self.results['name'] = apk.get_app_name()
            self.results['files'] = apk.get_files_types()
            self.results['package'] = apk.get_package()
            self.results['permissions'] = apk.get_details_permissions()
            self.results[
                'declared_permissions'] = apk.get_declared_permissions_details(
                )
            self.results['main_activity'] = apk.get_main_activity()
            self.results['activities'] = apk.get_activities()
            self.results['receivers'] = apk.get_receivers()
            self.results['services'] = apk.get_services()
            self.results['manifest'] = apk.get_android_manifest_axml().get_xml(
            )
            self.results['libraries'] = list(apk.get_libraries())
            self.results['main_activity_content'] = None
            self.results['internal_classes'] = []
            try:
                self.results['main_activity_content'] = self.results[
                    'main_activity_content'] = vm[0].get_class(
                        "L{};".format(self.results['main_activity']).replace(
                            '.', '/')).get_source()
            except:
                self.log('error', traceback.print_exc())

            try:
                self.results['internal_classes'] = self._get_internal_classes(
                    vm_analysis)
                self._store_internal_classes()
            except:
                self.log('error', traceback.print_exc())

            # Then, run all the APK Plugins in order to see if this is a known malware
            for plugin in APKPlugin.__subclasses__():
                plugin = plugin(target, apk, vm, vm_analysis)
                plugin.apply(self)

        except:
            self.log('error', traceback.print_exc())

        return True
示例#4
0
#!/usr/bin/python2
from collections import defaultdict

from androguard.misc import AnalyzeAPK

apk_path = raw_input('Provide path to apk\n')

print('Analyzing...')
apk, dex, vm = AnalyzeAPK(apk_path)

print('\nActivities:')
for activity in apk.get_activities():
    print(activity)

print('\nMain activity:')
print(apk.get_main_activity())

print('\nSuper dangerous permissions:')
for perm, details in apk.get_details_permissions().items():
    if details[0] == 'dangerous':
        # Protection levels: https://developer.android.com/guide/topics/permissions/overview#normal-dangerous
        print(perm)

print('\nServices:')
for service in apk.get_services():
    print(service)

print('\nBroadcasts:')
for receiver in apk.get_receivers():
    print(receiver)
 'min_sdk_version':
 int(apk.get_min_sdk_version()),
 'version_code':
 apk.xml['AndroidManifest.xml'].get(
     '{http://schemas.android.com/apk/res/android}versionCode'),
 'libraries':
 list(apk.get_libraries()),
 'androidtv':
 apk.is_androidtv(),
 'target_sdk_version':
 apk.get_target_sdk_version(),
 'api_keys': {},  # TODO
 'activities':
 apk.get_activities(),
 'main_activity':
 apk.get_main_activity(),
 'receivers':
 apk.get_receivers(),
 'signature_name':
 apk.get_signature_name(),
 'dexes': {},
 'displayed_version':
 apk.xml['AndroidManifest.xml'].get(
     '{http://schemas.android.com/apk/res/android}versionName'),
 'services':
 apk.get_services(),
 'permissions':
 apk.get_permissions(),
 'cordova':
 None,  #What is this ?
 'functionalities': {},
示例#6
0
文件: static.py 项目: muhzii/cuckoo
class AndroidPackage(object):
    """Static android information."""
    def __init__(self, filepath):
        self.filepath = filepath

        self.apk = None
        self.analysis = None

    def _get_detailed_permissions(self):
        """Return a list of all permission requests by the application."""
        perms = []
        for k, v in self.apk.get_details_permissions().items():
            perms.append({
                "name": k,
                "protection_level": v[0],
                "description": v[2]
            })

        return perms

    def _enumerate_services(self):
        """Return a list of all services with their actions"""
        services = []
        for _service in self.apk.get_services():
            service = {}
            service["name"] = _service
            service["action"] = []

            intent_filters = self.apk.get_intent_filters("service", _service)
            if "action" in intent_filters:
                service["action"] = intent_filters["action"]

            services.append(service)

        return services

    def _enumerate_receivers(self):
        """Return a list of all BroadcastReceiver's with their actions"""
        receivers = []
        for _receiver in self.apk.get_receivers():
            receiver = {}
            receiver["name"] = _receiver
            receiver["action"] = []

            intent_filters = self.apk.get_intent_filters("receiver", _receiver)
            if "action" in intent_filters:
                receiver["action"] = intent_filters["action"]

            receivers.append(receiver)

        return receivers

    def _enumerate_apk_files(self):
        """Return a list of files in the APK."""
        files = []
        for filename, filetype in self.apk.get_files_types().items():
            buf = self.apk.zip.read(filename)
            files.append({
                "name": filename,
                "md5": hashlib.md5(buf).hexdigest(),
                "size": len(buf),
                "type": filetype,
            })

        return files

    def _enumerate_encrypted_assets(self):
        """Returns a list of files in the APK assets that have high entropy."""
        files = []
        for filename, filetype in self.apk.get_files_types().items():
            if "assets" in filename:
                buf = self.apk.zip.read(filename)
                file_entropy = entropy.shannon_entropy(buf)
                if file_entropy > 0.9:
                    files.append({
                        "name": filename,
                        "entropy": file_entropy,
                        "size": len(buf),
                        "type": filetype,
                    })

        return files

    def _get_certificates_info(self):
        """Return a list of APK certificates"""
        certficates = []
        for cert in self.apk.get_certificates():
            not_valid_after = cert['tbs_certificate']['validity'][
                'not_after'].native
            not_valid_before = cert['tbs_certificate']['validity'][
                'not_before'].native
            certficates.append({
                "sha1":
                cert.sha1.encode("hex"),
                "sha256":
                cert.sha256.encode("hex"),
                "issuer":
                cert.issuer.human_friendly,
                "subject":
                cert.subject.human_friendly,
                "not_valid_after":
                not_valid_after.strftime("%Y-%m-%d %H:%M:%S"),
                "not_valid_before":
                not_valid_before.strftime("%Y-%m-%d %H:%M:%S"),
                "public_key_algorithm":
                cert.public_key.algorithm,
                "public_key_size":
                "%d bit" % cert.public_key.bit_size,
                "signature_algorithm":
                cert.signature_algo + " with " + cert.hash_algo,
                "signature":
                cert.signature.encode("hex"),
                "serial_number":
                str(cert.serial_number)
            })

        return certficates

    def _enumerate_native_methods(self):
        """Return a list of all methods compiled in the application"""
        methods = []
        for mca in self.analysis.get_methods():
            if mca.is_external():
                continue

            if not mca.get_method().get_access_flags() & 0x0100:
                continue

            methods.append(self._get_pretty_method(mca))

        return methods

    def _get_pretty_method(self, mca):
        """Return a string representation of an API method.
        @param mca: MethodClassAnalysis object.
        """
        class_name = mca.get_method().get_class_name().replace("/", ".")[1:-1]
        method_name = mca.get_method().get_name()

        return "%s.%s%s" % (class_name, method_name, mca.descriptor)

    def _enumerate_api_calls(self):
        """Return a dictionary of all APIs with their xrefs."""
        classes = []
        exclude_pattern = re.compile(
            "^(Lcom/google/|Landroid|Ljava|Lcom/sun/|Lorg/apache/|"
            "Lorg/spongycastle|Lmyjava/|Lkotlin/)")

        for ca in self.analysis.get_classes():
            if ca.is_external():
                continue

            if exclude_pattern.match(ca.name):
                continue

            classes.append(ca.name)

        calls = []
        for class_name in classes:
            for mca in self.analysis.find_methods(class_name):
                xrefs_to = []
                for _, m, _ in mca.get_xref_to():
                    callee_class = m.get_class_name().replace("/", ".")[1:-1]
                    callee_api = "%s.%s" % (callee_class, m.get_name())
                    xrefs_to.append(callee_api)

                if not xrefs_to:
                    continue

                api = {}
                api["name"] = self._get_pretty_method(mca)
                api["callees"] = xrefs_to

                calls.append(api)

        return calls

    def run(self):
        """Run androguard to extract static APK information
        @return: dict of static features.
        """
        from androguard.misc import AnalyzeAPK

        logging.getLogger("androguard.dvm").setLevel(logging.WARNING)
        logging.getLogger("androguard.analysis").setLevel(logging.WARNING)
        logging.getLogger("androguard.misc").setLevel(logging.WARNING)
        logging.getLogger("androguard.apk").setLevel(logging.CRITICAL)

        try:
            self.apk, _, self.analysis = AnalyzeAPK(self.filepath)
        except (OSError, zipfile.BadZipfile) as e:
            log.error("Error parsing APK file: %s", e)
            return None

        manifest = {}
        if self.apk.is_valid_APK():
            manifest["package"] = self.apk.get_package()
            manifest["services"] = self._enumerate_services()
            manifest["receivers"] = self._enumerate_receivers()
            manifest["providers"] = self.apk.get_providers()
            manifest["activities"] = self.apk.get_activities()
            manifest["main_activity"] = self.apk.get_main_activity()
            manifest["permissions"] = self._get_detailed_permissions()

        apkinfo = {}
        apkinfo["manifest"] = manifest
        apkinfo["files"] = self._enumerate_apk_files()
        apkinfo["encrypted_assets"] = self._enumerate_encrypted_assets()
        apkinfo["is_signed_v1"] = self.apk.is_signed_v1()
        apkinfo["is_signed_v2"] = self.apk.is_signed_v2()
        apkinfo["certificates"] = self._get_certificates_info()
        apkinfo["native_methods"] = self._enumerate_native_methods()
        apkinfo["api_calls"] = self._enumerate_api_calls()

        return apkinfo
示例#7
0
    def run(self):
        app.logger.info('new analysis')
        s = Session()
        self.status = 'Analyzing APK'
        a, d, dx = AnalyzeAPK(self.target_file,
                              session=s)  #APK,list[DalvikVMFormat],Analysis
        print(type(a), type(d[0]), type(dx))
        #cache activities, receivers, services, and providers, because for some reason, saving the Session causes a bug, breaking getters
        """i.e. bytecodes/apk.py", line 582, in get_elements
                for item in self.xml[i].findall('.//' + tag_name):
            TypeError: string indices must be integers """
        activities = a.get_activities()
        receivers = a.get_receivers()
        services = a.get_services()
        providers = a.get_providers()
        self.main_activity = a.get_main_activity()
        if self.session_save_file:
            sys.setrecursionlimit(100000000)
            self.status = 'Saving session file'
            Save(s, self.session_save_file)

        cached_analyses.append({'md5': self.md5, 'analysis': (a, d, dx)})

        #gather all classes from dexs 'd'
        #classes = get_all_classes_from_dexs(d)
        classes = dx.classes
        total_num = len(classes)
        done = 0  #num of done classes
        #result_classes contains the completed analysis info for each class run through the ClassAnalysis object
        result_classes = []
        analysis_start_time = time.time()

        self.status = 'Getting all classes'
        for c_name, c_analysis in classes.items():
            ca = ClassAnalysis(c_name, c_analysis, activities, receivers,
                               services, providers)
            ca_result = ca.run()
            result_classes.append(ca_result)
            done += 1
            if done % ceil(total_num / 100) == 0:
                self.progress += 1
                #app.logger.info(self.progress)
                # with app.test_request_context('/'):
                #     socketio.emit('newstatus', {'data':self.progress}, namespace='/status')
        analysis_end_time = time.time()
        analysis_total_time = analysis_end_time - analysis_start_time

        #debugging:
        self.status = 'Writing beforenetworkx debugging JSON'
        with open(self.graph_out_path + '.beforenetworkx', 'w') as f:
            json.dump(result_classes,
                      f,
                      indent=4,
                      separators=(',', ': '),
                      sort_keys=True)

        #create a networkx graph given the completed analyses in result_classess
        create_graph_start_time = time.time()
        self.status = 'Creating graph out of {} classes analyzed'.format(
            len(result_classes))
        graph = create_graph(classes=result_classes)
        create_graph_end_time = time.time()
        create_graph_total_time = create_graph_end_time - create_graph_start_time

        #write graph to file: graph_out_path
        write_graph_start_time = time.time()
        self.status = 'Writing graph to disk'
        write_graph(graph, self.graph_out_path)
        write_graph_end_time = time.time()
        write_graph_total_time = write_graph_end_time - write_graph_start_time

        #build and write another graph that contains only providers,receivers,activities, and services
        if self.component_subgraph_out_path:
            component_names = []
            self.status = 'Getting component nodes from graph'
            for node in graph:
                node_tmp = graph.node[node]
                if node_tmp[
                        'component_type'] != NonComponentType.EXTERNAL and node_tmp[
                            'component_type'] != NonComponentType.INTERNAL:
                    component_names.append(node_tmp['name'])
            self.status = 'Creating subgraph containing only components'
            subgraph = get_class_subgraph(graph, class_names=component_names)
            self.status = 'Writing subgraph to disk'
            write_graph(subgraph, self.component_subgraph_out_path)

        #app metadata for misc/debugging
        apk_size = os.path.getsize(self.target_file)
        self.status = 'Writing metadata'
        self.write_app_metadata(result_classes, a, analysis_total_time,
                                apk_size, create_graph_total_time,
                                write_graph_total_time)
        #debugging
        # with open(self.graph_out_path+'.runmetrics', 'w') as f:
        #     json.dump()

        self.progress = 100
        self.status = 'Done'
        self.paused.wait(
        )  #wait for caller to collect last status and reset event before finishing

        app.logger.info('done')
示例#8
0
outDexName = "EXTRACTED_DEX_FROM_" + tail

print()
print("======== KEY AND PACKAGE INFO ========")
outDexContent, locationDEX = DEXDecrypt.decrypt(a, d, dx, sys.argv[1])
with open(outDexName, "wb") as file:
    file.write(outDexContent)
    file.close()

#Search for the class with configuration parameters
cfg_src = source.getStringsClassSource(a, d, dx, outDexName)

#Decrypt the strings, currently returns C2 URL
print()
print("======== DECRYPTED STRINGS ========")
decrypted_cfg_src = decryptConfig.all(cfg_src)

#Collect and print other  IoC's
appName = a.get_app_name()
mainActivity = a.get_main_activity()
minSDK = a.get_min_sdk_version()
sha1apk = FileHash('sha1').hash_file(sys.argv[1])
C2URL = decrypted_cfg_src
fileSize = os.path.getsize(sys.argv[1]) * (10**-6)

print()
print("======== IOC INFORMATION ========")
print("AppName, MainActivity, MINSDK, EncryptedDEX, SHA1Sum, C&C ,Size(MB)")
print(appName, ",", mainActivity, ",", minSDK, ",", locationDEX, ",", sha1apk,
      ",", C2URL, ",", fileSize)