예제 #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 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))
예제 #4
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
    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))
예제 #6
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()]
예제 #7
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