예제 #1
0
    def testAPKManifest(self):
        from androguard.core.bytecodes.apk import APK
        a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk",
                testzip=True)

        self.assertEqual(a.get_app_name(), "TestsAndroguardApplication")
        self.assertEqual(a.get_app_icon(), "res/drawable-hdpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=120),
                         "res/drawable-ldpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=160),
                         "res/drawable-mdpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=240),
                         "res/drawable-hdpi/icon.png")
        self.assertIsNone(a.get_app_icon(max_dpi=1))
        self.assertEqual(a.get_main_activity(),
                         "tests.androguard.TestActivity")
        self.assertEqual(a.get_package(), "tests.androguard")
        self.assertEqual(a.get_androidversion_code(), '1')
        self.assertEqual(a.get_androidversion_name(), "1.0")
        self.assertEqual(a.get_min_sdk_version(), "9")
        self.assertEqual(a.get_target_sdk_version(), "16")
        self.assertIsNone(a.get_max_sdk_version())
        self.assertEqual(a.get_permissions(), [])
        self.assertEqual(a.get_declared_permissions(), [])
        self.assertTrue(a.is_valid_APK())
예제 #2
0
def get_apk_info(f, root=None):
    """
    获取apk信息
    :param root:
    :param f:
    :return:
    """
    if root:
        apk_path = os.path.join(root, f)
    else:
        apk_path = os.path.join(download_dir, f)

    apk_info = []
    try:
        apk = APK(apk_path)
        if apk.is_valid_APK():
            apk_info.append(f)
            apk_info.append(get_file_md5(apk_path))
            apk_info.append(apk.get_app_name())
            apk_info.append(apk.get_package())
            apk_info.append(get_cert_md5(apk))
            apk_info.append(apk.get_androidversion_name())
    except Exception as e:
        print(f + ' ->>', e)

    return apk_info
예제 #3
0
파일: apkinfo.py 프로젝트: LetMeR00t/cuckoo
    def run(self):
        """Run androguard to extract static android information
                @return: list of static features
        """
        self.key = "apkinfo"
        apkinfo = {}

        if "file" not in self.task["category"]:
            return

        from androguard.core.bytecodes.apk import APK
        from androguard.core.bytecodes.dvm import DalvikVMFormat
        from androguard.core.analysis.analysis import uVMAnalysis
        from androguard.core.analysis import analysis

        f = File(self.task["target"])
        if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
            if not os.path.exists(self.file_path):
                raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path)

            try:
                a = APK(self.file_path)
                if a.is_valid_APK():
                    manifest = {}
                    apkinfo["files"] = self._apk_files(a)
                    manifest["package"] = a.get_package()
                    # manifest["permissions"]=a.get_details_permissions_new()
                    manifest["main_activity"] = a.get_main_activity()
                    manifest["activities"] = a.get_activities()
                    manifest["services"] = a.get_services()
                    manifest["receivers"] = a.get_receivers()
                    # manifest["receivers_actions"]=a.get__extended_receivers()
                    manifest["providers"] = a.get_providers()
                    manifest["libraries"] = a.get_libraries()
                    apkinfo["manifest"] = manifest
                    # apkinfo["certificate"] = a.get_certificate()
                    static_calls = {}
                    if self.check_size(apkinfo["files"]):
                        vm = DalvikVMFormat(a.get_dex())
                        vmx = uVMAnalysis(vm)

                        static_calls["all_methods"] = self.get_methods(vmx)
                        static_calls["is_native_code"] = analysis.is_native_code(vmx)
                        static_calls["is_dynamic_code"] = analysis.is_dyn_code(vmx)
                        static_calls["is_reflection_code"] = analysis.is_reflection_code(vmx)

                        # static_calls["dynamic_method_calls"]= analysis.get_show_DynCode(vmx)
                        # static_calls["reflection_method_calls"]= analysis.get_show_ReflectionCode(vmx)
                        # static_calls["permissions_method_calls"]= analysis.get_show_Permissions(vmx)
                        # static_calls["crypto_method_calls"]= analysis.get_show_CryptoCode(vmx)
                        # static_calls["native_method_calls"]= analysis.get_show_NativeMethods(vmx)
                    else:
                        log.warning("Dex size bigger than: %s",
                                    self.options.decompilation_threshold)
                    apkinfo["static_method_calls"] = static_calls
            except (IOError, OSError, zipfile.BadZipfile) as e:
                raise CuckooProcessingError("Error opening file %s" % e)

        return apkinfo
예제 #4
0
    def run(self):
        """Run Google play unofficial python api the get the google play information
        @return: list of google play features
        """
        self.key = "googleplay"
        googleplay = {}

        if not HAVE_GOOGLEPLAY:
            log.error("Unable to import the GooglePlay library, has it been "
                      "installed properly?")
            return

        if "file" not in self.task["category"]:
            return

        f = File(self.task["target"])
        if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
            if not os.path.exists(self.file_path):
                raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path)

            android_id = self.options.get("android_id")
            google_login = self.options.get("google_login")
            google_password = self.options.get("google_password")
            # auth_token = self.options.get("auth_token", None)

            if not android_id and not google_login and not google_password:
                raise CuckooProcessingError("Google Play Credentials not configured, skip")

            try:
                a = APK(self.file_path)
                if a.is_valid_APK():
                    package = a.get_package()
                    # Connect
                    api = GooglePlayAPI(android_id)
                    api.login(google_login, google_password, None)

                    # Get the version code and the offer type from the app details
                    app_data = api.details(package)
                    app_detail = app_data.docV2.details.appDetails

                    if not app_detail.installationSize:
                        return googleplay

                    googleplay["title"] = app_detail.title
                    googleplay["app_category"] = app_detail.appCategory._values
                    googleplay["version_code"] = app_detail.versionCode
                    googleplay["app_type"] = app_detail.appType
                    googleplay["content_rating"] = app_detail.contentRating
                    googleplay["developer_email"] = app_detail.developerEmail
                    googleplay["developer_name"] = app_detail.developerName
                    googleplay["developer_website"] = app_detail.developerWebsite
                    googleplay["installation_size"] = app_detail.installationSize
                    googleplay["num_downloads"] = app_detail.numDownloads
                    googleplay["upload_date"] = app_detail.uploadDate
                    googleplay["permissions"] = app_detail.permission._values
            except (IOError, OSError, zipfile.BadZipfile) as e:
                raise CuckooProcessingError("Error opening file %s" % e)

        return googleplay
예제 #5
0
    def run(self):
        """Run androguard to extract static android information
                @return: list of static features
        """
        self.key = "apkinfo"
        apkinfo = {}

        if "file" not in self.task["category"] or not HAVE_ANDROGUARD:
            return

        f = File(self.task["target"])
        if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
            if not os.path.exists(self.file_path):
                raise CuckooProcessingError(
                    "Sample file doesn't exist: \"%s\"" % self.file_path)

            try:
                a = APK(self.file_path)
                if a.is_valid_APK():
                    manifest = {}
                    apkinfo["files"] = self._apk_files(a)
                    manifest["package"] = a.get_package()
                    # manifest["permissions"]=a.get_details_permissions_new()
                    manifest["main_activity"] = a.get_main_activity()
                    manifest["activities"] = a.get_activities()
                    manifest["services"] = a.get_services()
                    manifest["receivers"] = a.get_receivers()
                    # manifest["receivers_actions"]=a.get__extended_receivers()
                    manifest["providers"] = a.get_providers()
                    manifest["libraries"] = a.get_libraries()
                    apkinfo["manifest"] = manifest
                    # apkinfo["certificate"] = a.get_certificate()
                    static_calls = {}
                    if self.check_size(apkinfo["files"]):
                        vm = DalvikVMFormat(a.get_dex())
                        vmx = uVMAnalysis(vm)

                        static_calls["all_methods"] = self.get_methods(vmx)
                        static_calls[
                            "is_native_code"] = analysis.is_native_code(vmx)
                        static_calls["is_dynamic_code"] = analysis.is_dyn_code(
                            vmx)
                        static_calls[
                            "is_reflection_code"] = analysis.is_reflection_code(
                                vmx)

                        # static_calls["dynamic_method_calls"]= analysis.get_show_DynCode(vmx)
                        # static_calls["reflection_method_calls"]= analysis.get_show_ReflectionCode(vmx)
                        # static_calls["permissions_method_calls"]= analysis.get_show_Permissions(vmx)
                        # static_calls["crypto_method_calls"]= analysis.get_show_CryptoCode(vmx)
                        # static_calls["native_method_calls"]= analysis.get_show_NativeMethods(vmx)
                    else:
                        log.warning("Dex size bigger than: %s",
                                    self.options.decompilation_threshold)
                    apkinfo["static_method_calls"] = static_calls
            except (IOError, OSError, BadZipfile) as e:
                raise CuckooProcessingError("Error opening file %s" % e)

        return apkinfo
예제 #6
0
def main(apk_path):
    try:
        apk = APK(apk_path)
    except Exception as ex:
        return False, ex
    if not apk.is_valid_APK():
        return False, 'It is not a valid apk'

    activities = []
    for act in apk.get_activities():
        if not filtered(act, FILTERED_ACTIVITY):
            activities.append(act)
예제 #7
0
파일: apk.py 프로젝트: alephre/aleph
    def parse_apk(self, data):

        try:
            apk = AG_APK(data, raw=True)
            if apk.is_valid_APK():
                return apk
            else:
                self.logger.debug("Zip file %s is not a valid APK file" %
                                  self.sample.path)
        except Exception as ex:
            self.logger.warning("Could not parse %s because of %s",
                                self.sample.path, ex)

        return None
예제 #8
0
파일: objects.py 프로젝트: muhzii/cuckoo
    def get_apk_entry(self):
        """Get the entry point for this APK. The entry point is denoted by a
        package and main activity name."""
        logging.getLogger("androguard.axml").setLevel(logging.WARNING)
        logging.getLogger("androguard.core.api_specific_resources").setLevel(
            logging.WARNING)

        filetype = self.get_type()
        if "Zip archive data" not in filetype and "Java archive data" not in filetype:
            return "", ""

        from androguard.core.bytecodes.apk import APK

        try:
            a = APK(self.file_path)
            if not a.is_valid_APK():
                return "", ""

            package = a.get_package()
            if not package:
                log.warning("Unable to find the main package, this analysis "
                            "will probably fail.")
                return "", ""

            main_activity = a.get_main_activity()
            if main_activity:
                log.debug("Picked package %s and main activity %s.", package,
                          main_activity)
                return package, main_activity

            activities = a.get_activities()
            for activity in activities:
                if "main" in activity or "start" in activity:
                    log.debug(
                        "Choosing package %s and main activity due to "
                        "its name %s.", package, activity)
                    return package, activity

            if activities and activities[0]:
                log.debug("Picked package %s and the first activity %s.",
                          package, activities[0])
                return package, activities[0]
        except Exception as e:
            log.warning("Error extracting package and main activity: %s.", e)

        return "", ""
예제 #9
0
def extract_attributes(sha256):
    with NamedTemporaryFile() as f:
        f.write(default_storage.open(sha256).read())
        f.seek(0)

        sign = ApplicationSignature.compute_from_apk(f.name)
        package = sign.handle
        sign = sign.to_dict()

        a = APK(f.name)
        sign['uploaded_at'] = datetime.now()
        sign['sha256'] = sha256
        sign['activities'] = a.get_activities()
        sign['features'] = a.get_features()
        sign['libraries'] = a.get_libraries()
        sign['main_activity'] = a.get_activities()
        sign['min_sdk_version'] = a.get_min_sdk_version()
        sign['max_sdk_version'] = a.get_max_sdk_version()
        sign['target_sdk_version'] = a.get_target_sdk_version()
        sign['permissions'] = a.get_permissions()
        sign['aosp_permissions'] = a.get_requested_aosp_permissions()
        sign[
            'third_party_permissions'] = a.get_requested_third_party_permissions(
            )
        sign['providers'] = a.get_providers()
        sign['receivers'] = a.get_receivers()
        sign['services'] = a.get_services()
        sign['is_valid'] = a.is_valid_APK()
        sign['is_signed'] = a.is_signed()
        sign['is_signed_v1'] = a.is_signed_v1()
        sign['is_signed_v2'] = a.is_signed_v2()
        sign['is_signed_v3'] = a.is_signed_v3()

        if not es.exists(settings.ELASTICSEARCH_APK_INDEX, id=sha256):
            es.index(index=settings.ELASTICSEARCH_APK_INDEX,
                     id=sha256,
                     body=sign)
        else:
            es.update(index=settings.ELASTICSEARCH_APK_INDEX,
                      id=sha256,
                      body={'doc': sign},
                      retry_on_conflict=5)
    del a, sign, f
    gc.collect()

    return package
예제 #10
0
def extract_apk_permisson(name,category):
    path = '/media/新加卷/begin_android_english/'+category+'/'+name+'.apk'
    try:
        apk=APK(path)
        if apk.is_valid_APK():
            package=apk.get_package()
            permissions=apk.get_permissions()
            # clean repeat permission
            simple_permissions=set()
            for p in permissions:
                p=p.split('.')[-1]
                if PERMISSIONS.has_key(p):
                    simple_permissions.add(p)

            insert_sql='insert into apk_permission(package,category'
            attrs=','

            for permission in simple_permissions:
                    attrs=attrs+permission+','

            attrs=attrs.rstrip(',')
            values="values ('%s','%s',"%(package,category)
            for i in range(len(simple_permissions)):
                values=values+'1,'
            values=values.rstrip(',')
            values=values+')'

            insert_sql=insert_sql+attrs+') '+values

            #print insert_sql
            db.insert(insert_sql)

            print ('analysis %s'%(path))
        else:
            print('%s is not valid apk'%(path))
    except:

        etype, evalue, tracebackObj = sys.exc_info()[:3]
        print ('apk:%s errortype:%s errorvalue:%s'%(path,etype,evalue))
    finally:
        sql = "update apk set state = 0 where package='%s'"%name
        print sql
        db1.update(sql)
        print 1
예제 #11
0
    def testAPKManifest(self):
        from androguard.core.bytecodes.apk import APK
        a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk", testzip=True)

        self.assertEqual(a.get_app_name(), "TestsAndroguardApplication")
        self.assertEqual(a.get_app_icon(), "res/drawable-hdpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=120), "res/drawable-ldpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=160), "res/drawable-mdpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=240), "res/drawable-hdpi/icon.png")
        self.assertIsNone(a.get_app_icon(max_dpi=1))
        self.assertEqual(a.get_main_activity(), "tests.androguard.TestActivity")
        self.assertEqual(a.get_package(), "tests.androguard")
        self.assertEqual(a.get_androidversion_code(), '1')
        self.assertEqual(a.get_androidversion_name(), "1.0")
        self.assertEqual(a.get_min_sdk_version(), "9")
        self.assertEqual(a.get_target_sdk_version(), "16")
        self.assertIsNone(a.get_max_sdk_version())
        self.assertEqual(a.get_permissions(), [])
        self.assertEqual(a.get_declared_permissions(), [])
        self.assertTrue(a.is_valid_APK())
예제 #12
0
파일: objects.py 프로젝트: msr00t/cuckoo
    def get_apk_entry(self):
        """Get the entry point for this APK. The entry point is denoted by a
        package and main activity name."""
        filetype = self.get_type()
        if "Zip archive data" not in filetype and "Java archive data" not in filetype:
            return "", ""

        from androguard.core.bytecodes.apk import APK

        try:
            a = APK(self.file_path)
            if not a.is_valid_APK():
                return "", ""

            package = a.get_package()
            if not package:
                log.warning("Unable to find the main package, this analysis "
                            "will probably fail.")
                return "", ""

            main_activity = a.get_main_activity()
            if main_activity:
                log.debug("Picked package %s and main activity %s.",
                          package, main_activity)
                return package, main_activity

            activities = a.get_activities()
            for activity in activities:
                if "main" in activity or "start" in activity:
                    log.debug("Choosing package %s and main activity due to "
                              "its name %s.", package, activity)
                    return package, activity

            if activities and activities[0]:
                log.debug("Picked package %s and the first activity %s.",
                          package, activities[0])
                return package, activities[0]
        except Exception as e:
            log.warning("Error extracting package and main activity: %s.", e)

        return "", ""
예제 #13
0
    def run(self):
        """Run androguard to extract static android information
                @return: list of static features
        """
        self.key = "apkinfo"
        apkinfo = {}

        if "file" not in self.task["category"] or not HAVE_ANDROGUARD:
            return

        f = File(self.task["target"])
        #if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
        if not os.path.exists(self.file_path):
            raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path)

        try:
            a = APK(self.file_path)
            if a.is_valid_APK():
                manifest = {}

                apkinfo["files"] = self._apk_files(a)
                manifest["package"] = a.get_package()
                apkinfo["hidden_payload"] = []

                for file in apkinfo["files"]:
                    if self.file_type_check(file):
                       apkinfo["hidden_payload"].append(file)

                apkinfo["files_flaged"] = self.files_name_map

                manifest["permissions"]= get_permissions(a)
                manifest["main_activity"] = a.get_main_activity()
                manifest["activities"] = a.get_activities()
                manifest["services"] = a.get_services()
                manifest["receivers"] = a.get_receivers()
                manifest["receivers_actions"] = get_extended_receivers(a)
                manifest["providers"] = a.get_providers()
                manifest["libraries"] = a.get_libraries()
                apkinfo["manifest"] = manifest

                apkinfo["icon"] = get_apk_icon(self.file_path)
                certificate = get_certificate(self.file_path)
                if certificate:
                    apkinfo["certificate"] = certificate


                #vm = DalvikVMFormat(a.get_dex())
                #strings = vm.get_strings()
                strings = self._get_strings(self.file_path)
                apkinfo["interesting_strings"] = find_strings(strings)
                apkinfo["dex_strings"] = strings

                static_calls = {}
                if self.options.decompilation:
                    if self.check_size(apkinfo["files"]):
                        vm = DalvikVMFormat(a.get_dex())
                        vmx = uVMAnalysis(vm)

                        static_calls["all_methods"] = get_methods(vmx)
                        static_calls["is_native_code"] = analysis.is_native_code(vmx)
                        static_calls["is_dynamic_code"] = analysis.is_dyn_code(vmx)
                        static_calls["is_reflection_code"] = analysis.is_reflection_code(vmx)
                        static_calls["is_crypto_code"] = is_crypto_code(vmx)

                        static_calls["dynamic_method_calls"] = get_show_DynCode(vmx)
                        static_calls["reflection_method_calls"] = get_show_ReflectionCode(vmx)
                        static_calls["permissions_method_calls"] = get_show_Permissions(vmx)
                        static_calls["crypto_method_calls"] = get_show_CryptoCode(vmx)
                        static_calls["native_method_calls"] = get_show_NativeMethods(vmx)

                        classes = list()
                        for cls in vm.get_classes():
                            classes.append(cls.name)

                        static_calls["classes"] = classes

                else:
                    log.warning("Dex size bigger than: %s",
                                self.options.decompilation_threshold)

                apkinfo["static_method_calls"] = static_calls

        except (IOError, OSError, BadZipfile) as e:
            raise CuckooProcessingError("Error opening file %s" % e)

        return apkinfo
예제 #14
0
    def run(self):
        """Run androguard to extract static android information
                @return: list of static features
        """
        self.key = "apkinfo"
        apkinfo = {}

        if "file" not in self.task["category"] or not HAVE_ANDROGUARD:
            return

        #f = File(self.task["target"])
        #if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
        if not os.path.exists(self.file_path):
            raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path)

        apkinfo["APKiD"] = self._scan_APKiD(self.file_path)

        try:
            a = APK(self.file_path)
            if a.is_valid_APK():
                manifest = {}

                apkinfo["files"] = self._apk_files(a)
                apkinfo["encrypted_assets"] = self.find_encrypted_assets(a)
                manifest["package"] = a.get_package()
                apkinfo["hidden_payload"] = []

                for file in apkinfo["files"]:
                    if self.file_type_check(file):
                       apkinfo["hidden_payload"].append(file)

                apkinfo["files_flaged"] = self.files_name_map

                manifest["permissions"]= get_permissions(a)
                manifest["main_activity"] = a.get_main_activity()
                manifest["activities"] = a.get_activities()
                manifest["services"] = a.get_services()
                manifest["receivers"] = a.get_receivers()
                manifest["receivers_actions"] = get_extended_receivers(a)
                manifest["receivers_info"] = get_receivers_info(a)
                manifest["providers"] = a.get_providers()
                manifest["libraries"] = a.get_libraries()
                apkinfo["manifest"] = manifest

                apkinfo["icon"] = get_apk_icon(self.file_path)
                certificate = get_certificate(self.file_path)
                if certificate:
                    apkinfo["certificate"] = certificate


                #vm = DalvikVMFormat(a.get_dex())
                #strings = vm.get_strings()

                strings = self._get_strings(self.file_path)
                for subdir, dirs, files in os.walk(self.dropped_path):
                    for file in files:
                        path = os.path.join(subdir, file)
                        try:
                            extra_strings = self._get_strings(path)
                            strings = list(set(extra_strings + strings))
                        except:
                            pass

                apkinfo["dex_strings"] = strings

                static_calls = {}
                if self.options.decompilation:
                    if self.check_size(apkinfo["files"]):
                        vm = DalvikVMFormat(a.get_dex())
                        vmx = uVMAnalysis(vm)
                        # Be less verbose about androguard logging messages.
                        logging.getLogger("andro.runtime").setLevel(logging.CRITICAL)

                        static_calls["all_methods"] = get_methods(vmx)
                        static_calls["is_native_code"] = analysis.is_native_code(vmx)
                        static_calls["is_dynamic_code"] = analysis.is_dyn_code(vmx)
                        static_calls["is_reflection_code"] = analysis.is_reflection_code(vmx)
                        static_calls["is_crypto_code"] = is_crypto_code(vmx)

                        static_calls["dynamic_method_calls"] = get_show_DynCode(vmx)
                        static_calls["reflection_method_calls"] = get_show_ReflectionCode(vmx)
                        static_calls["permissions_method_calls"] = get_show_Permissions(vmx)
                        static_calls["crypto_method_calls"] = get_show_CryptoCode(vmx)
                        static_calls["native_method_calls"] = get_show_NativeMethods(vmx)

                        classes = list()
                        for cls in vm.get_classes():
                            classes.append(cls.name)

                        static_calls["classes"] = classes

                else:
                    log.warning("Dex size bigger than: %s",
                                self.options.decompilation_threshold)

                apkinfo["static_method_calls"] = static_calls

        except (IOError, OSError, BadZipfile) as e:
            raise CuckooProcessingError("Error opening file %s" % e)

        return apkinfo
예제 #15
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("target",
                        type=str,
                        nargs="?",
                        help="URL, path to the file or folder to analyze")
    parser.add_argument("-d",
                        "--debug",
                        action="store_true",
                        help="Enable debug logging")
    parser.add_argument(
        "--remote",
        type=str,
        action="store",
        default=None,
        help="Specify IP:port to a Cuckoo API server to submit remotely",
        required=False)
    parser.add_argument("--url",
                        action="store_true",
                        default=False,
                        help="Specify whether the target is an URL",
                        required=False)
    parser.add_argument("--package",
                        type=str,
                        action="store",
                        default="",
                        help="Specify an analysis package",
                        required=False)
    parser.add_argument("--custom",
                        type=str,
                        action="store",
                        default="",
                        help="Specify any custom value",
                        required=False)
    parser.add_argument("--owner",
                        type=str,
                        action="store",
                        default="",
                        help="Specify the task owner",
                        required=False)
    parser.add_argument("--timeout",
                        type=int,
                        action="store",
                        default=0,
                        help="Specify an analysis timeout",
                        required=False)
    parser.add_argument(
        "-o",
        "--options",
        type=str,
        action="store",
        default="",
        help=
        "Specify options for the analysis package (e.g. \"name=value,name2=value2\")",
        required=False)
    parser.add_argument(
        "--priority",
        type=int,
        action="store",
        default=1,
        help="Specify a priority for the analysis represented by an integer",
        required=False)
    parser.add_argument(
        "--machine",
        type=str,
        action="store",
        default="",
        help="Specify the identifier of a machine you want to use",
        required=False)
    parser.add_argument(
        "--platform",
        type=str,
        action="store",
        default="",
        help=
        "Specify the operating system platform you want to use (windows/darwin/linux)",
        required=False)
    parser.add_argument(
        "--memory",
        action="store_true",
        default=False,
        help="Enable to take a memory dump of the analysis machine",
        required=False)
    parser.add_argument(
        "--enforce-timeout",
        action="store_true",
        default=False,
        help="Enable to force the analysis to run for the full timeout period",
        required=False)
    parser.add_argument("--clock",
                        type=str,
                        action="store",
                        default=None,
                        help="Set virtual machine clock",
                        required=False)
    parser.add_argument(
        "--tags",
        type=str,
        action="store",
        default=None,
        help="Specify tags identifier of a machine you want to use",
        required=False)
    parser.add_argument("--baseline",
                        action="store_true",
                        default=None,
                        help="Run a baseline analysis",
                        required=False)
    parser.add_argument("--max",
                        type=int,
                        action="store",
                        default=None,
                        help="Maximum samples to add in a row",
                        required=False)
    parser.add_argument("--pattern",
                        type=str,
                        action="store",
                        default=None,
                        help="Pattern of files to submit",
                        required=False)
    parser.add_argument("--shuffle",
                        action="store_true",
                        default=False,
                        help="Shuffle samples before submitting them",
                        required=False)
    parser.add_argument("--unique",
                        action="store_true",
                        default=False,
                        help="Only submit new samples, ignore duplicates",
                        required=False)
    parser.add_argument("--quiet",
                        action="store_true",
                        default=False,
                        help="Only print text on failure",
                        required=False)
    parser.add_argument("--valid_apk",
                        action="store_true",
                        default=False,
                        help="validates APK file",
                        required=False)

    try:
        args = parser.parse_args()
    except IOError as e:
        parser.error(e)
        return False

    if not args.baseline and not args.target:
        print "No file or URL has been specified!"
        exit(1)

    # If the quiet flag has been set, then we also disable the "warning"
    # level of the logging module. (E.g., when pydeep has not been installed,
    # there will be a warning message, because Cuckoo can't resolve the
    # ssdeep hash of this particular sample.)
    if args.debug:
        logging.basicConfig(level=logging.DEBUG)
    else:
        logging.basicConfig()

    if args.quiet:
        logging.disable(logging.WARNING)

    db = Database()

    if args.url:
        target = to_unicode(args.target)
        if args.remote:
            if not HAVE_REQUESTS:
                print(
                    bold(red("Error")) +
                    ": you need to install python-requests (`pip install requests`)"
                )
                return False

            url = "http://{0}/tasks/create/url".format(args.remote)

            data = dict(url=target,
                        package=args.package,
                        timeout=args.timeout,
                        options=args.options,
                        priority=args.priority,
                        machine=args.machine,
                        platform=args.platform,
                        memory=args.memory,
                        enforce_timeout=args.enforce_timeout,
                        custom=args.custom,
                        owner=args.owner,
                        tags=args.tags)

            try:
                response = requests.post(url, data=data)
            except Exception as e:
                print(
                    bold(red("Error")) + ": unable to send URL: {0}".format(e))
                return False

            json = response.json()
            task_id = json["task_id"]
        else:
            task_id = db.add_url(target,
                                 package=args.package,
                                 timeout=args.timeout,
                                 options=args.options,
                                 priority=args.priority,
                                 machine=args.machine,
                                 platform=args.platform,
                                 custom=args.custom,
                                 owner=args.owner,
                                 memory=args.memory,
                                 enforce_timeout=args.enforce_timeout,
                                 clock=args.clock,
                                 tags=args.tags)

        if task_id:
            if not args.quiet:
                print(
                    bold(green("Success")) +
                    u": URL \"{0}\" added as task with ID {1}".format(
                        target, task_id))
        else:
            print(bold(red("Error")) + ": adding task to database")
    elif args.baseline:
        if args.remote:
            print "Remote baseline support has not yet been implemented."
            exit(1)

        task_id = db.add_baseline(args.timeout, args.owner, args.machine,
                                  args.memory)
        if task_id:
            if not args.quiet:
                print(
                    bold(green("Success")) +
                    u": Baseline analysis added as task with ID {0}".format(
                        task_id))
        else:
            print(bold(red("Error")) + ": adding task to database")
    else:
        target = to_unicode(args.target)

        # Get absolute path to deal with relative.
        path = to_unicode(os.path.abspath(target))

        if not os.path.exists(path):
            print(
                bold(red("Error")) +
                u": the specified file/folder does not exist at path \"{0}\"".
                format(path))
            return False

        files = []
        if os.path.isdir(path):
            for dirname, dirnames, filenames in os.walk(path):
                for file_name in filenames:
                    file_path = os.path.join(dirname, file_name)

                    if os.path.isfile(file_path):
                        if args.pattern:
                            if fnmatch.fnmatch(file_name, args.pattern):
                                files.append(to_unicode(file_path))
                        else:
                            files.append(to_unicode(file_path))
        else:
            files.append(path)

        if args.shuffle:
            random.shuffle(files)
        else:
            files = sorted(files)

        for file_path in files:
            if not File(file_path).get_size():
                if not args.quiet:
                    print(
                        bold(
                            yellow("Empty") +
                            ": sample {0} (skipping file)".format(file_path)))

                continue

            if args.valid_apk:
                try:
                    a = APK(file_path)
                    if not a.is_valid_APK():
                        if not args.quiet:
                            print(
                                bold(
                                    yellow("Invalid APK") +
                                    ": sample {0} (skipping file)".format(
                                        file_path)))
                        continue
                    else:
                        if len(a.get_activities()) == 0:
                            if not args.quiet:
                                print(
                                    bold(
                                        yellow("NO Activities APK") +
                                        ": sample {0} (skipping file)".format(
                                            file_path)))
                            continue
                        if len(a.get_services()) == 0:
                            if not args.quiet:
                                print(
                                    bold(
                                        yellow("Non-Executable APK") +
                                        ": sample {0} (skipping file)".format(
                                            file_path)))
                            continue
                except:
                    if not args.quiet:
                        print(
                            bold(
                                yellow("Invalid APK") +
                                ": sample {0} (skipping file)".format(
                                    file_path)))
                    continue

            if args.max is not None:
                # Break if the maximum number of samples has been reached.
                if not args.max:
                    break

                args.max -= 1

            if args.remote:
                if not HAVE_REQUESTS:
                    print(
                        bold(red("Error")) +
                        ": you need to install python-requests (`pip install requests`)"
                    )
                    return False

                url = "http://{0}/tasks/create/file".format(args.remote)

                files = dict(file=open(file_path, "rb"),
                             filename=os.path.basename(file_path))

                data = dict(package=args.package,
                            timeout=args.timeout,
                            options=args.options,
                            priority=args.priority,
                            machine=args.machine,
                            platform=args.platform,
                            memory=args.memory,
                            enforce_timeout=args.enforce_timeout,
                            custom=args.custom,
                            owner=args.owner,
                            tags=args.tags)

                try:
                    response = requests.post(url, files=files, data=data)
                except Exception as e:
                    print(
                        bold(red("Error")) +
                        ": unable to send file: {0}".format(e))
                    return False

                json = response.json()
                task_id = json["task_id"]
            else:
                if args.unique:
                    sha256 = File(file_path).get_sha256()
                    if not db.find_sample(sha256=sha256) is None:
                        msg = ": Sample {0} (skipping file)".format(file_path)
                        if not args.quiet:
                            print(bold(yellow("Duplicate")) + msg)
                        continue

                task_id = db.add_path(file_path=file_path,
                                      package=args.package,
                                      timeout=args.timeout,
                                      options=args.options,
                                      priority=args.priority,
                                      machine=args.machine,
                                      platform=args.platform,
                                      custom=args.custom,
                                      owner=args.owner,
                                      memory=args.memory,
                                      enforce_timeout=args.enforce_timeout,
                                      clock=args.clock,
                                      tags=args.tags)

            if task_id:
                if not args.quiet:
                    print(
                        bold(green("Success")) +
                        u": File \"{0}\" added as task with ID {1}".format(
                            file_path, task_id))
            else:
                print(bold(red("Error")) + ": adding task to database")
예제 #16
0
def main(options, args):

    if options.emulator is None or options.file is None or options.policy is None:
        sys.exit('please confirm the parameters are correct')

    emulator = options.emulator
    apk_path = options.file
    policy = options.policy

    device = Device(emulator)

    if options.install:
        stevedore.install_apk(apk_path, device)

    if not os.path.isdir(LOGS):
        os.mkdir(LOGS)

    sha256 = hashlib.sha256()
    sha256.update(open(apk_path).read())
    sha256sum = sha256.hexdigest()

    log_file = os.path.join(LOGS, sha256sum + '.log')

    if not os.path.isfile(log_file):
        #print 'writing log file into %s' % log_file
        try:
            apk = APK(apk_path)
        except Exception as ex:
            return False, ex
        if not apk.is_valid_APK():
            return False, 'It is not a valid apk'

        activities = []
        for act in apk.get_activities():
            if not filtered(act, FILTERED_ACTIVITY):
                activities.append(act)
        services = apk.get_services()
        receivers = []
        for rec in apk.get_receivers():
            if not filtered(rec, FILTERED_BROADCAST):
                receivers.append(rec)

        package_name = apk.get_package()

        #write to log file
        with open(log_file, 'w') as fout:
            fout.write('package_name=' + package_name + '\n')
            fout.write('activity=' + ' '.join(activities) + '\n')
            fout.write('service=' + ' '.join(services) + '\n')
            fout.write('receiver=' + ' '.join(receivers) + '\n')
    else:
        #print 'reading log file from %s' % log_file
        with open(log_file, 'r') as fin:
            for line in fin.readlines():
                if line.startswith('package_name='):
                    package_name = line.replace('package_name=', '')
                elif line.startswith('activity='):
                    activities = line.replace('activity=', '').split()
                elif line.startswith('service='):
                    services = line.replace('service=', '').split()
                elif line.startswith('receiver='):
                    receivers = line.replace('receiver=', '').split()

    if policy == 'random':
        policy = ['broadcast', 'listener', 'launcher', 'service',
                  'receiver'][random.randint(0, 4)]

    if policy == 'broadcast':
        actions = IntentEvent.get_intent_actions()
        if len(actions) > 0:
            selected = actions[random.randint(0, len(actions) - 1)]
            intent = IntentEvent(action=selected, package_name=package_name)
            intent.execute(device)
    elif policy == 'listener':
        if emulator.startswith('emulator'):
            listener_type = ['sms', 'gsm', 'rotate',
                             'volume'][random.randint(0, 3)]
            listener = ListenerEvent(listener_type)
            listener.execute(device)
        else:
            listener_type = ['sms', 'rotate', 'volume'][random.randint(0, 2)]
            if listener_type == 'sms':
                intent = IntentEvent(
                    action='android.provider.Telephony.SMS_RECEIVED'
                )  #, package_name=package_name)
                intent.execute(device)
            else:
                listener = ListenerEvent(listener_type)
                listener.execute(device)
    elif policy == 'launcher':
        if len(activities) > 0:
            selected = activities[random.randint(0, len(activities) - 1)]
            launcher = LauncherEvent(package_name, selected)
            launcher.execute(device)
    elif policy == 'service':

        if len(services) > 0:
            selected = services[random.randint(0, len(services) - 1)]
            service = ServiceEvent(package_name, selected)
            service.execute(device)

            if random.randint(0, 1) == 1:
                import time
                time.sleep(3)
                service = ServiceEvent(package_name=package_name,
                                       service_name=selected,
                                       stop=True)
                service.execute(device)

    elif policy == 'receiver':
        if len(receivers) > 0:
            selected = receivers[random.randint(0, len(receivers) - 1)]
            receiver = ReceiverEvent(package_name, selected)
            receiver.execute(device)
예제 #17
0
    def run(self):
        """Run androguard to extract static android information
                @return: list of static features
        """
        self.key = "apkinfo"
        apkinfo = {}

        if "file" not in self.task["category"] or not HAVE_ANDROGUARD:
            return

        f = File(self.task["target"])
        #if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
        if not os.path.exists(self.file_path):
            raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" %
                                        self.file_path)

        try:
            a = APK(self.file_path)
            if a.is_valid_APK():
                manifest = {}

                apkinfo["files"] = self._apk_files(a)
                manifest["package"] = a.get_package()
                apkinfo["hidden_payload"] = []

                for file in apkinfo["files"]:
                    if self.file_type_check(file):
                        apkinfo["hidden_payload"].append(file)

                apkinfo["files_flaged"] = self.files_name_map

                manifest["permissions"] = get_permissions(a)
                manifest["main_activity"] = a.get_main_activity()
                manifest["activities"] = a.get_activities()
                manifest["services"] = a.get_services()
                manifest["receivers"] = a.get_receivers()
                manifest["receivers_actions"] = get_extended_receivers(a)
                manifest["providers"] = a.get_providers()
                manifest["libraries"] = list(a.get_libraries())
                apkinfo["manifest"] = manifest

                apkinfo["icon"] = get_apk_icon(self.file_path)
                certificate = get_certificate(self.file_path)
                if certificate:
                    apkinfo["certificate"] = certificate

                #vm = DalvikVMFormat(a.get_dex())
                #strings = vm.get_strings()
                strings = self._get_strings(self.file_path)
                apkinfo["interesting_strings"] = find_strings(strings)
                apkinfo["dex_strings"] = strings

                static_calls = {}
                if self.options.decompilation:
                    if self.check_size(apkinfo["files"]):
                        vm = DalvikVMFormat(a.get_dex())
                        vmx = Analysis(vm)
                        vmx.create_xref()

                        static_calls["all_methods"] = get_methods(vmx)
                        static_calls[
                            "permissions_method_calls"] = get_show_Permissions(
                                vmx)

                        static_calls[
                            "native_method_calls"] = get_show_NativeMethods(
                                vmx)
                        static_calls["is_native_code"] = bool(
                            static_calls["native_method_calls"]
                        )  # True if not empty, False if empty

                        static_calls[
                            "dynamic_method_calls"] = get_show_DynCode(vmx)
                        static_calls["is_dynamic_code"] = bool(
                            static_calls["dynamic_method_calls"])

                        static_calls[
                            "reflection_method_calls"] = get_show_ReflectionCode(
                                vmx)
                        static_calls["is_reflection_code"] = bool(
                            static_calls["reflection_method_calls"])

                        static_calls[
                            "crypto_method_calls"] = get_show_CryptoCode(vmx)
                        static_calls["is_crypto_code"] = bool(
                            static_calls["crypto_method_calls"])

                        classes = list()
                        for cls in vm.get_classes():
                            classes.append(cls.name)

                        static_calls["classes"] = classes

                    else:
                        log.warning(
                            "Aborted decompilation, static extraction of calls not perforemd",
                        )

                apkinfo["static_method_calls"] = static_calls

        except (IOError, OSError, BadZipfile) as e:
            raise CuckooProcessingError("Error opening file %s" % e)
        return apkinfo