예제 #1
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()]
예제 #2
0
def check(indicators, path, verbose=False):
    """
    Check an APK with given indicators
    Returns True/False, string (explanation of the discovery)
    """
    m = hashlib.sha256()
    with open(path, 'rb') as f:
        data = f.read()
        m.update(data)
    res = search(m.hexdigest(), indicators['sha256'], 'value')
    if verbose:
        print("SHA256: {}".format(m.hexdigest()))
    if res:
        if verbose:
            print("Known Stalkerware hash: {}".format(res))
            return True, "Known Stalkerware hash: {}".format(res)
    else:
        if verbose:
            print("App hash not in the indicator database")

    apk = APK(path)
    res = search(apk.get_package(), indicators['appids'], 'package')
    if verbose:
        print("Package id: {}".format(apk.get_package()))
    if res:
        if verbose:
            print("Known stalkerware package id: {}".format(res))
        return True, "Known stalkerware package id: {}".format(res)
    else:
        if verbose:
            print("Package id not in the indicators")

    if len(apk.get_certificates()) > 0:
        cert = apk.get_certificates()[0]
        sha1 = cert.sha1_fingerprint.replace(' ', '')
        if verbose:
            print("Certificate: {}".format(sha1))
        res = search(sha1, indicators['certificates'], 'certificate')
        if res:
            if verbose:
                print("Known Stalkerware certificate: {}".format(res))
            return True, "Known Stalkerware certificate: {}".format(res)
        else:
            if verbose:
                print("Certificate not in the indicators")
    else:
        if verbose:
            print("No certificate in this APK")
    if 'yara' in indicators:
        for dex in apk.get_all_dex():
            res = indicators['yara'].match(data=dex)
            if len(res) > 0:
                if verbose:
                    print("Matches yara rules {}".format(res[0]))
                return True, "Yara rule {}".format(res[0])
            else:
                if verbose:
                    print("Does not match any yara rules")
    return False, ""
예제 #3
0
    def testAPKManifest(self):
        from androguard.core.bytecodes.apk import APK
        a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk",
                testzip=True)

        self.assertEqual(a.get_app_name(), "TestsAndroguardApplication")
        self.assertEqual(a.get_app_icon(), "res/drawable-hdpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=120),
                         "res/drawable-ldpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=160),
                         "res/drawable-mdpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=240),
                         "res/drawable-hdpi/icon.png")
        self.assertIsNone(a.get_app_icon(max_dpi=1))
        self.assertEqual(a.get_main_activity(),
                         "tests.androguard.TestActivity")
        self.assertEqual(a.get_package(), "tests.androguard")
        self.assertEqual(a.get_androidversion_code(), '1')
        self.assertEqual(a.get_androidversion_name(), "1.0")
        self.assertEqual(a.get_min_sdk_version(), "9")
        self.assertEqual(a.get_target_sdk_version(), "16")
        self.assertIsNone(a.get_max_sdk_version())
        self.assertEqual(a.get_permissions(), [])
        self.assertEqual(a.get_declared_permissions(), [])
        self.assertTrue(a.is_valid_APK())
예제 #4
0
파일: app.py 프로젝트: sjl872964789/home
class App(object):

    def __init__(self, app_path, root_path, app_name):
        print("Root path:"+root_path)
        assert app_path is not None
        self.logger = logging.getLogger(self.__class__.__name__)
        self.app_path = app_path

        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()
        if app_name is not None:
            self.app_name = app_name
        else:
            self.app_name = self.apk.get_app_name()
        print("Main activity:"+self.main_activity)
        print("Package name:"+self.package_name)
        self.output_path=root_path+self.package_name

    def get_package_name(self):
        """
        get package name of current app
        :return:
        """
        return self.package_name
예제 #5
0
def get_apk_info(f, root=None):
    """
    获取apk信息
    :param root:
    :param f:
    :return:
    """
    if root:
        apk_path = os.path.join(root, f)
    else:
        apk_path = os.path.join(download_dir, f)

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

    return apk_info
예제 #6
0
    def get_apk_info(self):
        apk = APK(self.apk_file)
        app_icon_file = apk.get_app_icon()
        app_icon_data = apk.get_file(app_icon_file)

        size = (256, 256)

        buffered = BytesIO()
        im = Image.open(BytesIO(app_icon_data))
        im = im.resize(size, Image.ANTIALIAS)
        im.save(buffered, "PNG")

        app_icon_b64 = "data:image/png;base64," + base64.b64encode(
            buffered.getvalue()).decode('utf-8')

        self.package_name = apk.get_package()
        self.app_name = apk.get_app_name()

        self.report_saver.package_name = self.package_name
        self.report_saver.app_name = self.app_name
        self.report_saver.version = apk.get_androidversion_code()
        self.report_saver.app_icon = app_icon_b64

        permission_parser = PermissionParser(mode='groups')
        permission_values = permission_parser.transform(
            apk.get_permissions()).flatten().tolist()
        permission_labels = permission_parser.labels()
        self.report_saver.permissions_actual = {
            permission_labels[i]: bool(v)
            for i, v in enumerate(permission_values)
        }
예제 #7
0
    def testFrameworkResAPK(self):
        from androguard.core.bytecodes.apk import APK

        a = APK("examples/tests/lineageos_nexus5_framework-res.apk")

        self.assertEqual(a.get_app_name(), 'Android System')
        self.assertEqual(a.get_package(), 'android')
예제 #8
0
 def perform_analysis(self):
     if self.apk_file and os.path.exists(self.apk_file):
         try:
             apk = APK(self.apk_file)
         except Exception, ex:
             print ex
             return
         
         self.permissions = apk.get_permissions()
         # duplicate permissions check
         if (len(self.permissions) != len(set(self.permissions))):
             self.permission_duplicate = True
             
         # remove duplicate permissions
         self.permissions = list(set(self.permissions))
         
         
         # uses-features
         features_name = apk.get_elements('uses-feature', 'android:name')
         if len(features_name) > 0:
             package_name = apk.get_package()
             features_used = apk.get_elements('uses-feature', 'android:required')
             for i in xrange(len(features_name)):
                 if features_name[i] != '':
                     if(features_used[i] != '%s.false' % package_name):
                         self.features.append(features_name[i])
         self.features = list(set(self.features))
예제 #9
0
    def testAPKPermissions(self):
        from androguard.core.bytecodes.apk import APK
        a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True)

        self.assertEqual(a.get_package(), "a2dp.Vol")
        self.assertListEqual(
            sorted(a.get_permissions()),
            sorted([
                "android.permission.RECEIVE_BOOT_COMPLETED",
                "android.permission.CHANGE_WIFI_STATE",
                "android.permission.ACCESS_WIFI_STATE",
                "android.permission.KILL_BACKGROUND_PROCESSES",
                "android.permission.BLUETOOTH",
                "android.permission.BLUETOOTH_ADMIN",
                "com.android.launcher.permission.READ_SETTINGS",
                "android.permission.RECEIVE_SMS",
                "android.permission.MODIFY_AUDIO_SETTINGS",
                "android.permission.READ_CONTACTS",
                "android.permission.ACCESS_COARSE_LOCATION",
                "android.permission.ACCESS_FINE_LOCATION",
                "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS",
                "android.permission.WRITE_EXTERNAL_STORAGE",
                "android.permission.READ_PHONE_STATE",
                "android.permission.BROADCAST_STICKY",
                "android.permission.GET_ACCOUNTS"
            ]))
    def testFrameworkResAPK(self):
        from androguard.core.bytecodes.apk import APK

        a = APK("examples/tests/lineageos_nexus5_framework-res.apk")

        self.assertEqual(a.get_app_name(), 'Android System')
        self.assertEqual(a.get_package(), 'android')
예제 #11
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
예제 #12
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
예제 #13
0
    def run(self):
        """Run Google play unofficial python api the get the google play information
        @return: list of google play features
        """
        self.key = "googleplay"
        googleplay = {}

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

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

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

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

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

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

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

                    if not app_detail.installationSize:
                        return googleplay

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

        return googleplay
예제 #14
0
def androsign_main(args_apk, args_hash, args_all, show):
    from androguard.core.bytecodes.apk import APK
    from androguard.util import get_certificate_name_string

    import hashlib
    import traceback
    from colorama import Fore, Style
    from asn1crypto import x509

    # Keep the list of hash functions in sync with cli/entry_points.py:sign
    hashfunctions = dict(md5=hashlib.md5,
                         sha1=hashlib.sha1,
                         sha256=hashlib.sha256,
                         sha512=hashlib.sha512,
                         )

    if args_hash.lower() not in hashfunctions:
        print("Hash function {} not supported!"
              .format(args_hash.lower()), file=sys.stderr)
        print("Use one of {}"
              .format(", ".join(hashfunctions.keys())), file=sys.stderr)
        sys.exit(1)

    for path in args_apk:
        try:
            a = APK(path)

            print("{}, package: '{}'".format(os.path.basename(path), a.get_package()))
            print("Is signed v1: {}".format(a.is_signed_v1()))
            print("Is signed v2: {}".format(a.is_signed_v2()))

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

            if len(certs) > 0:
                print("Found {} unique certificates".format(len(certs)))

            for cert in certs:
                if show:
                    x509_cert = x509.Certificate.load(cert)
                    print("Issuer:", get_certificate_name_string(x509_cert.issuer, short=True))
                    print("Subject:", get_certificate_name_string(x509_cert.subject, short=True))
                    print("Serial Number:", hex(x509_cert.serial_number))
                    print("Hash Algorithm:", x509_cert.hash_algo)
                    print("Signature Algorithm:", x509_cert.signature_algo)
                    print("Valid not before:", x509_cert['tbs_certificate']['validity']['not_before'].native)
                    print("Valid not after:", x509_cert['tbs_certificate']['validity']['not_after'].native)

                if not args_all:
                    print("{} {}".format(args_hash.lower(), hashfunctions[args_hash.lower()](cert).hexdigest()))
                else:
                    for k, v in hashfunctions.items():
                        print("{} {}".format(k, v(cert).hexdigest()))
                print()
        except:
            print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr)
            traceback.print_exc(file=sys.stderr)

        if len(args_apk) > 1:
            print()
예제 #15
0
def install_app_and_install_frida(app_path):
    app = APK(app_path)
    package_name = app.get_package()
    logger.info("Start ADB")
    adb = ADB()
    logger.info("Install APP")
    adb.install_app(app_path)
    logger.info("Frida Initialize")
    push_and_start_frida_server(adb)
    return package_name
예제 #16
0
def parse_apk(apk_path):
    apk = APK(apk_path)

    package = apk.get_package()
    version_code = apk.get_androidversion_code()
    version_name = apk.get_androidversion_name()
    tmp_icon = save_icon(apk, package)

    return {"version_code": version_code,
            "version_name": version_name,
            "tmp_icon": tmp_icon,
            "package": package}
예제 #17
0
def main():
    parser = get_parser()

    args = parser.parse_args()

    hashfunctions = dict(md5=hashlib.md5,
                         sha1=hashlib.sha1,
                         sha256=hashlib.sha256,
                         sha512=hashlib.sha512,
                        )

    if args.hash.lower() not in hashfunctions:
        print("Hash function {} not supported!".format(args.hash.lower()), file=sys.stderr)
        print("Use one of {}".format(", ".join(hashfunctions.keys())), file=sys.stderr)
        sys.exit(1)

    for path in args.apk:
        try:
            a = APK(path)

            print("{}, package: '{}'".format(os.path.basename(path), a.get_package()))
            print("Is signed v1: {}".format(a.is_signed_v1()))
            print("Is signed v2: {}".format(a.is_signed_v2()))

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

            if len(certs) > 0:
                print("Found {} unique certificates".format(len(certs)))

            for cert in certs:
                if args.show:
                    x509_cert = x509.Certificate.load(cert)
                    print("Issuer:", get_certificate_name_string(x509_cert.issuer, short=True))
                    print("Subject:", get_certificate_name_string(x509_cert.subject, short=True))
                    print("Serial Number:", hex(x509_cert.serial_number))
                    print("Hash Algorithm:", x509_cert.hash_algo)
                    print("Signature Algorithm:", x509_cert.signature_algo)
                    print("Valid not before:", x509_cert['tbs_certificate']['validity']['not_before'].native)
                    print("Valid not after:", x509_cert['tbs_certificate']['validity']['not_after'].native)

                if not args.all:
                    print("{} {}".format(args.hash.lower(), hashfunctions[args.hash.lower()](cert).hexdigest()))
                else:
                    for k, v in hashfunctions.items():
                        print("{} {}".format(k, v(cert).hexdigest()))
                print()
        except:
            print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr)
            traceback.print_exc(file=sys.stderr)

        if len(args.apk) > 1:
            print()
예제 #18
0
    def __edit_text_analyse__(self, a: apk.APK, d: DalvikVMFormat,
                              dx: Analysis):

        # load keywords
        with open(
                os.path.join(os.path.dirname(__file__),
                             "assets" + os.path.sep + 'pii_keywords.txt'),
                'r') as file:
            keywords: [str] = file.read().splitlines(False)

        # parse flowdroid results
        folder = os.path.join(os.path.dirname(__file__),
                              "results" + os.path.sep + "flowdroid")

        file_name = a.get_filename().split(os.path.sep)[-1][:-4]
        fd_path = os.path.join(folder, file_name + ".xml")

        self.leak_id_names: [str] = []

        if not os.path.exists(fd_path):
            print("Flowdroid result doesn't exist")
            return

        resource_list = self.__analyse_flowdroid_result__(fd_path)

        resource_ids = []
        for s_id, s_method, s_statement, sink_method, sink_statement in resource_list:
            resource_ids.append(s_id)

        # find Resource class
        package_name = a.get_package()
        package_name = package_name.replace(".", "/")

        cls: ClassDefItem = d.get_class("L" + package_name +
                                        "/R$id;")  # find resource id
        if cls is None:
            print("This application doesn't have an R class")
            return

        fields: [EncodedField] = cls.get_fields()

        # match ids with keywords
        for field in fields:
            field: EncodedField = field
            value: EncodedValue = field.get_init_value()

            # resource id -> resource name
            the_value = str(value.get_value())
            field_name = field.get_name()
            if the_value in resource_ids and field_name in keywords:
                self.leak_id_names.append(field_name)
예제 #19
0
class StaticAnalysis:
    def __init__(self):
        print "Static Analysis"
        self.apk = None

    def load_apk(self, apk):
        if apk is not None and os.path.isfile(apk):
            self.apk = APK(apk)
        else:
            raise IOError("{0} could not be loaded".format(apk))

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

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

        from androguard.core.bytecodes.apk import APK

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

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

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

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

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

        return "", ""
예제 #21
0
class StaticAnalysis:

    def __init__(self):
        print "Static Analysis"
        self.apk = None     
   
    def load_apk(self, apk):
        if apk is not None and os.path.isfile(apk):
	    self.apk = APK(apk)
        else:
	    raise IOError("{0} could not be loaded".format(apk))

    def get_apk_package(self):
        try:
	    return self.apk.get_package()
	except Exception, e:
	    raise e
예제 #22
0
 def retrieve_content_from_apk(self):
     a = APK(self.filename)
     package_name = a.get_package()
     resources = a.get_android_resources()  # .get_strings_resources()
     self.client_id = resources.get_string(package_name,
                                           "PSA_API_CLIENT_ID_PROD")[1]
     self.client_secret = resources.get_string(
         package_name, "PSA_API_CLIENT_SECRET_PROD")[1]
     self.host_brandid_prod = resources.get_string(package_name,
                                                   "HOST_BRANDID_PROD")[1]
     self.culture = self.__get_cultures_code(
         a.get_file("res/raw/cultures.json"), self.country_code)
     ## Get Customer id
     self.site_code = BRAND[package_name][
         "brand_code"] + "_" + self.country_code + "_ESP"
     pfx_cert = a.get_file("assets/MWPMYMA1.pfx")
     save_key_to_pem(pfx_cert, b"y5Y2my5B")
예제 #23
0
def extract_apk_permisson(name,category):
    path = '/media/新加卷/begin_android_english/'+category+'/'+name+'.apk'
    try:
        apk=APK(path)
        if apk.is_valid_APK():
            package=apk.get_package()
            permissions=apk.get_permissions()
            # clean repeat permission
            simple_permissions=set()
            for p in permissions:
                p=p.split('.')[-1]
                if PERMISSIONS.has_key(p):
                    simple_permissions.add(p)

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

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

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

            insert_sql=insert_sql+attrs+') '+values

            #print insert_sql
            db.insert(insert_sql)

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

        etype, evalue, tracebackObj = sys.exc_info()[:3]
        print ('apk:%s errortype:%s errorvalue:%s'%(path,etype,evalue))
    finally:
        sql = "update apk set state = 0 where package='%s'"%name
        print sql
        db1.update(sql)
        print 1
예제 #24
0
def main():
    parser = get_parser()

    args = parser.parse_args()

    hashfunctions = dict(md5=hashlib.md5,
                         sha1=hashlib.sha1,
                         sha256=hashlib.sha256,
                         sha512=hashlib.sha512,
                        )

    if args.hash.lower() not in hashfunctions:
        print("Hash function {} not supported!".format(args.hash.lower()), file=sys.stderr)
        print("Use one of {}".format(", ".join(hashfunctions.keys())), file=sys.stderr)
        sys.exit(1)

    for path in args.apk:
        try:
            a = APK(path)

            print("{}, package: '{}'".format(os.path.basename(path), a.get_package()))
            print("Is signed v1: {}".format(a.is_signed_v1()))
            print("Is signed v2: {}".format(a.is_signed_v2()))

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

            if len(certs) > 0:
                print("Found {} unique certificates".format(len(certs)))

            for cert in certs:

                if not args.all:
                    print("{} {}".format(args.hash.lower(), hashfunctions[args.hash.lower()](cert).hexdigest()))
                else:
                    for k, v in hashfunctions.items():
                        print("{} {}".format(k, v(cert).hexdigest()))
        except:
            print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr)
            traceback.print_exc(file=sys.stderr)

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

        self.assertEqual(a.get_app_name(), "TestsAndroguardApplication")
        self.assertEqual(a.get_app_icon(), "res/drawable-hdpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=120), "res/drawable-ldpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=160), "res/drawable-mdpi/icon.png")
        self.assertEqual(a.get_app_icon(max_dpi=240), "res/drawable-hdpi/icon.png")
        self.assertIsNone(a.get_app_icon(max_dpi=1))
        self.assertEqual(a.get_main_activity(), "tests.androguard.TestActivity")
        self.assertEqual(a.get_package(), "tests.androguard")
        self.assertEqual(a.get_androidversion_code(), '1')
        self.assertEqual(a.get_androidversion_name(), "1.0")
        self.assertEqual(a.get_min_sdk_version(), "9")
        self.assertEqual(a.get_target_sdk_version(), "16")
        self.assertIsNone(a.get_max_sdk_version())
        self.assertEqual(a.get_permissions(), [])
        self.assertEqual(a.get_declared_permissions(), [])
        self.assertTrue(a.is_valid_APK())
예제 #26
0
def install_app_and_install_frida(app_path):
    """
        Install app and Frida script
    Parameters
    ----------
    app_path

    Returns
    -------

    """
    app = APK(app_path)
    package_name = app.get_package()
    logger.info("Start ADB")
    adb = ADB()
    logger.info("Install APP")
    adb.install_app(app_path)
    logger.info("Frida Initialize")
    push_and_start_frida_server(adb)
    return package_name
예제 #27
0
파일: objects.py 프로젝트: msr00t/cuckoo
    def get_apk_entry(self):
        """Get the entry point for this APK. The entry point is denoted by a
        package and main activity name."""
        filetype = self.get_type()
        if "Zip archive data" not in filetype and "Java archive data" not in filetype:
            return "", ""

        from androguard.core.bytecodes.apk import APK

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

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

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

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

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

        return "", ""
예제 #28
0
    def get_apk_info(self):
        apk = APK(self.apk_file)
        app_icon_file = apk.get_app_icon()
        app_icon_data = apk.get_file(app_icon_file)

        size = (256, 256)

        buffered = BytesIO()
        im = Image.open(BytesIO(app_icon_data))
        im = im.resize(size, Image.ANTIALIAS)
        im.save(buffered, "PNG")

        app_icon_b64 = "data:image/png;base64," + base64.b64encode(
            buffered.getvalue()).decode('utf-8')

        self.package_name = apk.get_package()
        self.app_name = apk.get_app_name()

        self.report_saver.package_name = self.package_name
        self.report_saver.app_name = self.app_name
        self.report_saver.version = apk.get_androidversion_code()
        self.report_saver.app_icon = app_icon_b64
예제 #29
0
    def testAPKPermissions(self):
        from androguard.core.bytecodes.apk import APK
        a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True)

        self.assertEqual(a.get_package(), "a2dp.Vol")
        self.assertListEqual(sorted(a.get_permissions()), sorted(["android.permission.RECEIVE_BOOT_COMPLETED",
                                                                  "android.permission.CHANGE_WIFI_STATE",
                                                                  "android.permission.ACCESS_WIFI_STATE",
                                                                  "android.permission.KILL_BACKGROUND_PROCESSES",
                                                                  "android.permission.BLUETOOTH",
                                                                  "android.permission.BLUETOOTH_ADMIN",
                                                                  "com.android.launcher.permission.READ_SETTINGS",
                                                                  "android.permission.RECEIVE_SMS",
                                                                  "android.permission.MODIFY_AUDIO_SETTINGS",
                                                                  "android.permission.READ_CONTACTS",
                                                                  "android.permission.ACCESS_COARSE_LOCATION",
                                                                  "android.permission.ACCESS_FINE_LOCATION",
                                                                  "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS",
                                                                  "android.permission.WRITE_EXTERNAL_STORAGE",
                                                                  "android.permission.READ_PHONE_STATE",
                                                                  "android.permission.BROADCAST_STICKY",
                                                                  "android.permission.GET_ACCOUNTS"]))
예제 #30
0
def install_app_and_install_frida(app_path, is_google_emulator: bool = False):
    """
        Install app and Frida script
    
    Parameters
    ----------
    app_path

    Returns
    -------

    """
    app = APK(app_path)
    package_name = app.get_package()
    logger.info("[*] Start ADB")
    adb = ADB()
    logger.info(f"[*] Install App {package_name}")
    adb.install_app(app_path)
    logger.info("[*] Frida Initialization")
    if not is_google_emulator:
        push_and_start_frida_server(adb)
    else:
        push_and_start_frida_server_google_emulator(adb)
    return package_name
예제 #31
0
class Run(Lobotomy):
    def __init__(self, ROOT_DIR):
        Lobotomy.__init__(self)
        self.ROOT_DIR = ROOT_DIR
        self.t = Terminal()
        self.logger = Logger()
        self.util = Util()
        self.apk = None
        self.package = None
        self.vm = None
        self.vmx = None
        self.gmx = None
        self.components = None
        self.dex = None
        self.strings = None
        self.permissions = None
        self.permissions_details = None
        self.files = None
        self.attack_surface = None

    def _cmd_completer(self, name, text, line, begidx, endidx):
        fn = getattr(self, 'do_'+name)
        if not hasattr(fn.im_func, "_expected_args"):
            return []
        a = [arg for arg in fn.im_func._expected_args if arg.startswith(text)]
        return a

    def find_dex(self):
        """
        Return True is classes.dex is found within the target APK.

        Args:
            None

        Returns:
            None
        """
        if self.files:
            for f in self.files:
                if "classes" in f:
                    return True
                    break

    def process_vm(self, apk=False, dex=False):
        """
        Process the application's classes.dex

        Args:
            param1 = boolean
            param2 = boolean

        Results:
            None
        """
        try:
            if apk:
                # Make sure the APK contains a classes.dex file
                if self.find_dex():
                    self.dex = self.apk.get_dex()
                    if self.dex:
                        self.logger.log("info", "Loading classes.dex ...")
                        from androguard.core.bytecodes.dvm import DalvikVMFormat
                        from androguard.core.analysis.analysis import VMAnalysis
                        from androguard.core.analysis.ganalysis import GVMAnalysis
                        # Create a DalvikVMFormat instance ...
                        # In this case self.dex will be a file type
                        self.vm = DalvikVMFormat(self.dex)
                        if self.vm:
                            print(self.t.yellow("\n\t--> Loaded classes.dex (!)\n"))
                            self.logger.log("info", "Analyzing classes.dex ...")
                            # Analyze the DalvikVMFormat instance and return
                            # analysis instances of VMAnalysis and GVMAnalysis
                            self.vmx = VMAnalysis(self.vm)
                            self.gmx = GVMAnalysis(self.vmx, None)
                            if self.vmx and self.gmx:
                                print(self.t.yellow("\n\t--> Analyzed classes.dex (!)\n"))
                                # Set the analysis properties on the
                                # DalvikVMFormat instance
                                self.vm.set_vmanalysis(self.vmx)
                                self.vm.set_gvmanalysis(self.gmx)
                                # Generate xref(s) and dref(s)
                                self.vm.create_xref()
                                self.vm.create_dref()
                                return
                            else:
                                CommandError("process_vm : Cannot analyze VM instance (!)")
                                return
                        else:
                            CommandError("process_vm : Cannot load VM instance (!)")
                            return
                    else:
                        CommandError("process_vm : classes.dex not found (!)")
                        return
            if dex:
                if self.dex:
                    from androguard.core.bytecodes.dvm import DalvikVMFormat
                    from androguard.core.analysis.analysis import VMAnalysis
                    from androguard.core.analysis.ganalysis import GVMAnalysis
                    # Analyze the DalvikVMFormat instance and return
                    # analysis instances of VMAnalysis and GVMAnalysis
                    self.vm = DalvikVMFormat(self.util.read(self.dex))
                    if self.vm:
                        print(self.t.yellow("\n\t--> Loaded {} (!)\n"
                                            .format(self.dex
                                                    .split("/")[-1])))
                        self.logger.log("info", "Analyzing {} ..."
                                        .format(self.dex
                                                .split("/")[-1]))
                        # Set the analysis properties on the
                        # DalvikVMFormat instance
                        self.vmx = VMAnalysis(self.vm)
                        self.gmx = GVMAnalysis(self.vmx, None)
                        if self.vmx and self.gmx:
                            print(self.t.yellow("\n\t--> Analyzed {} (!)\n"
                                                .format(self.dex
                                                        .split("/")[-1])))
                            # Set the analysis properties on the
                            # DalvikVMFormat instance
                            self.vm.set_vmanalysis(self.vmx)
                            self.vm.set_gvmanalysis(self.gmx)
                            # Generate xref(s) and dref(s)
                            self.vm.create_xref()
                            self.vm.create_dref()
                            return
                        else:
                            CommandError("process_vm :" +
                                         "Cannot analyze VM instance (!)")
                            return
                    else:
                        CommandError("process_vm :" +
                                     "Cannot load VM instance (!)")
                        return
                else:
                    CommandError("process_vm : classes.dex not found (!)")
                    return
        except Exception as e:
            CommandError("process_vm : {}".format(e))

    def complete_operate(self, *args):
        return self._cmd_completer("operate", *args)

    @cmd_arguments(["apk", "dex"])
    def do_operate(self, *args):
        """
        := operate apk path_to_apk
        := operate dex path_to_classes.dex
        """
        # Locals
        arg0 = args[0].split(" ")[0]
        arg1 = args[0].split(" ")[1]

        try:
            if arg0 == "apk":
                if arg1:
                    self.logger.log("info", "Loading : {} ..."
                                    .format(arg1.split("/")[-1]))
                    from androguard.core.bytecodes.apk import APK
                    self.apk = APK(arg1)
                    if self.apk:
                        print(self.t.yellow("\n\t--> Loaded : {} (!)\n"
                                            .format(arg1.split("/")[-1])))
                        self.package = self.apk.get_package()
                        from core.brains.apk.components import Components
                        # Load activies, services, broadcast receivers, and
                        # content providers
                        self.components = Components(self.apk)
                        self.components.enumerate_components()
                        self.permissions = self.apk.get_permissions()
                        self.files = self.apk.get_files()
                        self.files_type = self.apk.get_files_types()
                        # Process DVM
                        self.process_vm(apk=True)
                    else:
                        CommandError("APK not loaded (!)")
            elif arg0 == "dex":
                if arg1:
                    self.logger.log("info", "Loading : {} ..."
                                    .format(arg1.split("/")[-1]))
                    self.dex = arg1
                    self.process_vm(dex=True)
        except ImportError as e:
            CommandError("operate : {}".format(e))

    def complete_surgical(self, *args):
        return self._cmd_completer("surgical", *args)

    def do_surgical(self, *args):
        """
        := surgical
        """
        try:
            if self.vm and self.vmx:
                from .surgical import Run
                run = Run(self.vm, self.vmx)
                run.prompt = self.t.yellow("(surgical) ")
                run.ruler = self.t.yellow("-")
                run.cmdloop()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError("surgical : {}".format(e))

    def complete_attacksurface(self, *args):
        return self._cmd_completer("attacksurface", *args)

    def do_attacksurface(self, *args):
        """
        := attacksurface
        """
        try:
            if self.apk and self.components:
                self.logger.log("info", "Loading attacksurface module ...")
                from core.brains.apk.attacksurface import AttackSurface
                self.attack_surface = AttackSurface(self.apk, self.components)
                self.attack_surface.run()
                # Helps with visual spacing after the results are printed
                print("\n")
        except ImportError as e:
            CommandError("attacksurface : {}".format(e))

    def complete_permissions(self, *args):
        return self._cmd_completer("permissions", *args)

    @cmd_arguments(["list"])
    def do_permissions(self, *args):
        """
        := permissions list
        """
        # Locals
        arg0 = args[0]

        try:
            if self.permissions:
                if args[0] == "list":
                    self.logger.log("info", "Loading permissions ... \n")
                    for p in self.permissions:
                        print(self.t.yellow("\t--> {}".format(p)))
                    print("\n")
            else:
                CommandError("Permissions not found (!)")
        except Exception as e:
            CommandError("permissions : {}".format(e))

    def complete_binja(self, *args):
        return self._cmd_completer("binja", *args)

    def do_binja(self, *args):
        """
        := binja
        """
        try:
            from .binja import Run
            run = Run(self.files, self.apk)
            run.prompt = self.t.cyan("(binja) ")
            run.ruler = self.t.cyan("-")
            run.cmdloop()
        except Exception as e:
            CommandError("binja : {}".format(e))



    def complete_files(self, *args):
        return self._cmd_completer("files", *args)

    @cmd_arguments(["all", "assets", "libs", "res"])
    def do_files(self, *args):
        """
        := files all
        := files assets
        := files libs
        := files res
        """
        # Locals
        arg0 = args[0]

        try:
            if self.files:
                if arg0 == "assets":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        if f.startswith("assets"):
                            print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
                elif arg0 == "libs":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        if f.startswith("lib"):
                            print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
                elif arg0 == "res":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        if f.startswith("res"):
                            print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
                elif arg0 == "all":
                    self.logger.log("info", "Loading files ... \n")
                    for f in self.files:
                        print(self.t.yellow("\t--> {}".format(f)))
                    print("\n")
            else:
                CommandError("Files not populated (!)")
        except Exception as e:
            CommandError("files : {}".format(e))

    def complete_strings(self, *args):
        return self._cmd_completer("strings", *args)

    @cmd_arguments(["list", "search"])
    def do_strings(self, *args):
        """
        List and search for strings found in classes.dex

        := strings list
        := strings search
        """
        # Locals
        arg0 = args[0]
        strings = None

        try:
            if arg0 == "list":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        for s in strings:
                            print(self.t.cyan("--> {}".format(s.encode("utf-8", errors="ignore"))))
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
            elif arg0 == "search":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        target = raw_input(self.t.yellow("\n\t--> Enter string : "))
                        for s in strings:
                            if target in s:
                                print(self.t.cyan("\t\t --> {}".format(s.encode("utf-8", errors="ignore"))))
                        print("\n")
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError("strings : {}".format(e))

    def complete_components(self, *args):
        return self._cmd_completer("components", *args)

    @cmd_arguments(["list"])
    def do_components(self, *args):
        """
        := components list
        """
        # Locals
        arg0 = args[0]

        try:
            if arg0 == "list":
                if self.apk:
                    self.logger.log("info", "Enumerating components ...\n")
                    if self.components.activities:
                        for a in self.components.activities:
                            print(self.t.yellow("\t--> activity : {}"
                                                .format(a)))
                        print("\n")
                    if self.components.services:
                        for s in self.components.services:
                            print(self.t.yellow("\t--> service : {}"
                                                .format(s)))
                        print("\n")
                    if self.components.receivers:
                        for r in self.components.receivers:
                            print(self.t.yellow("\t--> receiver : {}"
                                                .format(r)))
                        print("\n")
                    if self.components.providers:
                        for r in self.components.providers:
                            print(self.t.yellow("\t--> provider : {}"
                                                .format(s)))
                        print("\n")
                else:
                    CommandError("APK not loaded (!)")
        except Exception as e:
            CommandError("components : {}".format(e))

    def complete_interact(self, *args):
        return self._cmd_completer("interact", *args)

    def do_interact(self, *args):
        """
        Drop into an interactive IPython session.

        := interact
        """
        try:
            if self.vm and self.vmx:
                from core.brains.interact.interact import Interact
                i = Interact(self.vm, self.vmx)
                i.run()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError("interact : {}".format(e.message))

    def complete_class_tree(self, *args):
        return self._cmd_completer("class_tree", *args)

    def do_class_tree(self, *args):
        """
        := class_tree
        """
        try:
            if self.vm:
                for c in self.vm.get_classes():
                    # We don't care about Android support classes or resource
                    # classes
                    if c.name.startswith("Landroid") or \
                            c.name.split("/")[-1].startswith("R"):
                        continue
                    print("\n")
                    print(self.t.yellow("\t--> class : {} {}".format(c.get_access_flags_string(), c.name)))
                    for f in c.get_fields():
                        print(self.t.white("\t\t--> field : {} {} {}".format(f.get_access_flags_string(), f.get_descriptor(), f.name)))
                    for m in c.get_methods():
                        print(self.t.cyan("\t\t\t--> method : {} {} {}".format(m.get_access_flags_string(), m.name, m.get_descriptor())))
                print("\n")
            else:
                CommandError("class_tree : classes.dex not loaded (!)")
        except Exception as e:
            CommandError("class_tree : {}".format(e))

    def complete_native(self, *args):
        return self._cmd_completer("native", *args)

    def do_native(self, *args):
        """
        := native
        """
        # Locals
        native_methods = list()

        try:
            if self.vm:
                for method in self.vm.get_methods():
                    if method.get_access_flags() & 0x100:
                        native_methods.append((method.get_class_name(),
                                               method.get_name()))
                if native_methods:
                    print("\n")
                    for n in native_methods:
                        print(self.t.cyan("\t--> {} : {}".format(n[0], n[1])))
                    print("\n")
            else:
                self.logger.log("info",
                                "class_tree : classes.dex not loaded (!)")
        except Exception as e:
            CommandError("native : {}".format(e))

    def complete_ui(self, *args):
        return self._cmd_completer("ui", *args)

    def do_ui(self, *args):
        """
        := ui
        """
        try:
            if self.vm and self.vmx:
                from core.brains.ui.terminal import TerminalApp
                ui = TerminalApp(self.vm, self.vmx)
                ui.run()
        except Exception as e:
            CommandError("ui : {}".format(e))

    def complete_macro(self, *args):
        return self._cmd_completer("macro", *args)

    def do_macro(self, args):
        """
        := macro
        """
        # Locals
        directory_items = None
        macro = path.join(self.ROOT_DIR, "macro")
        selection = None
        apk_path = None
        json = None

        try:
            print("\n")
            directory_items = listdir(macro)
            for i, item in enumerate(directory_items):
                print(self.t.cyan("\t--> [{}] {}"
                                  .format(i, item)))
            print("\n")
            selection = raw_input(self.t.yellow("[{}] Select config : ".format(datetime.now())))
            try:
                index = int(selection)
            except ValueError:
                index = -1
            print("\n")
            if selection:
                for i, item in enumerate(directory_items):
                    if selection == item or i == index:
                        selection = item
                        break
                with open("".join([macro, "/", selection]), "rb") as config:
                    # Load the config as JSON
                    json = loads(config.read())
                    if json:
                        for k, v in json.items():
                            if k == "apk":
                                if v:
                                    apk_path = str(v)
                                    # Call operate() with the path to apk
                                    self.do_operate("apk {}"
                                                    .format(apk_path))
                                    return
                                else:
                                    CommandError("macro : Path to APK not found in {}"
                                                 .format(selection))
                            else:
                                CommandError("macro : Error loading {} as JSON"
                                             .format(selection))
        except Exception as e:
            CommandError("macro : {}".format(e))
예제 #32
0
def main():
    parser = get_parser()

    args = parser.parse_args()

    hashfunctions = dict(
        md5=hashlib.md5,
        sha1=hashlib.sha1,
        sha256=hashlib.sha256,
        sha512=hashlib.sha512,
    )

    if args.hash.lower() not in hashfunctions:
        print("Hash function {} not supported!".format(args.hash.lower()),
              file=sys.stderr)
        print("Use one of {}".format(", ".join(hashfunctions.keys())),
              file=sys.stderr)
        sys.exit(1)

    for path in args.apk:
        try:
            a = APK(path)

            print("{}, package: '{}'".format(os.path.basename(path),
                                             a.get_package()))
            print("Is signed v1: {}".format(a.is_signed_v1()))
            print("Is signed v2: {}".format(a.is_signed_v2()))

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

            if len(certs) > 0:
                print("Found {} unique certificates".format(len(certs)))

            for cert in certs:
                if args.show:
                    x509_cert = x509.Certificate.load(cert)
                    print(
                        "Issuer:",
                        get_certificate_name_string(x509_cert.issuer,
                                                    short=True))
                    print(
                        "Subject:",
                        get_certificate_name_string(x509_cert.subject,
                                                    short=True))
                    print("Serial Number:", hex(x509_cert.serial_number))
                    print("Hash Algorithm:", x509_cert.hash_algo)
                    print("Signature Algorithm:", x509_cert.signature_algo)
                    print(
                        "Valid not before:", x509_cert['tbs_certificate']
                        ['validity']['not_before'].native)
                    print(
                        "Valid not after:", x509_cert['tbs_certificate']
                        ['validity']['not_after'].native)

                if not args.all:
                    print("{} {}".format(
                        args.hash.lower(),
                        hashfunctions[args.hash.lower()](cert).hexdigest()))
                else:
                    for k, v in hashfunctions.items():
                        print("{} {}".format(k, v(cert).hexdigest()))
                print()
        except:
            print(Fore.RED + "Error in {}".format(os.path.basename(path)) +
                  Style.RESET_ALL,
                  file=sys.stderr)
            traceback.print_exc(file=sys.stderr)

        if len(args.apk) > 1:
            print()
예제 #33
0
def get_package_name(apk_path):
    """
    Extract the package name of an APK
    """
    a = APK(apk_path)
    return a.get_package(), a.get_androidversion_code()
예제 #34
0
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()))


current_dir = os.getcwd()
script_dir = dir_path = os.path.dirname(os.path.realpath(__file__))
if sys.version_info < (3, 6):
    raise RuntimeError("This application requires Python 3.6+")

if not argv[1].endswith(".apk"):
    print("No apk given")
    sys.exit(1)
print("APK loading...")
a = APK(argv[1])
package_name = a.get_package()
resources = a.get_android_resources()  # .get_strings_resources()
client_id = resources.get_string(package_name, "PSA_API_CLIENT_ID_PROD")[1]
client_secret = resources.get_string(package_name,
                                     "PSA_API_CLIENT_SECRET_PROD")[1]
HOST_BRANDID_PROD = resources.get_string(package_name, "HOST_BRANDID_PROD")[1]
pfx_cert = a.get_file("assets/MWPMYMA1.pfx")
REMOTE_REFRESH_TOKEN = None
print("APK loaded !")

client_email = input(f"{BRAND[package_name]['app_name']} email: ")
client_password = getpass(f"{BRAND[package_name]['app_name']} password: "******"What is your country code ? (ex: FR, GB, DE, ES...)\n")

## Get Customer id
예제 #35
0
class XAPK:
    def __init__(self, folder):
        self.folder = Path(folder)
        for x in self.folder.glob('*.apk'):
            self.apk_src = Path(x)
            break
        for x in self.folder.glob('*.obb'):
            self.obb_src = Path(x)
            break
        self.apk = APK(self.apk_src)
        self.manifest = self.make_manifest()
        self.icon = self.apk.get_file(self.apk.get_app_icon())

    def make_manifest(self):
        apk_size = self.apk_src.stat().st_size
        if self.obb_src:
            obb_size = self.obb_src.stat().st_size
        else:
            obb_size = 0
        total_size = apk_size + obb_size
        filename = self.apk.get_filename()

        manifest = {}
        manifest['xapk_version'] = 1
        manifest['package_name'] = self.apk.get_package()
        manifest['name'] = self.apk.get_app_name()
        # manifest['locales_name'] = {} # TODO
        manifest['version_code'] = self.apk.get_androidversion_code()
        manifest['version_name'] = self.apk.get_androidversion_name()
        manifest['min_sdk_version'] = self.apk.get_min_sdk_version()
        manifest['target_sdk_version'] = self.apk.get_target_sdk_version()
        manifest['permissions'] = self.apk.get_declared_permissions()
        manifest['total_size'] = total_size
        manifest['expansions'] = []

        if obb_size:
            main_obb = {}
            main_obb[
                'file'] = 'Android/obb/{package_name}/main.{version_code}.{package_name}.obb'.format(
                    **manifest)
            main_obb['install_location'] = 'EXTERNAL_STORAGE'
            main_obb[
                'install_path'] = 'Android/obb/{package_name}/main.{version_code}.{package_name}.obb'.format(
                    **manifest)
            manifest['expansions'].push(main_obb)

        return manifest

    def save(self):
        self.name = '{package_name}_v{version_name}.xapk'.format(
            **self.manifest)
        zip_path = self.folder.joinpath(self.name)

        zip_dir = tempfile.mkdtemp()
        try:
            print('copying apk to temp directory...')
            apk_name = '{package_name}.apk'.format(**self.manifest)
            apk_src = self.apk_src.resolve()
            apk_dest = PurePath(zip_dir).joinpath(apk_name)
            shutil.copy2(apk_src, apk_dest)
            print('apk: OK')

            if self.manifest.get('expansions'):
                print('copying obb to temp directory...')
                obb_name = self.manifest['expansions'][0]['install_path']
                obb_src = self.obb_src.resolve()
                obb_dest = PurePath(zip_dir).joinpath(obb_name)
                os.makedirs(Path(obb_dest).parent, exist_ok=True)
                shutil.copy2(obb_src, obb_dest)
                print('obb: OK')
            else:
                print('no obb found')

            print('creating icon in temp directory...')
            icon = self.icon
            icon_dest = PurePath(zip_dir).joinpath('icon.png')
            with open(icon_dest, 'wb') as iconfile:
                iconfile.write(icon)
            print('icon: OK')

            print('creating manifest in temp directory...')
            manifest_dest = PurePath(zip_dir).joinpath('manifest.json')
            with open(manifest_dest, 'w') as manifestfile:
                s = json.dumps(self.manifest, separators=(':', ','))
                manifestfile.write(s)
            print('manifest: OK')

            print('creating xapk archive...')
            with zipfile.ZipFile(zip_path,
                                 'w',
                                 compression=zipfile.ZIP_DEFLATED) as zfd:
                for root, dirs, files in os.walk(zip_dir):
                    for f in files:
                        filename = os.path.join(root, f)
                        zfd.write(filename, os.path.relpath(filename, zip_dir))
            print('xapk: OK')
        finally:
            print('cleaning up temp directory...')
            shutil.rmtree(zip_dir)
            print('cleanup: OK')
예제 #36
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
예제 #37
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)
예제 #38
0
class Run(Lobotomy):
    def __init__(self):
        Lobotomy.__init__(self)
        self.t = Terminal()
        self.logger = Logger()
        self.util = Util()
        self.apk = None
        self.package = None
        self.vm = None
        self.vmx = None
        self.gmx = None
        self.components = None
        self.dex = None
        self.strings = None
        self.permissions = None
        self.permissions_details = None
        self.files = None
        self.attack_surface = None

    def find_dex(self):
        """
        Return True is classes.dex is found within the target APK.

        Args:
            None

        Returns:
            None
        """
        if self.files:
            for f in self.files:
                if "classes" in f:
                    return True
                    break

    def process_vm(self):
        """
        Process the application's classes.dex

        Args:
            None

        Results:
            None
        """
        # Make sure classes.dex exists
        if self.find_dex():
            self.dex = self.apk.get_dex()
            # Analyze classes.dex
            # TODO Throw in a progress bar, this can take awhile
            if self.dex:
                self.logger.log("info", "Loading classes.dex ...")
                from androguard.core.bytecodes.dvm import DalvikVMFormat
                from androguard.core.analysis.analysis import VMAnalysis
                from androguard.core.analysis.ganalysis import GVMAnalysis
                # Create a new virtual machine instance
                self.vm = DalvikVMFormat(self.dex)
                if self.vm:
                    print(self.t.yellow("\n\t--> Loaded classes.dex (!)\n"))
                    self.logger.log("info", "Analyzing classes.dex ...")
                    # Analyze the virtual machine instance
                    self.vmx = VMAnalysis(self.vm)
                    self.gmx = GVMAnalysis(self.vmx, None)
                    if self.vmx and self.gmx:
                        print(self.t.yellow("\n\t--> Analyzed classes.dex (!)\n"))
                        self.vm.set_vmanalysis(self.vmx)
                        self.vm.set_gvmanalysis(self.gmx)
                        # Generate xref(s)
                        self.vm.create_xref()
                        self.vm.create_dref()
                    else:
                        CommandError("Cannot analyze VM instance (!)")
                else:
                    CommandError("Cannot load VM instance (!)")
        else:
            CommandError("classes.dex not found (!)")

    def do_operate(self, args):
        """
        := operate apk path_to_apk
        := operate dex path_to_classes.dex
        """
        try:
            if args.split()[0] == "apk":
                if args.split()[1]:
                    self.logger.log("info", "Loading : {} ...".format(args.split()[1].split("/")[-1]))
                    from androguard.core.bytecodes.apk import APK
                    self.apk = APK(args.split()[1])
                    if self.apk:
                        print(self.t.yellow("\n\t--> Loaded : {} (!)\n".format(args.split()[1].split("/")[-1])))
                        self.package = self.apk.get_package()
                        from core.brains.apk.components import Components
                        # Load activies, services, broadcast receivers, and
                        # content providers
                        self.components = Components(self.apk)
                        self.components.enumerate_components()
                        self.permissions = self.apk.get_permissions()
                        self.files = self.apk.get_files()
                        self.files_type = self.apk.get_files_types()
                        # Process virtual machine
                        self.process_vm()
                    else:
                        CommandError("APK not loaded (!)")
            else:
                CommandError("Unkown command (!)")
        except ImportError as e:
            CommandError(e.message)
        except IndexError as e:
            CommandError("Not enough arguments (!)")

    def do_surgical(self, args):
        """
        := surgical
        """

        try:
            if self.vm and self.vmx:
                from .surgical import Run
                run = Run(self.vm, self.vmx)
                run.prompt = self.t.yellow("(surgical) ")
                run.ruler = self.t.yellow("-")
                run.cmdloop()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError(e.message)

    def do_attacksurface(self, args):
        """
        := attacksurface
        """
        try:
            if self.apk and self.components:
                self.logger.log("info", "Loading attacksurface module ...")
                from core.brains.apk.attacksurface import AttackSurface
                self.attack_surface = AttackSurface(self.apk, self.components)
                self.attack_surface.run()
        except ImportError as e:
            CommandError(e.message)

    def do_permissions(self, args):
        """
        := permissions list
        """
        try:
            if self.permissions:
                if args.split()[0] == "list":
                    self.logger.log("info", "Loading permissions ... \n")
                    for p in self.permissions:
                        print(self.t.yellow("\t--> {}".format(p)))
                    print("\n")
            else:
                CommandError("Permissions not found (!)")
        except Exception as e:
            CommandError(e.message)

    def do_files(self, args):
        """
        := files all
        := files assets
        := files libs
        := files res
        """
        try:
            if self.files:
                if args.split()[0]:
                    if args.split()[0] == "assets":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            if f.startswith("assets"):
                                print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
                    elif args.split()[0] == "libs":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            if f.startswith("lib"):
                                print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
                    elif args.split()[0] == "res":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            if f.startswith("res"):
                                print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
                    elif args.split()[0] == "all":
                        self.logger.log("info", "Loading files ... \n")
                        for f in self.files:
                            print(self.t.yellow("\t--> {}".format(f)))
                        print("\n")
            else:
                CommandError("Files not populated (!)")
        except Exception as e:
            CommandError(e.message)

    def do_strings(self, args):
        """
        List and search for strings found in classes.dex

        := strings list
        := strings search
        """

        # Locals
        strings = None

        try:
            if args.split()[0] == "list":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        for s in strings:
                            print(self.t.cyan("--> {}".format(s.encode("utf-8"))))
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
            elif args.split()[0] == "search":
                if self.vm:
                    strings = self.vm.get_strings()
                    if strings:
                        target = raw_input(self.t.yellow("\n\t--> Enter string : \n"))
                        for s in strings:
                            if target in s:
                                print(self.t.cyan("\t\t --> {}".format(s)))
                        print("\n")
                    else:
                        CommandError("Strings not found (!)")
                else:
                    CommandError("classes.dex not loaded (!)")
            else:
                CommandError("Command not found (!)")
        except Exception as e:
            # We might be see an exception like this:
            # 'utf8' codec can't decode byte 0xc0 in position 0: invalid start byte
            raise e
            CommandError(e.message)

    def do_components(self, args):
        """
        := components list
        """
        try:
            if args.split()[0] == "list":
                if self.apk:
                    self.logger.log("info", "Enumerating components ...\n")
                    if self.components.activities:
                        for a in self.components.activities:
                            print(self.t.yellow("\t--> activity : {}".format(a)))
                        print("\n")
                    if self.components.services:
                        for s in self.components.services:
                            print(self.t.yellow("\t--> service : {}".format(s)))
                        print("\n")
                    if self.components.receivers:
                        for r in self.components.receivers:
                            print(self.t.yellow("\t--> receiver : {}".format(s)))
                        print("\n")
                    if self.components.providers:
                        for r in self.components.providers:
                            print(self.t.yellow("\t--> provider : {}".format(s)))
                        print("\n")
                else:
                    CommandError("APK not loaded (!)")
            else:
                CommandError("Command not found (!)")
        except Exception as e:
            CommandError(e.message)

    def do_interact(self, args):
        """
        Drop into an interactive IPython session.

        := interact
        """
        try:
            if self.vm and self.vmx:
                from core.brains.interact.interact import Interact
                i = Interact(self.vm, self.vmx)
                i.run()
            else:
                CommandError("classes.dex not loaded (!)")
        except Exception as e:
            CommandError(e.message)

    def do_macro(self, args):
        """
        """
        return
예제 #39
0
파일: main.py 프로젝트: tyxeron/androguard
def androsign_main(args_apk, args_hash, args_all, show):
    from androguard.core.bytecodes.apk import APK
    from androguard.util import get_certificate_name_string

    import hashlib
    import binascii
    import traceback
    from colorama import Fore, Style
    from asn1crypto import x509, keys
    from oscrypto import asymmetric

    # Keep the list of hash functions in sync with cli/entry_points.py:sign
    hashfunctions = dict(md5=hashlib.md5,
                         sha1=hashlib.sha1,
                         sha256=hashlib.sha256,
                         sha512=hashlib.sha512,
                         )

    if args_hash.lower() not in hashfunctions:
        print("Hash function {} not supported!"
              .format(args_hash.lower()), file=sys.stderr)
        print("Use one of {}"
              .format(", ".join(hashfunctions.keys())), file=sys.stderr)
        sys.exit(1)

    for path in args_apk:
        try:
            a = APK(path)

            print("{}, package: '{}'".format(os.path.basename(path), a.get_package()))
            print("Is signed v1: {}".format(a.is_signed_v1()))
            print("Is signed v2: {}".format(a.is_signed_v2()))
            print("Is signed v3: {}".format(a.is_signed_v3()))

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

            if len(certs) > 0:
                print("Found {} unique certificates".format(len(certs)))

            for cert in certs:
                if show:
                    x509_cert = x509.Certificate.load(cert)
                    print("Issuer:", get_certificate_name_string(x509_cert.issuer, short=True))
                    print("Subject:", get_certificate_name_string(x509_cert.subject, short=True))
                    print("Serial Number:", hex(x509_cert.serial_number))
                    print("Hash Algorithm:", x509_cert.hash_algo)
                    print("Signature Algorithm:", x509_cert.signature_algo)
                    print("Valid not before:", x509_cert['tbs_certificate']['validity']['not_before'].native)
                    print("Valid not after:", x509_cert['tbs_certificate']['validity']['not_after'].native)

                if not args_all:
                    print("{} {}".format(args_hash.lower(), hashfunctions[args_hash.lower()](cert).hexdigest()))
                else:
                    for k, v in hashfunctions.items():
                        print("{} {}".format(k, v(cert).hexdigest()))
                print()

            if len(certs) > 0:
                print("Found {} unique public keys associated with the certs".format(len(pkeys)))

            for public_key in pkeys:
                if show:
                    x509_public_key = asymmetric.load_public_key(public_key)
                    print("PublicKey Algorithm:", x509_public_key.algorithm)
                    print("Bit Size:", x509_public_key.bit_size)
                    print("Fingerprint:", binascii.hexlify(x509_public_key.fingerprint))
                    try:
                        print("Hash Algorithm:", hash_algo(x509_public_key))
                    except ValueError as ve:
                        # RSA pkey does not have an hash algorithm
                        pass
                print()


        except:
            print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr)
            traceback.print_exc(file=sys.stderr)

        if len(args_apk) > 1:
            print()
예제 #40
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()]
예제 #41
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'
예제 #42
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