예제 #1
0
def filter_valid_apks(source_directory,
                      valid_apks_directory=None,
                      invalid_apks_directory=None,
                      with_color=True):
    """
    Analyses a set of Android apks with Androguard to filter valid and invalid samples
    If a JSON file with the same name that the app is found in the source directory, it is also moved

    Parameters
    ----------
    :param source_directory: Folder containing apk files
    :param valid_apks_directory: Folder where valid apks are saved
    :param invalid_apks_directory: Folder where invalid apks are saved
    :param with_color: If colors are used to print messages
    """
    if not isdir(source_directory):
        print "Folder not found!"
        sys.exit(0)

    if valid_apks_directory is None:
        valid_apks_directory = join_dir(source_directory, VALID_APKS_DIRECTORY)

    if invalid_apks_directory is None:
        invalid_apks_directory = join_dir(source_directory,
                                          INVALID_APKS_DIRECTORY)

    num_valid_apk = 0
    num_invalid_apk = 0

    files_apks = [
        f for f in listdir(source_directory)
        if isfile(join(source_directory, f)) and f.endswith(".apk")
    ]

    print str(len(files_apks)) + " apks found. Processing..."

    if not os.path.exists(valid_apks_directory):
        os.makedirs(valid_apks_directory)

    if not os.path.exists(invalid_apks_directory):
        os.makedirs(invalid_apks_directory)

    for apk in tqdm(files_apks):

        if not apk.endswith(".apk"):
            shutil.move(join_dir(source_directory, apk),
                        join_dir(source_directory, apk + ".apk"))
            apk += ".apk"

        json_file = apk.replace(".apk", ".json")
        try:
            apk_analysed = APK(join_dir(source_directory, apk))
            valid_apk = apk_analysed.valid_apk

        except:
            valid_apk = False

        if valid_apk:

            if isfile(join(source_directory, json_file)):
                shutil.move(join_dir(source_directory, json_file),
                            join_dir(valid_apks_directory, json_file))

            shutil.move(join_dir(source_directory, apk),
                        join_dir(valid_apks_directory, apk))
            num_valid_apk += 1
        else:
            if isfile(join(source_directory, json_file)):
                shutil.move(join_dir(source_directory, json_file),
                            join_dir(invalid_apks_directory, json_file))
            shutil.move(join_dir(source_directory, apk),
                        join_dir(invalid_apks_directory, apk))
            num_invalid_apk += 1

    print_message("TOTAL VALID APKS: " + str(num_valid_apk), with_color,
                  "green")
    print colored("TOTAL INVALID APKS: " + str(num_invalid_apk), "red")
예제 #2
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()
예제 #3
0
def cert_info(app_dir, app_file):
    """Return certificate information."""
    try:
        logger.info('Reading Code Signing Certificate')
        manifestfile = None
        manidat = ''
        cert_info = ''
        certlist = []
        cert_path = os.path.join(app_dir, 'META-INF/')

        apk_file = os.path.join(app_dir, app_file)
        hashfunctions = {
            'md5': hashlib.md5,
            'sha1': hashlib.sha1,
            'sha256': hashlib.sha256,
            'sha512': hashlib.sha512,
        }
        files = [
            f for f in os.listdir(cert_path)
            if os.path.isfile(os.path.join(cert_path, f))
        ]
        a = APK(apk_file)
        if a.is_signed():
            certlist.append('APK is signed')
        else:
            certlist.append('Missing certificate')
        certlist.append('v1 signature: {}'.format(a.is_signed_v1()))
        certlist.append('v2 signature: {}'.format(a.is_signed_v2()))
        certlist.append('v3 signature: {}'.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:
            certlist.append('Found {} unique certificates'.format(len(certs)))

        for cert in certs:
            x509_cert = x509.Certificate.load(cert)
            certlist.append('Subject: {}'.format(
                get_certificate_name_string(x509_cert.subject, short=True)))
            certlist.append('Signature Algorithm: {}'.format(
                x509_cert.signature_algo))
            certlist.append('Valid From: {}'.format(
                x509_cert['tbs_certificate']['validity']['not_before'].native))
            certlist.append('Valid To: {}'.format(
                x509_cert['tbs_certificate']['validity']['not_after'].native))
            certlist.append('Issuer: {}'.format(
                get_certificate_name_string(x509_cert.issuer, short=True)))
            certlist.append('Serial Number: {}'.format(
                hex(x509_cert.serial_number)))
            certlist.append('Hash Algorithm: {}'.format(x509_cert.hash_algo))
            for k, v in hashfunctions.items():
                certlist.append('{}: {}'.format(k, v(cert).hexdigest()))

        for public_key in pkeys:
            x509_public_key = asymmetric.load_public_key(public_key)
            certlist.append('PublicKey Algorithm: {}'.format(
                x509_public_key.algorithm))
            certlist.append('Bit Size: {}'.format(x509_public_key.bit_size))
            certlist.append('Fingerprint: {}'.format(
                binascii.hexlify(x509_public_key.fingerprint).decode('utf-8')))
        cert_info = '\n'.join(certlist)
        if 'MANIFEST.MF' in files:
            manifestfile = os.path.join(cert_path, 'MANIFEST.MF')
        if manifestfile:
            with open(manifestfile, 'r', encoding='utf-8') as manifile:
                manidat = manifile.read()
        sha256_digest = bool(re.findall(r'SHA-256-Digest', manidat))
        findings = []
        if a.is_signed():
            findings.append(('good', 'Application is signed with a code '
                             'signing certificate'))
        else:
            findings.append(('bad', 'Code signing certificate not found'))
        if a.is_signed_v1():
            status = 'bad'
            if a.is_signed_v2() or a.is_signed_v3():
                status = 'warning'
            findings.append(
                (status, 'Application is signed with v1 signature scheme, '
                 'making it vulnerable to Janus vulnerability on '
                 'Android <7.0'))
        if re.findall(r'CN=Android Debug', cert_info):
            findings.append(
                ('bad', 'Application signed with a debug certificate. '
                 'Production application must not be shipped '
                 'with a debug certificate.'))
        if re.findall(r'Hash Algorithm: sha1', cert_info):
            status = 'bad'
            desc = ('Application is signed with SHA1withRSA. '
                    'SHA1 hash algorithm is known to have '
                    'collision issues.')
            if sha256_digest:
                status = 'warning'
                desc += (' The manifest file indicates SHA256withRSA'
                         ' is in use.')
            findings.append((status, desc))
        cert_dic = {
            'certificate_info': cert_info,
            'certificate_findings': findings,
        }
        return cert_dic
    except Exception:
        logger.exception('Reading Code Signing Certificate')
        return {}
예제 #4
0
    def run(self):
        """Run Google play unofficial python api the get the google play information
        @return: list of google play features
        """
        self.key = "googleplay"
        googleplay = {}

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

        if not HAVE_ANDROGUARD:
            log.error("Could not find the Androguard library, please install "
                      "it. (`pip install androguard`)")

        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, BadZipfile) as e:
                raise CuckooProcessingError("Error opening file %s" % e)

        return googleplay
예제 #5
0
            # Parsing and calculating
            testme = nlp(apkstr)
            if testme.similarity(sample) > 0.7:
                for token in testme:
                    if token.pos_ == "PUNCT":
                        pass
                    else:
                        print(f"{cyan}({magenta}*{cyan})->{white} {apkstr}")


# Execution
if __name__ == '__main__':
    try:
        # Getting and parsing target APK
        targetAPK = str(sys.argv[1])
        parsed = APK(targetAPK)

        # Permissions side
        Analyzer(parsed)

        # Deep scanner
        DeepScan(parsed)

        # Strings side
        print(
            f"{infoS} Analyzing interesting strings. It will take a while...\n"
        )

        #Thread Number
        threadNumber = 0
예제 #6
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()
예제 #7
0
from androguard.core.bytecodes.apk import APK
from androguard.core.bytecodes.dvm import DalvikVMFormat
from androguard.core.bytecodes.dvm import ClassDefItem

a = APK("C:/Users/jysrm/OneDrive/바탕 화면/study/test.apk")
f = open("new.txt", 'w')

d = DalvikVMFormat(a)

code_item = d.get_codes_item()

code = code_item.show()

f.write(code)

f.close()
예제 #8
0
from androguard.core.bytecodes.axml import AXMLPrinter
from androguard.core.bytecodes.axml import ARSCParser

ANDROID_SCHEME = "{http://schemas.android.com/apk/res/android}scheme"
ANDROID_HOST = "{http://schemas.android.com/apk/res/android}host"
ANDROID_NAME = "{http://schemas.android.com/apk/res/android}name"
ANDROID_BACKUP = "{http://schemas.android.com/apk/res/android}allowBackup"
ANDROID_CLEAR = "{http://schemas.android.com/apk/res/android}usesCleartextTraffic"
ANDROID_VALUE = "{http://schemas.android.com/apk/res/android}value"


if len(sys.argv) != 2:
	print("Введите путь к APK\n")
	exit(400)
file = sys.argv[1]
apk = APK(file)
axml = apk.get_android_manifest_xml()
lil_pow = 0


print("Флаги безопасности Manifest'а\n"
		"а. Установки CleartextTraffic:")
guess = axml.find("./application[@{}]".format(ANDROID_CLEAR))
if guess != None:
	print(guess.attrib.get(ANDROID_CLEAR))
else:
	print("Не обнаружено.")

print("b. Установки allowBackup:")
guess = axml.find("./application[@{}]".format(ANDROID_BACKUP))
if guess != None:
예제 #9
0
def is_valid_apk(p, arg):
    if not (os.path.exists(arg) and os.path.isfile(arg)
            and APK(arg).is_valid_APK()):
        p.error("[ERROR] The APK file {} is not valid!".format(arg))
    return arg
예제 #10
0
def analyze_apk(task, scan_id):
    # Start the APK analysis
    global APK_PATH
    global DECOMPILE_PATH
    try:
        scan = Scan.objects.get(pk=scan_id)
        APK_PATH = settings.BASE_DIR + scan.apk.url
        DECOMPILE_PATH = os.path.splitext(APK_PATH)[0]
        scan.status = 'In Progress'
        scan.progress = 3
        scan.save()
        task.update_state(state = 'STARTED',
                meta = {'current': scan.progress, 'total': 100, 'status': scan.status})
        logger.debug(scan.status)
        a = APK(APK_PATH)
        scan = set_hash_app(scan)
        scan.status = 'Getting info of apk'
        scan.progress = 5
        scan.save()
        task.update_state(state = 'STARTED',
                meta = {'current': scan.progress, 'total': 100, 'status': scan.status})
        logger.debug(scan.status)
        scan = get_info_apk(a, scan)
        scan.status = 'Getting info of certificates'
        scan.progress = 10
        scan.save()
        task.update_state(state = 'STARTED',
                meta = {'current': scan.progress, 'total': 100, 'status': scan.status})
        logger.debug(scan.status)
        certificates = get_info_certificate(a, scan)
        if (settings.VIRUSTOTAL_ENABLED):
            scan.status = 'Getting info of VT'
            scan.progress = 15
            scan.save()
            task.update_state(state = 'STARTED',
                meta = {'current': scan.progress, 'total': 100, 'status': scan.status})
            logger.debug(scan.status)
            report = get_report_virus_total(scan, scan.sha256)
            if (not report and settings.VIRUSTOTAL_UPLOAD):
                scan.status = 'Upload to VT'
                scan.save()
                upload_virus_total(scan, APK_PATH, scan.sha256)
        scan.status = 'Decompiling'
        scan.progress = 20
        scan.save()
        task.update_state(state = 'STARTED',
                meta = {'current': scan.progress, 'total': 100, 'status': scan.status})
        logger.debug(scan.status)
        decompile_jadx()
        if (a.get_app_icon()):
            update_icon(scan, DECOMPILE_PATH + '/resources/' + a.get_app_icon())
        scan.status = 'Finding vulnerabilities'
        scan.progress = 40
        task.update_state(state = 'STARTED',
                meta = {'current': scan.progress, 'total': 100, 'status': scan.status})
        scan.save()
        logger.debug(scan.status)
        findings = get_tree_dir(scan)
        scan.status = 'Finished'
        scan.progress = 100
        scan.finished_on = datetime.now()
        scan.save()
        task.update_state(state = 'STARTED',
                meta = {'current': scan.progress, 'total': 100, 'status': scan.status})
        logger.debug(scan.status)
    except Exception as e:
        scan.progress = 100
        scan.status = "Error"
        scan.finished_on = datetime.now()
        scan.save()
        task.update_state(state = 'STARTED',
                meta = {'current': scan.progress, 'total': 100, 'status': scan.status})
        logger.error(e)
예제 #11
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)
예제 #12
0
def extract_features(file_path):
    result = {}
    try:
        a = APK(file_path)
        d = DalvikVMFormat(a.get_dex())
        dx = Analysis(d)
        vm = dvm.DalvikVMFormat(a.get_dex())
        vmx = analysis.Analysis(vm)
        d.set_vmanalysis(dx)
        d.set_decompiler(DecompilerDAD(d, dx))
    except Exception as e:
        print e
        return None

    result['android_version_code'] = a.get_androidversion_code()
    result['android_version_name'] = a.get_androidversion_name()
    result['max_sdk'] = a.get_max_sdk_version()
    result['min_sdk'] = a.get_min_sdk_version()
    result['libraries'] = a.get_libraries()
    result['filename'] = a.get_filename()
    result['target_sdk'] = a.get_target_sdk_version()
    result['md5'] = hashlib.md5(a.get_raw()).hexdigest()
    result['sha256'] = hashlib.sha256(a.get_raw()).hexdigest()
    result['permissions'] = a.get_permissions()
    result['activities'] = a.get_activities()
    result['providers'] = a.get_providers()
    result['services'] = a.get_services()
    result['strings'] = d.get_strings()
    result['class_names'] = [c.get_name() for c in d.get_classes()]
    result['method_names'] = [m.get_name() for m in d.get_methods()]
    result['field_names'] = [f.get_name() for f in d.get_fields()]
    # result['is_native_code'] = 1 if analysis.is_native_code(dx) else 0
    result['is_obfuscation'] = 1 if analysis.is_ascii_obfuscation(d) else 0
    # result['is_crypto_code'] = 1 if analysis.is_crypto_code(dx) else 0
    # result['is_dyn_code'] = 1 if analysis.is_dyn_code(dx) else 0
    # result['is_reflection_code'] = 1 if analysis.is_reflection_code(vmx) else 0
    result['is_database'] = 1 if d.get_regex_strings(DB_REGEX) else 0

    s_list = []
    s_list.extend(result['class_names'])
    s_list.extend(result['method_names'])
    s_list.extend(result['field_names'])
    result['entropy_rate'] = entropy_rate(s_list)

    result['feature_vectors'] = {}

    result['feature_vectors']['api_calls'] = []
    for call in API_CALLS:
        status = 1 if dx.get_method_by_name(".", call, ".") else 0
        result['feature_vectors']['api_calls'].append(status)

    result['feature_vectors']['permissions'] = []
    for permission in PERMISSIONS:
        status = 1 if permission in result['permissions'] else 0
        result['feature_vectors']['permissions'].append(status)

    result['feature_vectors']['special_strings'] = []
    for word in SPECIAL_STRINGS:
        status = 1 if d.get_regex_strings(word) else 0
        result['feature_vectors']['special_strings'].append(status)

    result['feature_vectors']['others'] = [
        # result['is_reflection_code'],
        # result['is_crypto_code'],
        # result['is_native_code'],
        result['is_obfuscation'],
        result['is_database'],
        # result['is_dyn_code']
    ]

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

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

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

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

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

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

                apkinfo["files_flaged"] = self.files_name_map

                manifest["permissions"] = get_permissions(a)
                manifest["main_activity"] = a.get_main_activity()
                manifest["activities"] = a.get_activities()
                manifest["services"] = a.get_services()
                manifest["receivers"] = a.get_receivers()
                manifest["receivers_actions"] = get_extended_receivers(a)
                manifest["providers"] = a.get_providers()
                manifest["libraries"] = 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
예제 #14
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'
예제 #15
0
            private_key.private_bytes(
                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")
예제 #16
0
    def testApksignAPKs(self):
        # These APKs are from the apksign testcases and cover
        # all different signature algorithms as well as some error cases
        from androguard.core.bytecodes.apk import APK
        import zipfile
        from asn1crypto import x509, pem
        import binascii
        root = "examples/signing/apksig"

        # Correct values generated with openssl:
        certfp = {
            "dsa-1024.x509.pem":
            "fee7c19ff9bfb4197b3727b9fd92d95406b1bd96db99ea642f5faac019a389d7",
            "dsa-2048.x509.pem":
            "97cce0bab292c2d5afb9de90e1810b41a5d25c006a10d10982896aa12ab35a9e",
            "dsa-3072.x509.pem":
            "966a4537058d24098ea213f12d4b24e37ff5a1d8f68deb8a753374881f23e474",
            "ec-p256.x509.pem":
            "6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599",
            "ec-p384.x509.pem":
            "5e7777ada7ee7ce8f9c4d1b07094876e5604617b7988b4c5d5b764a23431afbe",
            "ec-p521.x509.pem":
            "69b50381d98bebcd27df6d7df8af8c8b38d0e51e9168a95ab992d1a9da6082da",
            "rsa-1024.x509.pem":
            "bc5e64eab1c4b5137c0fbc5ed05850b3a148d1c41775cffa4d96eea90bdd0eb8",
            "rsa-16384.x509.pem":
            "f3c6b37909f6df310652fbd7c55ec27d3079dcf695dc6e75e22ba7c4e1c95601",
            "rsa-2048.x509.pem":
            "fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8",
            "rsa-3072.x509.pem":
            "483934461229a780010bc07cd6eeb0b67025fc4fe255757abbf5c3f2ed249e89",
            "rsa-4096.x509.pem":
            "6a46158f87753395a807edcc7640ac99c9125f6b6e025bdbf461ff281e64e685",
            "rsa-8192.x509.pem":
            "060d0a24fea9b60d857225873f78838e081795f7ef2d1ea401262bbd75a58234",
        }

        will_not_validate_correctly = [
            "targetSandboxVersion-2.apk",
            "targetSandboxVersion-2.apk",
            "v1-only-with-cr-in-entry-name.apk",
            "v1-only-with-lf-in-entry-name.apk",
            "v1-only-with-nul-in-entry-name.apk",
            "v1-only-with-rsa-1024-cert-not-der2.apk",
            "v2-only-cert-and-public-key-mismatch.apk",
            "v2-only-with-dsa-sha256-1024-sig-does-not-verify.apk",
        ]

        # Collect possible hashes for certificates
        # Unfortunately, not all certificates are supplied...
        for apath in os.listdir(root):
            if apath in certfp:
                with open(os.path.join(root, apath), "rb") as fp:
                    cert = x509.Certificate.load(pem.unarmor(fp.read())[2])
                    h = cert.sha256_fingerprint.replace(" ", "").lower()
                    self.assertEqual(h, certfp[apath])
                    self.assertIn(h, certfp.values())

        for apath in os.listdir(root):
            if apath.endswith(".apk"):
                if apath == "v2-only-garbage-between-cd-and-eocd.apk" or \
                   apath == "v2-only-truncated-cd.apk":
                    # Can not load as APK
                    if sys.version_info.major == 2:
                        # Different name in python2...
                        with self.assertRaises(zipfile.BadZipfile):
                            APK(os.path.join(root, apath))
                    else:
                        with self.assertRaises(zipfile.BadZipFile):
                            APK(os.path.join(root, apath))
                    continue
                elif apath in will_not_validate_correctly:
                    # These APKs are faulty (by design) and will return a not correct fingerprint.
                    # TODO: we need to check if we can prevent such errors...
                    continue

                a = APK(os.path.join(root, apath))

                self.assertIsInstance(a, APK)

                # Special error cases
                if apath == "v2-only-apk-sig-block-size-mismatch.apk":
                    with self.assertRaises(AssertionError):
                        a.is_signed_v2()
                    continue
                elif apath == "v2-only-empty.apk":
                    with self.assertRaises(AssertionError):
                        a.is_signed_v2()
                    continue

                if a.is_signed_v1():
                    if apath == "weird-compression-method.apk":
                        with self.assertRaises(NotImplementedError):
                            for c in a.get_signature_names():
                                a.get_certificate(c)

                    elif apath == "v1-only-with-rsa-1024-cert-not-der.apk":
                        for sig in a.get_signature_names():
                            c = a.get_certificate(sig)
                            h = c.sha256_fingerprint.replace(" ", "").lower()
                            self.assertNotIn(h, certfp.values())
                            # print([apath, h]) # I do not know, why put this file?
                            der = a.get_certificate_der(sig)
                            apk.show_Certificate(c, True)
                            apk.show_Certificate(c, False)
                            self.assertEqual(
                                hashlib.sha256(der).hexdigest(), h)
                        pass
                    else:
                        for sig in a.get_signature_names():
                            c = a.get_certificate(sig)
                            h = c.sha256_fingerprint.replace(" ", "").lower()
                            self.assertIn(h, certfp.values())

                            # Check that we get the same signature if we take the DER
                            der = a.get_certificate_der(sig)
                            self.assertEqual(
                                hashlib.sha256(der).hexdigest(), h)

                if a.is_signed_v2():
                    if apath == "weird-compression-method.apk":
                        with self.assertRaises(NotImplementedError):
                            a.get_certificates_der_v2()
                    elif apath == "v2-only-with-rsa-pkcs1-sha256-1024-cert-not-der.apk":
                        # FIXME
                        # Not sure what this one should do... but the certificate fingerprint is weird
                        # as the hash over the DER is not the same when using the certificate
                        continue
                    else:
                        for c in a.get_certificates_der_v2():
                            cert = x509.Certificate.load(c)
                            h = cert.sha256_fingerprint.replace(" ",
                                                                "").lower()
                            self.assertIn(h, certfp.values())
                            # Check that we get the same signature if we take the DER
                            self.assertEqual(hashlib.sha256(c).hexdigest(), h)
예제 #17
0
def analyzeAPK(filename, raw=False, decompiler=None):

    a = APK(filename, raw)
    return a
예제 #18
0
 def testAPKActivitiesAreString(self):
     from androguard.core.bytecodes.apk import APK
     a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True)
     activities = a.get_activities()
     self.assertTrue(isinstance(activities[0], str),
                     'activities[0] is not of type str')
예제 #19
0
 def __init__(self, app_path):
     self.app_path = app_path
     from androguard.core.bytecodes.apk import APK
     self.a = APK(app_path)
     self.d = None
     self.dx = None
예제 #20
0
    def testEffectiveTargetSdkVersion(self):
        from androguard.core.bytecodes.apk import APK

        a = APK('examples/android/abcore/app-prod-debug.apk')
        self.assertEqual(27, a.get_effective_target_sdk_version())

        a = APK('examples/android/Invalid/Invalid.apk')
        self.assertEqual(15, a.get_effective_target_sdk_version())

        a = APK('examples/android/TC/bin/TC-debug.apk')
        self.assertEqual(1, a.get_effective_target_sdk_version())

        a = APK('examples/android/TCDiff/bin/TCDiff-debug.apk')
        self.assertEqual(1, a.get_effective_target_sdk_version())

        a = APK('examples/android/TestsAndroguard/bin/TestActivity.apk')
        self.assertEqual(16, a.get_effective_target_sdk_version())

        a = APK(
            'examples/android/TestsAndroguard/bin/TestActivity_unsigned.apk')
        self.assertEqual(16, a.get_effective_target_sdk_version())

        a = APK('examples/dalvik/test/bin/Test-debug.apk')
        self.assertEqual(1, a.get_effective_target_sdk_version())

        a = APK('examples/dalvik/test/bin/Test-debug-unaligned.apk')
        self.assertEqual(1, a.get_effective_target_sdk_version())

        a = APK('examples/tests/a2dp.Vol_137.apk')
        self.assertEqual(25, a.get_effective_target_sdk_version())

        a = APK('examples/tests/hello-world.apk')
        self.assertEqual(25, a.get_effective_target_sdk_version())

        a = APK('examples/tests/duplicate.permisssions_9999999.apk')
        self.assertEqual(27, a.get_effective_target_sdk_version())

        a = APK('examples/tests/com.politedroid_4.apk')
        self.assertEqual(3, a.get_effective_target_sdk_version())
예제 #21
0
from androguard.core.bytecodes.apk import APK
from androguard.core.bytecodes.dvm import DalvikVMFormat
from androguard.core.analysis.analysis import Analysis
from androguard.decompiler.decompiler import DecompilerJADX
from androguard.core.androconf import show_logging
import logging

# Enable log output
show_logging(level=logging.DEBUG)

# Load our example APK
a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk")

# Create DalvikVMFormat Object
d = DalvikVMFormat(a)
# Create Analysis Object
dx = Analysis(d)

# Load the decompiler
# Set the path to the jadx executable!
decompiler = DecompilerJADX(d, dx, jadx="/home/vagrant/jadx/build/jadx/bin/jadx")

# propagate decompiler and analysis back to DalvikVMFormat
d.set_decompiler(decompiler)
d.set_vmanalysis(dx)

# Now you can do stuff like:
for m in d.get_methods()[:10]:
    print(m)
    print(decompiler.get_source_method(m))
예제 #22
0
    def testUsesImpliedPermissions(self):
        from androguard.core.bytecodes.apk import APK

        a = APK('examples/android/abcore/app-prod-debug.apk')
        self.assertEqual([
            ['android.permission.READ_EXTERNAL_STORAGE', None],
        ], a.get_uses_implied_permission_list())
        a = APK('examples/android/Invalid/Invalid.apk')
        self.assertEqual([], a.get_uses_implied_permission_list())
        a = APK('examples/android/TC/bin/TC-debug.apk')
        self.assertEqual([
            ['android.permission.WRITE_EXTERNAL_STORAGE', None],
            ['android.permission.READ_PHONE_STATE', None],
            ['android.permission.READ_EXTERNAL_STORAGE', None],
        ], a.get_uses_implied_permission_list())
        a = APK('examples/android/TCDiff/bin/TCDiff-debug.apk')
        self.assertEqual([
            ['android.permission.WRITE_EXTERNAL_STORAGE', None],
            ['android.permission.READ_PHONE_STATE', None],
            ['android.permission.READ_EXTERNAL_STORAGE', None],
        ], a.get_uses_implied_permission_list())
        a = APK('examples/android/TestsAndroguard/bin/TestActivity.apk')
        self.assertEqual([], a.get_uses_implied_permission_list())
        a = APK(
            'examples/android/TestsAndroguard/bin/TestActivity_unsigned.apk')
        self.assertEqual([], a.get_uses_implied_permission_list())
        a = APK('examples/dalvik/test/bin/Test-debug.apk')
        self.assertEqual([
            ['android.permission.WRITE_EXTERNAL_STORAGE', None],
            ['android.permission.READ_PHONE_STATE', None],
            ['android.permission.READ_EXTERNAL_STORAGE', None],
        ], a.get_uses_implied_permission_list())
        a = APK('examples/dalvik/test/bin/Test-debug-unaligned.apk')
        self.assertEqual([
            ['android.permission.WRITE_EXTERNAL_STORAGE', None],
            ['android.permission.READ_PHONE_STATE', None],
            ['android.permission.READ_EXTERNAL_STORAGE', None],
        ], a.get_uses_implied_permission_list())
        a = APK('examples/tests/a2dp.Vol_137.apk')
        self.assertEqual([
            ['android.permission.READ_EXTERNAL_STORAGE', None],
        ], a.get_uses_implied_permission_list())
        a = APK('examples/tests/com.politedroid_4.apk')
        self.assertEqual([
            ['android.permission.WRITE_EXTERNAL_STORAGE', None],
            ['android.permission.READ_PHONE_STATE', None],
            ['android.permission.READ_EXTERNAL_STORAGE', None],
        ], a.get_uses_implied_permission_list())
        a = APK('examples/tests/duplicate.permisssions_9999999.apk')
        self.assertEqual([
            ['android.permission.READ_EXTERNAL_STORAGE', 18],
        ], a.get_uses_implied_permission_list())
        a = APK('examples/tests/hello-world.apk')
        self.assertEqual([], a.get_uses_implied_permission_list())
        a = APK('examples/tests/urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234.apk')
        self.assertEqual([], a.get_uses_implied_permission_list())
예제 #23
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()
예제 #24
0
def get_dex(apk_path):
    """
    Extract the package name of an APK
    """
    a = APK(apk_path)
    return a.get_dex()
예제 #25
0
 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 extract_features(file_path):
    result = {}
    try:
        a = APK(file_path)
        d = DalvikVMFormat(a.get_dex())
        dx = Analysis(d)
        vm = dvm.DalvikVMFormat(a.get_dex())
        #vmx = analysis.uVMAnalysis(vm)
        d.set_vmanalysis(dx)
        d.set_decompiler(DecompilerDAD(d, dx))
    except:
        return None

    result['android_version_code'] = a.get_androidversion_code()
    result['android_version_name'] = a.get_androidversion_name()
    result['max_sdk'] = a.get_max_sdk_version()
    result['min_sdk'] = a.get_min_sdk_version()
    #result['libraries'] = a.get_libraries()
    result['filename'] = a.get_filename()
    result['target_sdk'] = a.get_target_sdk_version()
    result['md5'] = hashlib.md5(a.get_raw()).hexdigest()
    result['sha256'] = hashlib.sha256(a.get_raw()).hexdigest()
    result['permissions'] = a.get_permissions()
    result['activities'] = a.get_activities()
    result['providers'] = a.get_providers()
    result['services'] = a.get_services()
    result['strings'] = d.get_strings()
    result['class_names'] = [c.get_name() for c in d.get_classes()]
    result['method_names'] = [m.get_name() for m in d.get_methods()]
    result['field_names'] = [f.get_name() for f in d.get_fields()]
    #result['is_native_code'] = 1 if analysis.is_native_code(dx) else 0
    result['is_obfuscation'] = 1 if analysis.is_ascii_obfuscation(d) else 0
    #result['is_crypto_code'] = 1 if analysis.is_crypto_code(dx) else 0
    '''result['is_dyn_code'] = 1 if analysis.is_dyn_code(dx) else 0
    result['is_reflection_code'] = 1 if analysis.is_reflection_code(vmx) else 0'''
    result['is_database'] = 1 if d.get_regex_strings(DB_REGEX) else 0
    arr = []
    s = a.get_elements("action", "name")
    for i in s:
        arr.append(i)

    result['intents'] = arr

    s_list = []
    s_list.extend(result['class_names'])
    s_list.extend(result['method_names'])
    s_list.extend(result['field_names'])
    result['entropy_rate'] = entropy_rate(s_list)

    result['feature_vectors'] = {}

    # Search for the presence of api calls in a given apk
    result['feature_vectors']['api_calls'] = []
    for call in API_CALLS:
        status = 1 if dx.get_method(call) else 0
        result['feature_vectors']['api_calls'].append(status)

    # Search for the presence of permissions in a given apk
    result['feature_vectors']['permissions'] = []
    for permission in PERMISSIONS:
        status = 1 if permission in result['permissions'] else 0
        result['feature_vectors']['permissions'].append(status)

    #Search for the presence of intents in a given apk
    result['feature_vectors']['intents'] = []
    n = len(INTENTS)
    m = len(result['intents'])
    for i in range(n):
        stri = INTENTS[i]
        flg = False
        for j in range(m):
            if stri in result['intents'][j]:
                flg = True
                break
        if flg:
            status = 1
        else:
            status = 0
        result['feature_vectors']['intents'].append(status)

    #Check for special strings in code
    result['feature_vectors']['special_strings'] = []
    for word in SPECIAL_STRINGS:
        status = 1 if d.get_regex_strings(word) else 0
        result['feature_vectors']['special_strings'].append(status)

    return result
def get_permissions(path):
    application = APK(path)
    permissions = application.get_permissions()
    permissions = list(set(permissions))
    return permissions
예제 #28
0
 def __init__(self, apk, pos):
     self.data = []
     self.don = []
     self.apk = APK(str(apk))
     self.pos = pos
     self.main()
    def testApksignAPKs(self):
        # These APKs are from the apksign testcases and cover
        # all different signature algorithms as well as some error cases
        from androguard.core.bytecodes.apk import APK
        import zipfile
        from asn1crypto import x509, pem
        import binascii
        root = "examples/signing/apksig"
        
        # Correct values generated with openssl:
        # In the apksig repo:src/test/resources/com/android/apksig
        # for f in *.pem; do openssl x509 -in $f -noout -sha256 -fingerprint; done
        certfp = {
            'dsa-1024.x509.pem': 'fee7c19ff9bfb4197b3727b9fd92d95406b1bd96db99ea642f5faac019a389d7',
            'dsa-2048.x509.pem': '97cce0bab292c2d5afb9de90e1810b41a5d25c006a10d10982896aa12ab35a9e',
            'dsa-3072.x509.pem': '966a4537058d24098ea213f12d4b24e37ff5a1d8f68deb8a753374881f23e474',
            'ec-p256.x509.pem': '6a8b96e278e58f62cfe3584022cec1d0527fcb85a9e5d2e1694eb0405be5b599',
            'ec-p384.x509.pem': '5e7777ada7ee7ce8f9c4d1b07094876e5604617b7988b4c5d5b764a23431afbe',
            'ec-p521.x509.pem': '69b50381d98bebcd27df6d7df8af8c8b38d0e51e9168a95ab992d1a9da6082da',
            'rsa-1024_2.x509.pem': 'eba3685e799f59804684abebf0363e14ccb1c213e2b954a22669714ed97f61e9',
            'rsa-1024.x509.pem': 'bc5e64eab1c4b5137c0fbc5ed05850b3a148d1c41775cffa4d96eea90bdd0eb8',
            'rsa-16384.x509.pem': 'f3c6b37909f6df310652fbd7c55ec27d3079dcf695dc6e75e22ba7c4e1c95601',
            'rsa-2048_2.x509.pem': '681b0e56a796350c08647352a4db800cc44b2adc8f4c72fa350bd05d4d50264d',
            'rsa-2048_3.x509.pem': 'bb77a72efc60e66501ab75953af735874f82cfe52a70d035186a01b3482180f3',
            'rsa-2048.x509.pem': 'fb5dbd3c669af9fc236c6991e6387b7f11ff0590997f22d0f5c74ff40e04fca8',
            'rsa-3072.x509.pem': '483934461229a780010bc07cd6eeb0b67025fc4fe255757abbf5c3f2ed249e89',
            'rsa-4096.x509.pem': '6a46158f87753395a807edcc7640ac99c9125f6b6e025bdbf461ff281e64e685',
            'rsa-8192.x509.pem': '060d0a24fea9b60d857225873f78838e081795f7ef2d1ea401262bbd75a58234',
        }

        will_not_validate_correctly = [
            "targetSandboxVersion-2.apk",
            "targetSandboxVersion-2.apk",
            "v1-only-with-cr-in-entry-name.apk",
            "v1-only-with-lf-in-entry-name.apk",
            "v1-only-with-nul-in-entry-name.apk",
            "v1-only-with-rsa-1024-cert-not-der2.apk",
            "v2-only-cert-and-public-key-mismatch.apk",
            "v2-only-with-dsa-sha256-1024-sig-does-not-verify.apk",
            "debuggable-boolean.apk",
            "debuggable-resource.apk",
        ]

        # Collect possible hashes for certificates
        # Unfortunately, not all certificates are supplied...
        for apath in os.listdir(root):
            if apath in certfp:
                with open(os.path.join(root, apath), "rb") as fp:
                    cert = x509.Certificate.load(pem.unarmor(fp.read())[2])
                    h = cert.sha256_fingerprint.replace(" ","").lower()
                    self.assertEqual(h, certfp[apath])
                    self.assertIn(h, certfp.values())

        for apath in os.listdir(root):
            if apath.endswith(".apk"):
                if apath == "v2-only-garbage-between-cd-and-eocd.apk" or \
                   apath == "v2-only-truncated-cd.apk" or \
                   apath == "v1v2v3-with-rsa-2048-lineage-3-signers-invalid-zip.apk":
                    # Can not load as APK
                    with self.assertRaises(zipfile.BadZipFile):
                        APK(os.path.join(root, apath))
                    continue
                elif apath in will_not_validate_correctly:
                    # These APKs are faulty (by design) and will return a not correct fingerprint.
                    # TODO: we need to check if we can prevent such errors...
                    continue

                a = APK(os.path.join(root, apath))

                self.assertIsInstance(a, APK)

                # Test if the correct method returns True, while others return
                # False
                m_tests = {'1': a.is_signed_v1,
                           '2': a.is_signed_v2,
                           '3': a.is_signed_v3}

                # These APKs will raise an error
                excluded = [
                            "v1v2v3-with-rsa-2048-lineage-3-signers-no-sig-block.apk",
                            "v2-only-apk-sig-block-size-mismatch.apk",
                            "v2-only-empty.apk",
                            "v2-only-wrong-apk-sig-block-magic.apk",
                            "v2-stripped.apk",
                            "v2-stripped-with-ignorable-signing-schemes.apk",
                            "v2v3-signed-v3-block-stripped.apk",
                            "v3-only-empty.apk",
                            "v3-only-with-ecdsa-sha512-p384-wrong-apk-sig-block-magic.apk",
                            "v3-only-with-rsa-pkcs1-sha512-4096-apk-sig-block-size-mismatch.apk",
                            "v3-stripped.apk",
                           ]
                if apath[0] == "v" and apath not in excluded:
                    methods = apath.split("-", 1)[0].split("v")[1:]
                    for m, f in m_tests.items():
                        if m in methods:
                            self.assertTrue(f())
                        else:
                            self.assertFalse(f())

                # Special error cases
                if apath == "v2-only-apk-sig-block-size-mismatch.apk":
                    with self.assertRaises(apk.BrokenAPKError):
                        a.is_signed_v2()
                    continue
                elif apath == "v2-only-empty.apk":
                    with self.assertRaises(apk.BrokenAPKError):
                        a.is_signed_v2()
                    continue
                elif apath == "v3-only-with-rsa-pkcs1-sha512-4096-apk-sig-block-size-mismatch.apk":
                    with self.assertRaises(apk.BrokenAPKError):
                        a.is_signed_v3()
                    continue

                if a.is_signed_v1():
                    if apath == "weird-compression-method.apk":
                        with self.assertRaises(NotImplementedError):
                            for c in a.get_signature_names():
                                a.get_certificate(c)

                    elif apath == "v1-only-with-rsa-1024-cert-not-der.apk":
                        for sig in a.get_signature_names():
                            c = a.get_certificate(sig)
                            h = c.sha256_fingerprint.replace(" ","").lower()
                            self.assertNotIn(h, certfp.values())
                            # print([apath, h]) # I do not know, why put this file?
                            der = a.get_certificate_der(sig)
                            apk.show_Certificate(c, True)
                            apk.show_Certificate(c, False)
                            self.assertEqual(hashlib.sha256(der).hexdigest(), h)
                        pass
                    else:
                        for sig in a.get_signature_names():
                            c = a.get_certificate(sig)
                            h = c.sha256_fingerprint.replace(" ","").lower()
                            self.assertIn(h, certfp.values())

                            # Check that we get the same signature if we take the DER
                            der = a.get_certificate_der(sig)
                            self.assertEqual(hashlib.sha256(der).hexdigest(), h)

                if a.is_signed_v2():
                    if apath == "weird-compression-method.apk":
                        with self.assertRaises(NotImplementedError):
                            a.get_certificates_der_v2()
                    elif apath == "v2-only-with-rsa-pkcs1-sha256-1024-cert-not-der.apk":
                        # FIXME
                        # Not sure what this one should do... but the certificate fingerprint is weird
                        # as the hash over the DER is not the same when using the certificate
                        continue
                    else:
                        for c in a.get_certificates_der_v2():
                            cert = x509.Certificate.load(c)
                            h = cert.sha256_fingerprint.replace(" ","").lower()
                            self.assertIn(h, certfp.values())
                            # Check that we get the same signature if we take the DER
                            self.assertEqual(hashlib.sha256(c).hexdigest(), h)

                if a.is_signed_v3():
                    print(apath)
                    if apath == "weird-compression-method.apk":
                        with self.assertRaises(NotImplementedError):
                            a.get_certificates_der_v3()
                    elif apath == "v3-only-with-rsa-pkcs1-sha256-3072-sig-does-not-verify.apk" or \
                         apath == "v3-only-cert-and-public-key-mismatch.apk":
                        cert = x509.Certificate.load(a.get_certificates_der_v3()[0])
                        h = cert.sha256_fingerprint.replace(" ","").lower()
                        self.assertNotIn(h, certfp.values())
                    else:
                        for c in a.get_certificates_der_v3():
                            cert = x509.Certificate.load(c)
                            h = cert.sha256_fingerprint.replace(" ","").lower()
                            self.assertIn(h, certfp.values())
                            # Check that we get the same signature if we take the DER
                            self.assertEqual(hashlib.sha256(c).hexdigest(), h)
예제 #30
0
def getFeatures(source_directory):
    ############################################################
    # Label tong hop
    with open(LabelsNum_file, "r+") as file_LabeslNum:
        LABELSNUMANDTEXT = json.load(file_LabeslNum)

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

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

    source_directory = str(source_directory)

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

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

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

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

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

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

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

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

    for analyze_apk in tqdm(apk_list):

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

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

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

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

        pre_static_dict = collections.OrderedDict()

        pre_static_dict['Filename'] = apk_filename

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

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

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

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

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

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

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

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

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

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

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

        # API packages

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

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

        static_analysis_dict['API packages'] = API_packages_dict

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

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

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

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

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

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

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

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

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

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

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

    fp.close()

    csvFile.close()