예제 #1
1
 def testAPKIntentFilters(self):
     from androguard.core.bytecodes.apk import APK
     a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True)
     activities = a.get_activities()
     receivers = a.get_receivers()
     services = a.get_services()
     filter_list = []
     for i in activities:
         filters = a.get_intent_filters("activity", i)
         if len(filters) > 0:
             filter_list.append(filters)
     for i in receivers:
         filters = a.get_intent_filters("receiver", i)
         if len(filters) > 0:
             filter_list.append(filters)
     for i in services:
         filters = a.get_intent_filters("service", i)
         if len(filters) > 0:
             filter_list.append(filters)
     pairs = zip(filter_list, [{'action': ['android.intent.action.MAIN'], 'category': ['android.intent.category.LAUNCHER']},
                                                      {'action': ['android.service.notification.NotificationListenerService']},
                                                      {'action': ['android.intent.action.BOOT_COMPLETED', 'android.intent.action.MY_PACKAGE_REPLACED'], 'category': ['android.intent.category.HOME']},
                                                      {'action': ['android.appwidget.action.APPWIDGET_UPDATE']}])
     self.assertTrue(any(x != y for x, y in pairs))
예제 #2
1
class App(object):
    """
    this class describes an app
    """

    def __init__(self, app_path, output_dir=None):
        """
        create a App instance
        :param app_path: local file path of app
        :return:
        """
        assert app_path is not None
        self.logger = logging.getLogger(self.__class__.__name__)

        self.app_path = app_path

        self.output_dir = output_dir
        if output_dir is not None:
            if not os.path.isdir(output_dir):
                os.makedirs(output_dir)

        from androguard.core.bytecodes.apk import APK
        self.apk = APK(self.app_path)
        self.package_name = self.apk.get_package()
        self.main_activity = self.apk.get_main_activity()
        self.permissions = self.apk.get_permissions()
        self.activities = self.apk.get_activities()
        self.possible_broadcasts = self.get_possible_broadcasts()
        self.dumpsys_main_activity = None
        self.hashes = self.get_hashes()

    def get_package_name(self):
        """
        get package name of current app
        :return:
        """
        return self.package_name

    def get_main_activity(self):
        """
        get package name of current app
        :return:
        """
        if self.main_activity is not None:
            return self.main_activity
        else:
            self.logger.warning("Cannot get main activity from manifest. Using dumpsys result instead.")
            return self.dumpsys_main_activity

    def get_start_intent(self):
        """
        get an intent to start the app
        :return: Intent
        """
        package_name = self.get_package_name()
        if self.get_main_activity():
            package_name += "/%s" % self.get_main_activity()
        return Intent(suffix=package_name)

    def get_start_with_profiling_intent(self, trace_file, sampling=None):
        """
        get an intent to start the app with profiling
        :return: Intent
        """
        package_name = self.get_package_name()
        if self.get_main_activity():
            package_name += "/%s" % self.get_main_activity()
        if sampling is not None:
            return Intent(prefix="start --start-profiler %s --sampling %d" % (trace_file, sampling), suffix=package_name)
        else:
            return Intent(prefix="start --start-profiler %s" % trace_file, suffix=package_name)

    def get_stop_intent(self):
        """
        get an intent to stop the app
        :return: Intent
        """
        package_name = self.get_package_name()
        return Intent(prefix="force-stop", suffix=package_name)

    def get_possible_broadcasts(self):
        possible_broadcasts = set()
        for receiver in self.apk.get_receivers():
            intent_filters = self.apk.get_intent_filters('receiver', receiver)
            actions = intent_filters['action'] if 'action' in intent_filters else []
            categories = intent_filters['category'] if 'category' in intent_filters else []
            categories.append(None)
            for action in actions:
                for category in categories:
                    intent = Intent(prefix='broadcast', action=action, category=category)
                    possible_broadcasts.add(intent)
        return possible_broadcasts

    def get_hashes(self, block_size=2 ** 8):
        """
        Calculate MD5,SHA-1, SHA-256
        hashes of APK input file
        @param block_size:
        """
        md5 = hashlib.md5()
        sha1 = hashlib.sha1()
        sha256 = hashlib.sha256()
        f = open(self.app_path, 'rb')
        while True:
            data = f.read(block_size)
            if not data:
                break
            md5.update(data)
            sha1.update(data)
            sha256.update(data)
        return [md5.hexdigest(), sha1.hexdigest(), sha256.hexdigest()]
예제 #3
0
def test(app_path):

    if not app_path:
        return False

    if not os.path.exists(app_path):
        return False

    app_apk = APK(app_path)
    dvm = DalvikVMFormat(app_apk.get_dex())

    receivers = app_apk.get_receivers()
    activities = app_apk.get_activities()
    services = app_apk.get_services()

    for activity in activities:
        if not check_class_in_dex(dvm, activity):
            return True

    for receiver in receivers:
        if not check_class_in_dex(dvm, receiver):
            return True
    for service in services:
        if not check_class_in_dex(dvm, service):
            return True

    return False
예제 #4
0
 def testAPKIntentFilters(self):
     from androguard.core.bytecodes.apk import APK
     a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True)
     activities = a.get_activities()
     receivers = a.get_receivers()
     services = a.get_services()
     filter_list = []
     for i in activities:
         filters = a.get_intent_filters("activity", i)
         if len(filters) > 0:
             filter_list.append(filters)
     for i in receivers:
         filters = a.get_intent_filters("receiver", i)
         if len(filters) > 0:
             filter_list.append(filters)
     for i in services:
         filters = a.get_intent_filters("service", i)
         if len(filters) > 0:
             filter_list.append(filters)
     pairs = zip(filter_list, [{
         'action': ['android.intent.action.MAIN'],
         'category': ['android.intent.category.LAUNCHER']
     }, {
         'action':
         ['android.service.notification.NotificationListenerService']
     }, {
         'action': [
             'android.intent.action.BOOT_COMPLETED',
             'android.intent.action.MY_PACKAGE_REPLACED'
         ],
         'category': ['android.intent.category.HOME']
     }, {
         'action': ['android.appwidget.action.APPWIDGET_UPDATE']
     }])
     self.assertTrue(any(x != y for x, y in pairs))
예제 #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
파일: 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
예제 #7
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
def extract_features_using_androguard(androguard: APK):
    resulat_dict = dict()
    count_dict = dict()
    _permissions = androguard.get_permissions()

    _hardwares = list(androguard.get_features())
    np = len(_permissions)
    if np > 0:
        resulat_dict = {
            'defined_perm': dict(Counter(_permissions)),
        }
        count_dict = {'num_permission': np}
    nh = len(_hardwares)
    if nh > 0:
        resulat_dict.update({'hardware': dict(Counter(_hardwares))})
        count_dict.update({'num_hardware': len(_hardwares)})
    # List of all intents in apk
    _filters = list()
    # Apk components
    components_dict = {
        'activity': androguard.get_activities(),
        'service': androguard.get_services(),
        'receiver': androguard.get_receivers(),
        'provider': androguard.get_providers()
    }

    # Extract intents
    for categorie, names in components_dict.items():
        # Components and Count the number of each components in apk
        nm = len(names)
        if nm > 0:
            count_dict.update({'num_' + categorie: nm})
            resulat_dict.update(
                {categorie: dict(Counter(components_dict[categorie]))})
            # Extract intent filter for each component
            intents = extract_intent(androguard, categorie, names)
            ni = len(intents)
            if ni > 0:
                _filters.extend(intents)
                count_dict.update({'num_intent_' + categorie: ni})
    nf = len(_filters)
    if nf > 0:
        resulat_dict.update({'intent': dict(Counter(_filters))})
        count_dict.update({'num_intent': nf})
    resulat_dict.update({'component_count': count_dict})
    return resulat_dict
def get_data(apkPath, apkName):
    a = APK(apkPath)
    jsonFile = apkName + ".json"
    pro = a.get_providers()
    rec = a.get_receivers()
    ser = a.get_services()
    act = a.get_activities()
    per = a.get_permissions()
    hwc = get_hardware(a)
    data = {'permissions': [], 'hardwareComponent': [], 'components': {}}
    data['permissions'] = per
    data['hardwareComponent'] = hwc
    data['components']['providers'] = pro
    data['components']['receivers'] = rec
    data['components']['services'] = rec
    data['components']['activities'] = act
    with open(jsonFile, 'w') as f:
        json.dump(data, f)
예제 #10
0
def lim_features_categories(apk_filepath):
    try:
        apk = APK(apk_filepath)
        info = {
            'declared permissions': sorted(apk.get_permissions()),
            'activities': apk.get_activities(),
            'services': apk.get_services(),
            'intent filters': apk.get_intent_filters('receiver', ''),
            'content providers': apk.get_providers(),
            'broadcast receivers': apk.get_receivers(),
            'hardware components': apk.get_features()
        }

        for category in info:
            info[category] = [
                feature.replace(".", "_").lower() for feature in info[category]
            ]

        return info
    except:
        # We just do not process the APK
        pass
예제 #11
0
class App(object):
    def __init__(self, app_path, output_dir=None):
        from androguard.core.bytecodes.apk import APK
        from androguard.core.androconf import show_logging
        show_logging(level=logging.CRITICAL)

        self.app_path = app_path
        self.apk = APK(app_path)
        self.package_name = self.apk.get_package()
        self.domain = appdomainmapping.get_domain(self.package_name)
        self.permissions = self.apk.get_permissions()
        self.version_name = self.apk.get_androidversion_name()
        self.receivers = self.apk.get_receivers()
        self.activities = self.apk.get_activities()
        self.app_size = self.compute_app_size()
        # self.possible_broadcasts = self.get_possible_broadcasts()
        self.exploration_model: Optional[ExplorationModel] = None
        self.ad_tracking_libraries = set()
        self.short_name: str = self.get_short_name()

    def __eq__(self, o: object) -> bool:
        if isinstance(o, App):
            return self.package_name == o.package_name
        else:
            return False

    def __hash__(self) -> int:
        return hash(self.package_name)

    def __lt__(self, other):
        if self.domain == other.domain:
            return self.package_name < other.package_name
        else:
            return self.domain < other.domain

    def get_short_name(self) -> str:
        assert self.package_name in APP_SHORT_NAME_MAP, f"{self.package_name} is not present in APP_SHORT_NAME_MAP"
        return APP_SHORT_NAME_MAP[self.package_name]

    def compute_app_size(self):
        """
        :return: The app file size in MB.
        """
        return os.path.getsize(self.app_path) / (1024 * 1024.0)

    def construct_data(self, config_togape, compute_use_case_executions,
                       load_from_cache):
        togape_output_dir = config_togape[configutil.TOGAPE_CFG_OUTPUT_DIR]
        model_dir = os.path.join(togape_output_dir,
                                 configutil.TOGAPE_MODEL_DIR_NAME,
                                 self.package_name)
        feature_dir = config_togape[configutil.TOGAPE_CFG_FEATURE_DIR]
        # Actually only the file is needed oracle-PCK_NAME.json
        evaluation_dir = config_togape[configutil.TOGAPE_CFG_EVALUATION_DIR]
        matrics_playback_dir = os.path.join(
            togape_output_dir, configutil.MATRICS_PLAYBACK_MODEL_DIR_NAME)
        use_case_manager = UseCaseManager(
            config_togape[configutil.TOGAPE_CFG_ATD_PATH])
        if load_from_cache:
            self.exploration_model = DummyExplorationModel.create(
                app=self,
                package_name=self.package_name,
                exploration_model_dir=model_dir,
                use_case_manager=use_case_manager,
                matrics_playback_dir=matrics_playback_dir,
                compute_use_case_executions_b=
                LOAD_EXPLORATION_MODEL_FROM_FILE_DUMP)

        else:
            self.exploration_model = ExplorationModel.load_exploration_model(
                self, self.package_name, model_dir, feature_dir,
                evaluation_dir, use_case_manager, matrics_playback_dir,
                compute_use_case_executions,
                LOAD_EXPLORATION_MODEL_FROM_FILE_DUMP)
            self.ad_tracking_libraries = LibraryExtractor.get_ad_tracking_libraries(
                self.app_path, model_dir)
예제 #12
0
class App(object):
    """
    this class describes an app
    """
    def __init__(self, app_path, output_dir=None):
        """
        create a App instance
        :param app_path: local file path of app
        :return:
        """
        assert app_path is not None
        self.logger = logging.getLogger(self.__class__.__name__)

        self.app_path = app_path

        self.output_dir = output_dir
        if output_dir is not None:
            if not os.path.isdir(output_dir):
                os.makedirs(output_dir)

        from androguard.core.bytecodes.apk import APK
        self.apk = APK(self.app_path)
        self.package_name = self.apk.get_package()
        self.main_activity = self.apk.get_main_activity()
        self.permissions = self.apk.get_permissions()
        self.activities = self.apk.get_activities()
        self.possible_broadcasts = self.get_possible_broadcasts()
        self.dumpsys_main_activity = None
        self.hashes = self.get_hashes()

    def get_package_name(self):
        """
        get package name of current app
        :return:
        """
        return self.package_name

    def get_main_activity(self):
        """
        get package name of current app
        :return:
        """
        if self.main_activity is not None:
            return self.main_activity
        else:
            self.logger.warning(
                "Cannot get main activity from manifest. Using dumpsys result instead."
            )
            return self.dumpsys_main_activity

    def get_start_intent(self):
        """
        get an intent to start the app
        :return: Intent
        """
        package_name = self.get_package_name()
        if self.get_main_activity():
            package_name += "/%s" % self.get_main_activity()
        return Intent(suffix=package_name)

    def get_start_with_profiling_intent(self, trace_file, sampling=None):
        """
        get an intent to start the app with profiling
        :return: Intent
        """
        package_name = self.get_package_name()
        if self.get_main_activity():
            package_name += "/%s" % self.get_main_activity()
        if sampling is not None:
            return Intent(prefix="start --start-profiler %s --sampling %d" %
                          (trace_file, sampling),
                          suffix=package_name)
        else:
            return Intent(prefix="start --start-profiler %s" % trace_file,
                          suffix=package_name)

    def get_stop_intent(self):
        """
        get an intent to stop the app
        :return: Intent
        """
        package_name = self.get_package_name()
        return Intent(prefix="force-stop", suffix=package_name)

    def get_possible_broadcasts(self):
        possible_broadcasts = set()
        for receiver in self.apk.get_receivers():
            intent_filters = self.apk.get_intent_filters('receiver', receiver)
            actions = intent_filters[
                'action'] if 'action' in intent_filters else []
            categories = intent_filters[
                'category'] if 'category' in intent_filters else []
            categories.append(None)
            for action in actions:
                for category in categories:
                    intent = Intent(prefix='broadcast',
                                    action=action,
                                    category=category)
                    possible_broadcasts.add(intent)
        return possible_broadcasts

    def get_hashes(self, block_size=2**8):
        """
        Calculate MD5,SHA-1, SHA-256
        hashes of APK input file
        @param block_size:
        """
        md5 = hashlib.md5()
        sha1 = hashlib.sha1()
        sha256 = hashlib.sha256()
        f = open(self.app_path, 'rb')
        while True:
            data = f.read(block_size)
            if not data:
                break
            md5.update(data)
            sha1.update(data)
            sha256.update(data)
        return [md5.hexdigest(), sha1.hexdigest(), sha256.hexdigest()]
예제 #13
0
def analyze(path):
    try:
        start = process_time()
        hashfunctions = dict(md5=hashlib.md5,
                             sha1=hashlib.sha1,
                             sha256=hashlib.sha256,
                             sha512=hashlib.sha512)
        a = APK(path)

        certs = set(
            a.get_certificates_der_v3() + a.get_certificates_der_v2() +
            [a.get_certificate_der(x) for x in a.get_signature_names()])

        for cert in certs:
            x509_cert = x509.Certificate.load(cert)

            issuer = {
                'commonName': None,
                'organizationName': None,
                'organizationalUnitName': None,
                'countryName': None,
                'stateOrProvinceName': None,
                'localityName': None
            }
            subject = {
                'commonName': None,
                'organizationName': None,
                'organizationalUnitName': None,
                'countryName': None,
                'stateOrProvinceName': None,
                'localityName': None
            }

            strIssuer = get_certificate_name_string(x509_cert.issuer,
                                                    short=False)
            strSubject = get_certificate_name_string(x509_cert.subject,
                                                     short=False)

            arrIssuer = strIssuer.split(',')
            for i in arrIssuer:
                if i.lstrip().split('=')[0] == 'commonName':
                    issuer['commonName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'organizationName':
                    issuer['organizationName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'organizationalUnitName':
                    issuer['organizationalUnitName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'countryName':
                    issuer['countryName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'stateOrProvinceName':
                    issuer['stateOrProvinceName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'localityName':
                    issuer['localityName'] = i.lstrip().split('=')[1]

            arrSubject = strSubject.split(',')
            for i in arrSubject:
                if i.lstrip().split('=')[0] == 'commonName':
                    subject['commonName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'organizationName':
                    subject['organizationName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'organizationalUnitName':
                    subject['organizationalUnitName'] = i.lstrip().split(
                        '=')[1]
                elif i.lstrip().split('=')[0] == 'countryName':
                    subject['countryName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'stateOrProvinceName':
                    subject['stateOrProvinceName'] = i.lstrip().split('=')[1]
                elif i.lstrip().split('=')[0] == 'localityName':
                    subject['localityName'] = i.lstrip().split('=')[1]

            for k, v in hashfunctions.items():
                if k == 'md5':
                    md5 = v(cert).hexdigest()
                elif k == 'sha1':
                    sha1 = v(cert).hexdigest()
                elif k == 'sha256':
                    sha256 = v(cert).hexdigest()
                elif k == 'sha512':
                    sha512 = v(cert).hexdigest()

        md5 = md5

        appName = a.get_app_name()
        fileSize = os.stat(a.get_filename()).st_size
        sha1 = sha1
        sha256 = sha256
        sha512 = sha512
        timestamp = time.time()
        dateTime = datetime.fromtimestamp(timestamp)
        timeOfSubmit = dateTime.strftime("%Y-%m-%d %H:%M:%S")
        package = a.get_package()
        androidversionCode = a.get_androidversion_code()
        androidversionName = a.get_androidversion_name()
        minSDKVersion = a.get_min_sdk_version()
        maxSDKVersion = a.get_max_sdk_version()
        targetSDKVersion = a.get_target_sdk_version()
        mainActivity = a.get_main_activity()

        attributes = {
            'validFrom':
            x509_cert['tbs_certificate']['validity']
            ['not_before'].native.strftime("%Y-%m-%d %H:%M:%S"),
            'validTo':
            x509_cert['tbs_certificate']['validity']
            ['not_after'].native.strftime("%Y-%m-%d %H:%M:%S"),
            'serialNumber':
            hex(x509_cert.serial_number),
            'hashAlgorithm':
            x509_cert.hash_algo,
            'signatureAlgorithm':
            x509_cert.signature_algo
        }

        certificateAttributes = json.dumps(attributes)
        certificateIssuer = json.dumps(issuer)
        certificateSubject = json.dumps(subject)

        declaredPermissions = json.dumps(a.get_declared_permissions())

        requestedPermissions = json.dumps(a.get_permissions())

        activities = json.dumps(a.get_activities())

        services = json.dumps(a.get_services())

        receivers = json.dumps(a.get_receivers())

        providers = json.dumps(a.get_providers())

        stop = process_time()
        analysisTime = stop - start

        connect = mysql.connect()
        cursor = connect.cursor()

        sql = "INSERT INTO tbl_apkinfo (md5, appName, fileSize, analysisTime, sha1, sha256, sha512, firstSubmission, lastSubmission, package, androidversionCode, androidversionName, minSDKVersion, maxSDKVersion, targetSDKVersion, mainActivity, certificateAttributes, certificateIssuer, certificateSubject,	declaredPermissions, requestedPermissions, activities, services, providers, receivers) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
        param = (md5, appName, fileSize, analysisTime, sha1, sha256, sha512,
                 timeOfSubmit, timeOfSubmit, package, androidversionCode,
                 androidversionName, minSDKVersion, maxSDKVersion,
                 targetSDKVersion, mainActivity, certificateAttributes,
                 certificateIssuer, certificateSubject, declaredPermissions,
                 requestedPermissions, activities, services, providers,
                 receivers)
        cursor.execute(sql, param)

        connect.commit()
        connect.close()

        androaxml_main(path,
                       os.path.join(app.config['OUTPUT_PATH'], md5 + '.xml'))
        return True
    except:
        return False
예제 #14
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)
예제 #15
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
예제 #16
0
def reverse(nameApk):

    # doc file config
    with open(config_file, "r+") as f:
        dataConfig = json.load(f)

    maxLabelsNum = dataConfig['maxLabelsNum']

    # Label tong hop
    # with open(LabelsNum_file, "r+") as file_LabeslNum:
    #     LABELSNUMANDTEXT = json.load(file_LabeslNum)



    # Load Android API packages and classes
    global API_PACKAGES_LIST, API_CLASSES_LIST, API_SYSTEM_COMMANDS


    ############################################################
    # READING PACKAGES, CLASSES AND SYSTEM COMMANDS
    ############################################################
    package_file = load_file(str(package_index_file))
    API_PACKAGES_LIST = [x.strip() for x in package_file]

    class_file = load_file(str(classes_index_file))
    API_CLASSES_LIST = [x.strip() for x in class_file]

    commands_file = load_file(str(system_commands_file))
    API_SYSTEM_COMMANDS = [x.strip() for x in commands_file]
    static_analysis_dict = collections.OrderedDict()
    try:

        analyze_apk = os.path.join(TEMP,nameApk)
        # Getting the name of the folder that contains all apks and folders with apks
        base_folder = TEMP.split("/")[-1]

        apk_filename = join_dir(base_folder, analyze_apk.replace(TEMP, ''))
        apk_filename = apk_filename.replace("//", "/")

        apk_name_no_extensions = "".join(apk_filename.split("/")[-1].split(".")[:-1])

        # export to monggoDB
        # if os.path.isfile(join_dir(output_folder, apk_filename.split("/")[-1].replace('.apk', '-analysis.json'))):
        #    database[apk_filename.replace('.apk', '')] = json.load(
        #        open(join_dir(output_folder, apk_filename.split("/")[-1].
        #                      replace('.apk', '-analysis.json'))))
        #    continue

        pre_static_dict = collections.OrderedDict()

        pre_static_dict['Filename'] = apk_filename

        hasher_md5 = hashlib.md5()
        hasher_sha256 = hashlib.sha256()
        hasher_sha1 = hashlib.sha1()
        with open(analyze_apk, 'rb') as afile:
            buf = afile.read()
            hasher_md5.update(buf)
            hasher_sha256.update(buf)
            hasher_sha1.update(buf)

        md5 = hasher_md5.hexdigest()
        sha256 = hasher_sha256.hexdigest()
        sha1 = hasher_sha1.hexdigest()

        pre_static_dict["md5"] = md5
        pre_static_dict["sha256"] = sha256
        pre_static_dict["sha1"] = sha1

        """
        if label is not None:
            pre_static_dict["Label"] = label
        else:
            pre_static_dict["Label"] = "/".join(apk_filename.split("/")[:-1])
        """
        pre_static_dict["VT_positives"] = None
        apk_Oject = APK(analyze_apk)

        # get package name
        static_analysis_dict['Package_name'] = apk_Oject.get_package()

        # get Permission
        static_analysis_dict['Permissions'] = apk_Oject.get_permissions()

        # Activities
        try:
            list_activities = apk_Oject.get_activities()
        except UnicodeEncodeError:
            list_activities = []

        # get Main ACtivity
        static_analysis_dict['Main_activity'] = apk_Oject.get_main_activity()

        # Receivers
        try:
            list_receivers = apk_Oject.get_receivers()
        except UnicodeEncodeError:
            list_receivers = []

        # Services
        try:
            list_services = apk_Oject.get_services()
        except UnicodeEncodeError:
            list_services = []

        # API calls and Strings
        list_smali_api_calls, list_smali_strings = read_strings_and_apicalls(analyze_apk, API_PACKAGES_LIST,
                                                                             API_CLASSES_LIST)
        for api_call in list_smali_api_calls.keys():
            new_api_call = '.'.join(api_call.split(".")[:-1])
            if new_api_call in list_smali_api_calls.keys():
                list_smali_api_calls[new_api_call] = list_smali_api_calls[new_api_call] + list_smali_api_calls[
                    api_call]
            else:
                list_smali_api_calls[new_api_call] = list_smali_api_calls[api_call]
                del list_smali_api_calls[api_call]
        static_analysis_dict['API_calls'] = list_smali_api_calls
        static_analysis_dict['Strings'] = Counter(filter(None, list_smali_strings))

        # API packages

        API_packages_dict = collections.OrderedDict()
        android_list_packages_lenghts = [len(x.split(".")) for x in API_PACKAGES_LIST]

        list_api_calls_keys = list_smali_api_calls.keys()
        for api_call in list_api_calls_keys:
            score = 0
            package_chosen = None
            for i, package in enumerate(API_PACKAGES_LIST):
                len_package = android_list_packages_lenghts[i]
                if api_call.startswith(package) and len_package > score:
                    score = len_package
                    package_chosen = package
            if package_chosen is not None:
                if not package_chosen in API_packages_dict.keys():
                    API_packages_dict[package_chosen] = list_smali_api_calls[api_call]
                else:
                    API_packages_dict[package_chosen] += list_smali_api_calls[api_call]

        static_analysis_dict['API_packages'] = API_packages_dict

        # Intents
        try:
            static_analysis_dict['Intents'] = intents_analysis(join_dir(analyze_apk.replace('.apk', ''),
                                                                        'AndroidManifest.xml'))
        except:
            static_analysis_dict['Intents'] = {'Failed to extract intents': 0}

        # Intents of activities
        intents_activities = collections.OrderedDict()
        for activity in list_activities:
            intents_activities[activity] = check_for_intents(join_dir(analyze_apk.replace('.apk', ''),
                                                                      'AndroidManifest.xml'),
                                                             activity, 'activity')
        static_analysis_dict['Activities'] = intents_activities

        # Intents of services
        intents_services = collections.OrderedDict()
        for service in list_services:
            intents_services[service] = check_for_intents(join_dir(analyze_apk.replace('.apk', ''),
                                                                   'AndroidManifest.xml'),
                                                          service, 'service')
        static_analysis_dict['Services'] = intents_services

        # Intents of receivers
        intents_receivers = collections.OrderedDict()
        for intent in list_receivers:
            intents_receivers[intent] = check_for_intents(join_dir(analyze_apk.replace('.apk', '/'),
                                                                   'AndroidManifest.xml'),
                                                          intent, 'receiver')
        static_analysis_dict['Receivers'] = intents_receivers
        static_analysis_dict['Receivers'] = intents_receivers

        apk_total_analysis = collections.OrderedDict([("Pre_static_analysis", pre_static_dict),
                                                       ("Static_analysis", static_analysis_dict)])
        #
        # save_as_json(apk_total_analysis, output_name=join_dir(output_folder, apk_name_no_extensions +
        #                                                       "-analysis.json"))

        row = standardData(pre_static_dict, static_analysis_dict)
        csvFileClient = open(DataCSVClient + md5 + '.csv', 'w+', newline='')
        writer = csv.writer(csvFileClient, delimiter=',')
        writer.writerow(row)
        csvFileClient.close()
        delAPk(analyze_apk)
        if checkMerge(DataCSVClient, dataConfig['mergeCSV']):
            mergeCSV()
        return md5, apk_total_analysis


    except Exception as e:
        print('Exception: ', e)
        return 'Error', 'No features'
예제 #17
0
class App(object):
    """
    The class representing the application to be analyzed.
    """
    def __init__(self, apk_path: str):
        self.logger = logging.getLogger('{0}.{1}'.format(
            __name__, self.__class__.__name__))

        if not os.path.isfile(apk_path):
            raise FileNotFoundError(
                'The input application file "{0}" was not found'.format(
                    apk_path))

        self.apk_path = apk_path

        self.apk = APK(self.apk_path)

        self.hashes = self.get_hashes()

        self.package_name = self.apk.get_package()
        self.main_activities = self.apk.get_main_activities()

        # This is the variable that holds the list of intents that should be used to start the app. Every
        # time an intent is used to start the app, the code should check if the intent is valid (it starts
        # an existing activity), if it's not valid then the intent should be removed from this list.
        self.start_intents = self.get_start_intents()

        self.permissions = self.apk.get_permissions()
        self.activities = self.apk.get_activities()
        self.possible_broadcasts = self.get_possible_broadcasts()

    def get_hashes(self, block_size=65536) -> List[str]:
        """
        Calculate MD5, SHA1 and SHA256 hashes of the input application file.

        :param block_size: The size of the block used for the hash functions.
        :return: A list containing the MD5, SHA1 and SHA256 hashes of the input application file.
        """
        md5_hash = hashlib.md5()
        sha1_hash = hashlib.sha1()
        sha256_hash = hashlib.sha256()
        with open(self.apk_path, 'rb') as filename:
            for chunk in iter(lambda: filename.read(block_size), b''):
                md5_hash.update(chunk)
                sha1_hash.update(chunk)
                sha256_hash.update(chunk)
        return [
            md5_hash.hexdigest(),
            sha1_hash.hexdigest(),
            sha256_hash.hexdigest()
        ]

    def get_package_name(self) -> str:
        """
        Get the package name of the current application.

        :return: The package name of the current application.
        """
        return self.package_name

    def get_main_activities(self) -> List[str]:
        """
        Get the main activities of the current application.

        :return: A list with the main activities of the current application.
        """
        return self.main_activities

    def get_start_intents(self) -> List[Intent]:
        """
        Get a list of intents to start the main activities of the current application. This method
        should be called only during initialization, after that use start_intents variable.

        :return: A list of intents to start the main activities of the current application.
        """
        list_of_intents: List[Intent] = []
        for activity in self.get_main_activities():
            list_of_intents.append(
                Intent(suffix='{0}/{1}'.format(self.package_name, activity)))
        if list_of_intents:
            return list_of_intents

        raise RuntimeError(
            'This application has no main activity that can be used')

    def get_stop_intent(self):
        """
        Get an intent to stop the current application.

        :return: An intent to stop the current application.
        """
        return Intent(prefix='force-stop', suffix=self.package_name)

    def get_possible_broadcasts(self) -> Set[Intent]:
        """
        Get the intents to trigger the broadcast receivers in the current application.

        :return: A set with the intents to trigger the broadcast receivers in the current application.
        """
        possible_broadcasts = set()
        for receiver in self.apk.get_receivers():
            intent_filters = self.apk.get_intent_filters('receiver', receiver)
            actions = intent_filters[
                'action'] if 'action' in intent_filters else []
            categories = intent_filters[
                'category'] if 'category' in intent_filters else []
            categories.append(None)
            for action in actions:
                for category in categories:
                    intent = Intent(prefix='broadcast',
                                    action=action,
                                    category=category)
                    possible_broadcasts.add(intent)
        return possible_broadcasts
예제 #18
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
예제 #19
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
예제 #20
0
def scan_apk(argv):
    print "[+] Welcome To MAFIA"
    scan_id = int(argv[1])

    print "scan_id: ", str(scan_id)

    steps = 13
    mod = 100.0/steps
    DBconnect.progress_update(scan_id,0,"Decompiling dex")
    apk=argv[2]
    # print apk
    pwd = os.getcwd()+"/application/engine"
    print "path: "+pwd
    # sys.exit(1)
    
    outputdir = dircreator(pwd+"/workfiles/"+str(scan_id))
    #print "1"
    java_folder=pwd+'/workfiles/'+str(scan_id)+'/output/javas'
    output_folder=pwd+'/workfiles/'+str(scan_id)+'/output/report'
    try:
        ex1 = os.makedirs(output_folder)
    except:
        pass

    key_path=pwd+'/workfiles/'+str(scan_id)+'/extracted'
    layout_path=pwd+'/workfiles/'+str(scan_id)+'/extracted/res'
    manifest_file = pwd+'/workfiles/'+str(scan_id)+'/output/Uncrypted_AndroidManifest.xml'

    os.system('chmod -R 777 '+pwd+'/workfiles/')

    DBconnect.progress_update(scan_id,mod*1,"Decompiling Classes")
    extraction(pwd,apk,outputdir,mod)


    DBconnect.progress_update(scan_id,mod*2,"Extracting permissions")
    manifest_Ext(outputdir)
    andr = APK(apk)
    perms = list(set(andr.get_permissions())) #list(set()) is needed to get unique items in list

    for perm in perms:
        DBconnect.write_permission(perm,scan_id)

    receivers = list(set(andr.get_receivers())) #list(set()) is needed to get unique items in list

    for receiver in receivers:
        DBconnect.write_receivers(receiver,scan_id)

    DBconnect.progress_update(scan_id,mod*3,"Manifest Analysis")
    manifest_analysis.manifest_analysis(manifest_file,output_folder,scan_id)

    DBconnect.progress_update(scan_id,mod*4,"Webview Security Analysis")
    webview.wv_check(scan_id,manifest_file,java_folder,output_folder)

    DBconnect.progress_update(scan_id,mod*5,"Tapjacking Vulnerabilities")
    tapjack.find_layout(scan_id,layout_path,output_folder)
    
    DBconnect.progress_update(scan_id,mod*6,"Shared Storage Check")
    write_ex.search_ext(scan_id,java_folder,output_folder)
    
    DBconnect.progress_update(scan_id,mod*7,"SQL injection")
    sql.sqlinject(scan_id,java_folder,output_folder)
    
    DBconnect.progress_update(scan_id,mod*8,"Shared preferences")
    shared_pref.shared_preferences(scan_id,java_folder,output_folder)

    DBconnect.progress_update(scan_id,mod*9,"Weak encryption algorithms")
    cryptos.weakalgo(scan_id,java_folder,output_folder)

    DBconnect.progress_update(scan_id,mod*10,"Hardcoded Keys")
    cryptos.keyInFile(scan_id,java_folder,output_folder)

    DBconnect.progress_update(scan_id,mod*11,"Finding Crypto Keys")
    cryptos.find_key_files(scan_id,java_folder,key_path,output_folder)

    DBconnect.progress_update(scan_id,mod*12,"Insecure SSL/TLS implementation")
    ssl.find_ssl_vulnerabilities(scan_id,java_folder,output_folder)
    
    logcat.find_logcat(scan_id,java_folder,output_folder)
    DBconnect.progress_update(scan_id,mod*13,"Scan successfully completed")
    
    print "success"
    def testAPKIntentFilters(self):
        from androguard.core.bytecodes.apk import APK
        a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True)
        activities = a.get_activities()
        receivers = a.get_receivers()
        services = a.get_services()
        filter_list = []
        for i in activities:
            filters = a.get_intent_filters("activity", i)
            if len(filters) > 0:
                filter_list.append(filters)
        for i in receivers:
            filters = a.get_intent_filters("receiver", i)
            if len(filters) > 0:
                filter_list.append(filters)
        for i in services:
            filters = a.get_intent_filters("service", i)
            if len(filters) > 0:
                filter_list.append(filters)

        pairs = zip(filter_list, [{
            'action': ['android.intent.action.MAIN'],
            'category': ['android.intent.category.LAUNCHER']
        }, {
            'action': [
                'android.intent.action.BOOT_COMPLETED',
                'android.intent.action.MY_PACKAGE_REPLACED'
            ],
            'category': ['android.intent.category.HOME']
        }, {
            'action': ['android.appwidget.action.APPWIDGET_UPDATE']
        }, {
            'action': ['android.service.notification.NotificationListenerService']
        }])
        self.assertFalse(any(x != y for x, y in pairs))

        a = APK("examples/tests/com.test.intent_filter.apk", testzip=True)
        activities = a.get_activities()
        activities = a.get_activities()
        receivers = a.get_receivers()
        services = a.get_services()
        filter_list = []
        for i in activities:
            filters = a.get_intent_filters("activity", i)
            if len(filters) > 0:
                filter_list.append(filters)
        for i in receivers:
            filters = a.get_intent_filters("receiver", i)
            if len(filters) > 0:
                filter_list.append(filters)
        for i in services:
            filters = a.get_intent_filters("service", i)
            if len(filters) > 0:
                filter_list.append(filters)

        pairs = zip(filter_list, [{
            'action': ['android.intent.action.VIEW'],
            'category': [
                'android.intent.category.APP_BROWSER',
                'android.intent.category.DEFAULT', 'android.intent.category.BROWSABLE'
            ],
            'data': [{
                'scheme': 'testscheme',
                'host': 'testhost',
                'port': '0301',
                'path': '/testpath',
                'pathPattern': 'testpattern',
                'mimeType': 'text/html'
            }]
            }, {
                'action': ['android.intent.action.MAIN'],
                'category': ['android.intent.category.LAUNCHER']
            }, {
                'action': ['android.intent.action.VIEW'],
                'category':
                ['android.intent.category.DEFAULT', 'android.intent.category.BROWSABLE'],
                'data': [{
                    'scheme': 'testhost',
                    'host': 'testscheme',
                    'port': '0301',
                    'path': '/testpath',
                    'pathPattern': 'testpattern',
                    'mimeType': 'text/html'
                }]
            }, {
                'action': ['android.intent.action.RESPOND_VIA_MESSAGE'],
                'data': [{
                    'scheme': 'testhost',
                    'host': 'testscheme',
                    'port': '0301',
                    'path': '/testpath',
                    'pathPattern': 'testpattern',
                    'mimeType': 'text/html'
                }, {
                    'scheme': 'testscheme2',
                    'host': 'testhost2',
                    'port': '0301',
                    'path': '/testpath2',
                    'pathPattern': 'testpattern2',
                    'mimeType': 'image/png'
                }]
	    }])
        self.assertFalse(any(x != y for x, y in pairs))
예제 #22
0
def getFeatures(source_directory):
    ############################################################
    # Label tong hop
    with open(LabelsNum_file, "r+") as file_LabeslNum:
        LABELSNUMANDTEXT = json.load(file_LabeslNum)

    # doc file config
    with open(config_file, "r+") as f:
        dataConfig = json.load(f)

    maxLabelsNum = dataConfig['maxLabelsNum']
    #lay part Data
    partData = dataConfig['partData']
    time = datetime.datetime.now()
    partDataFile = str(partData) + '_' + str(time).strip() + '.csv'
    csvFile = open(r'DataCSV/' + partDataFile, 'w+', newline='')
    writer = csv.writer(csvFile, delimiter=',')

    source_directory = str(source_directory)

    #if not os.path.exists(output_folder):
    #    os.makedirs(output_folder)

    # Load Android API packages and classes
    global API_PACKAGES_LIST, API_CLASSES_LIST, API_SYSTEM_COMMANDS

    ############################################################
    # get name and labels
    ARRNAME, ARRLABELS = load_NameandLabels(labels)

    ############################################################
    # READING PACKAGES, CLASSES AND SYSTEM COMMANDS
    ############################################################
    package_file = load_file(str(package_index_file))
    API_PACKAGES_LIST = [x.strip() for x in package_file]

    class_file = load_file(str(classes_index_file))
    API_CLASSES_LIST = [x.strip() for x in class_file]

    commands_file = load_file(str(system_commands_file))
    API_SYSTEM_COMMANDS = [x.strip() for x in commands_file]
    ############################################################

    ############################################################

    apk_list = list_files(source_directory, '*.apk')

    for analyze_apk in tqdm(apk_list):

        # Getting the name of the folder that contains all apks and folders with apks
        base_folder = source_directory.split("/")[-1]

        apk_filename = join_dir(base_folder,
                                analyze_apk.replace(source_directory, ''))
        apk_filename = apk_filename.replace("//", "/")

        apk_name_no_extensions = "".join(
            apk_filename.split("/")[-1].split(".")[:-1])

        # export to monggoDB
        #if os.path.isfile(join_dir(output_folder, apk_filename.split("/")[-1].replace('.apk', '-analysis.json'))):
        #    database[apk_filename.replace('.apk', '')] = json.load(
        #        open(join_dir(output_folder, apk_filename.split("/")[-1].
        #                      replace('.apk', '-analysis.json'))))
        #    continue

        pre_static_dict = collections.OrderedDict()

        pre_static_dict['Filename'] = apk_filename

        hasher_md5 = hashlib.md5()
        hasher_sha256 = hashlib.sha256()
        hasher_sha1 = hashlib.sha1()
        with open(analyze_apk, 'rb') as afile:
            buf = afile.read()
            hasher_md5.update(buf)
            hasher_sha256.update(buf)
            hasher_sha1.update(buf)

        md5 = hasher_md5.hexdigest()
        sha256 = hasher_sha256.hexdigest()
        sha1 = hasher_sha1.hexdigest()

        pre_static_dict["md5"] = md5
        pre_static_dict["sha256"] = sha256
        pre_static_dict["sha1"] = sha1
        """
        if label is not None:
            pre_static_dict["Label"] = label
        else:
            pre_static_dict["Label"] = "/".join(apk_filename.split("/")[:-1])
        """
        pre_static_dict["VT_positives"] = None

        try:
            androguard_apk_object = APK(analyze_apk)
        except Exception:
            print("ERROR in APK: " + apk_name_no_extensions)
            continue

        static_analysis_dict = collections.OrderedDict()
        # Package name
        static_analysis_dict[
            'Package name'] = androguard_apk_object.get_package()

        # Permissions
        static_analysis_dict[
            'Permissions'] = androguard_apk_object.get_permissions()

        # Activities
        try:
            list_activities = androguard_apk_object.get_activities()
        except UnicodeEncodeError:
            list_activities = []

        # Main activity
        static_analysis_dict[
            'Main activity'] = androguard_apk_object.get_main_activity()

        # Receivers
        try:
            list_receivers = androguard_apk_object.get_receivers()
        except UnicodeEncodeError:
            list_receivers = []

        # Services
        try:
            list_services = androguard_apk_object.get_services()
        except UnicodeEncodeError:
            list_services = []

        # API calls and Strings
        list_smali_api_calls, list_smali_strings = read_strings_and_apicalls(
            analyze_apk, API_PACKAGES_LIST, API_CLASSES_LIST)
        for api_call in list_smali_api_calls.keys():
            new_api_call = '.'.join(api_call.split(".")[:-1])
            if new_api_call in list_smali_api_calls.keys():
                list_smali_api_calls[new_api_call] = list_smali_api_calls[
                    new_api_call] + list_smali_api_calls[api_call]
            else:
                list_smali_api_calls[new_api_call] = list_smali_api_calls[
                    api_call]
                del list_smali_api_calls[api_call]
        static_analysis_dict['API calls'] = list_smali_api_calls
        static_analysis_dict['Strings'] = Counter(
            filter(None, list_smali_strings))

        # API packages

        API_packages_dict = collections.OrderedDict()
        android_list_packages_lenghts = [
            len(x.split(".")) for x in API_PACKAGES_LIST
        ]

        list_api_calls_keys = list_smali_api_calls.keys()
        for api_call in list_api_calls_keys:
            score = 0
            package_chosen = None
            for i, package in enumerate(API_PACKAGES_LIST):
                len_package = android_list_packages_lenghts[i]
                if api_call.startswith(package) and len_package > score:
                    score = len_package
                    package_chosen = package
            if package_chosen is not None:
                if not package_chosen in API_packages_dict.keys():
                    API_packages_dict[package_chosen] = list_smali_api_calls[
                        api_call]
                else:
                    API_packages_dict[package_chosen] += list_smali_api_calls[
                        api_call]

        static_analysis_dict['API packages'] = API_packages_dict

        # Intents
        try:
            static_analysis_dict['Intents'] = intents_analysis(
                join_dir(analyze_apk.replace('.apk', ''),
                         'AndroidManifest.xml'))
        except:
            static_analysis_dict['Intents'] = {'Failed to extract intents': 0}

        # Intents of activities
        intents_activities = collections.OrderedDict()
        for activity in list_activities:
            intents_activities[activity] = check_for_intents(
                join_dir(analyze_apk.replace('.apk', ''),
                         'AndroidManifest.xml'), activity, 'activity')
        static_analysis_dict['Activities'] = intents_activities

        # Intents of services
        intents_services = collections.OrderedDict()
        for service in list_services:
            intents_services[service] = check_for_intents(
                join_dir(analyze_apk.replace('.apk', ''),
                         'AndroidManifest.xml'), service, 'service')
        static_analysis_dict['Services'] = intents_services

        # Intents of receivers
        intents_receivers = collections.OrderedDict()
        for intent in list_receivers:
            intents_receivers[intent] = check_for_intents(
                join_dir(analyze_apk.replace('.apk', '/'),
                         'AndroidManifest.xml'), intent, 'receiver')
        static_analysis_dict['Receivers'] = intents_receivers

        row = standardData(pre_static_dict, static_analysis_dict)
        if md5 in ARRNAME:
            index = -1
            if md5 in ARRNAME:
                index = ARRNAME.index(md5)
            if sha256 in ARRNAME:
                index = ARRNAME.index(sha256)

            if index != -1:
                label = ARRLABELS[index]
                try:
                    if label not in LABELSNUMANDTEXT:
                        if 'SINGLETON' in label:
                            continue
                        continue
                        # maxLabelsNum += 1
                        # temp = collections.OrderedDict()
                        # temp[label] = maxLabelsNum
                        # LABELSNUMANDTEXT[label] = maxLabelsNum

                except:
                    continue
                labelNum = [LABELSNUMANDTEXT[label]]
                labelNum.extend(row)
                writer.writerow(labelNum)

        # apk_total_analysis = collections.OrderedDict([("Pre_static_analysis", pre_static_dict),
        #                                   ("Static_analysis", static_analysis_dict)])
        #
        # save_as_json(apk_total_analysis, output_name=join_dir(output_folder, apk_name_no_extensions +
        #                                                       "-analysis.json"))

    #save labelsnum neu co them nhan moo
    with open(str(LabelsNum_file), 'w+') as fp:
        json.dump(LABELSNUMANDTEXT, fp, indent=4)
    fp.close()

    # Save data config
    partData += 1
    dataConfig['partData'] = partData
    dataConfig['maxLabelsNum'] = maxLabelsNum

    with open(str(config_file), 'w+') as fp:
        json.dump(dataConfig, fp, indent=4)

    fp.close()

    csvFile.close()