Exemple #1
0
    def process_apk(self, data, name):
        """
        Processes Android application
        :param data:
        :param name:
        :return:
        """
        from cryptography.x509.base import load_pem_x509_certificate
        from apk_parse.apk import APK
        try:
            apkf = APK(data, process_now=False, process_file_types=False, raw=True,
                       temp_dir=self.args.tmp_dir)
            apkf.process()
            self.num_apk += 1

            pem = apkf.cert_pem
            aux = {'subtype': 'apk'}

            x509 = load_pem_x509_certificate(pem, self.get_backend())

            self.process_x509(x509, name=name, idx=0, data=data, pem=True, source='apk-pem-cert', aux=aux)

        except Exception as e:
            logger.debug('Exception in processing JSON %s : %s' % (name, e))
            self.trace_logger.log(e)
Exemple #2
0
    def __init__(self, project_dir, apk_dir, config_location):
        self.project_dir = project_dir

        self.apk_dir = apk_dir
        self.apkf = APK(apk_dir)

        self.manifestDict = extractXML(apk_dir, config_location)
        self.gradleDict = gr.GradleParserNew(self.project_dir +
                                             "/app").parse(False)
Exemple #3
0
def get_feature(apk_path):
    try:
        apkf = APK(apk_path)
        x_feature = ""
        x_feature = x_feature + str(apkf.file_size) + sep
        x_feature = x_feature + str(apkf.get_max_sdk_version()) + sep
        x_feature = x_feature + str(apkf.get_min_sdk_version()) + sep
        x_feature = x_feature + str(apkf.get_target_sdk_version()) + sep
        x_feature = x_feature + str(apkf.androidversion) + sep
        x_feature = x_feature + str(apkf.get_activities()) + sep
        x_feature = x_feature + str(apkf.get_services()) + sep
        x_feature = x_feature + str(apkf.get_receivers()) + sep
        x_feature = x_feature + str(apkf.get_providers()) + sep
        x_feature = x_feature + str(apkf.get_permissions()) + "\n"
        f.write(x_feature)
    except:
        pass
Exemple #4
0
def test():
    if len(sys.argv) == 1:
        print('Usage: %s app.apk' % sys.argv[0])
        sys.exit(1)

    apk_path = sys.argv[1]

    # Parsing xapks.
    apkf = APK(apk_path,
               process_now=False,
               process_file_types=False,
               as_file_name=True)
    apkf.file_md5 = 'skip'
    apkf.process()

    print(apkf.file_md5)
    print(apkf.file_size)
    print(apkf.cert_md5)
    print(apkf.cert_text)
    print(apkf.cert_pem)
    def __init__(self,
                 filename,
                 raw=False,
                 mode="r",
                 magic_file=None,
                 zipmodule=ZIPMODULE):
        APK.__init__(self, filename, raw, mode, magic_file, zipmodule)

        if self.package == "":
            logger.warn(
                "Couldn't extract package name and version from APK. Using heuristic"
            )
            file_name = os.path.splitext(os.path.basename(self.filename))[0]
            data = file_name.split('_')

            if len(data) == 2:
                package_name = data[0]
                version = data[1].replace('v', '').replace('_', '.')
                self.package = package_name
                self.androidversion["Name"] = version
                logger.warn("Heuristic identified: %s", self)
    def isMalware(self, url):
        # Preprocess to remove query information to get absolute url link
        o = urlparse(url)
        apk_url = o.scheme + "://" + o.netloc + o.path

        # Check whether it is valid APK
        path = urlparse(apk_url).path
        if os.path.splitext(path)[1] != '.apk':
            return EXIT_CODES.index('NotValid')

        # business logic here
        #download apk file and parse it
        download_apk = APK_Download(apk_url)
        if download_apk is None:
            return EXIT_CODES.index('NotValid')
        apk_file = APK(download_apk)

        try:
            if checkUrlRecord(apk_url) is True:
                return EXIT_CODES.index('isMalware')

            if checkNameandSizeRecord(apk_file.filename,
                                      apk_file.file_size) is True:
                insertAPK(apk_file.file_md5, apk_file.filename,
                          apk_file.file_size, apk_url)
                return EXIT_CODES.index('isMalware')

            if checkMD5Record(apk_file.file_md5) is True:
                insertAPK(apk_file.file_md5, apk_file.filename,
                          apk_file.file_size, apk_url)
                return EXIT_CODES.index('isMalware')
        except Exception as e:
            return EXIT_CODES.index('DB_no_connection')
        '''
        Virus Total Check
        '''
        vt_instance = VirusTotalPublicApi(API_KEY)
        self.__throttle_virustotal_api_call()

        #Submit file to Virus Total for scan
        scan_status = self.__virustotal_scan_submit(apk_file, vt_instance)
        if scan_status in EXIT_CODES:
            return scan_status

        scan_id = scan_status
        ret = self.__virustotal_scan_check(apk_file, vt_instance, scan_id)
        if ret is not None:
            if ret is EXIT_CODES.index('isMalware'):
                insertAPK(apk_file.file_md5, apk_file.filename,
                          apk_file.file_size, apk_url)
            return ret

        return EXIT_CODES.index('isClean')
Exemple #7
0
def main():
    # Parse command line arguments
    parser = argparse.ArgumentParser(
        description='Extracts Signing information from the APK')
    parser.add_argument('files',
                        nargs=argparse.ZERO_OR_MORE,
                        default=[],
                        help='APK files')
    parser.add_argument('--der',
                        dest='der',
                        default=False,
                        action='store_const',
                        const=True,
                        help='DER only')
    args = parser.parse_args()

    for file_name in args.files:
        apkf = APK(file_name)
        pem = apkf.cert_pem

        der = apkf.pkcs7_der
        if args.der:
            sys.stdout.write(der)
            return

        print(pem)
        print(apkf.cert_text)

        p7 = PKCS7.from_der(der)
        try:
            signed_date, valid_from, valid_to, signer = p7.get_timestamp_info()
            print('Sign date: %s = %s' % (utils.unix_time_millis(signed_date),
                                          utils.fmt_time(signed_date)))
            print('Sign not before: %s = %s' %
                  (utils.unix_time_millis(valid_from),
                   utils.fmt_time(valid_from)))
            print('Sign not after: %s = %s' %
                  (utils.unix_time_millis(valid_to), utils.fmt_time(valid_to)))
            print('Signer: %s' % str(signer))
        except Exception as e:
            logger.error('Error parsing signer info: %s' % e)

        if not isinstance(p7.content, PKCS7_SignedData):
            logger.info('Not a PKCS7 signed data')

        print('Signer info cnt: %s' % len(p7.content.signerInfos))
        if len(p7.content.signerInfos) > 0:
            signer_info = p7.content.signerInfos[0]
            print('Signer serial: %s' % signer_info.serial_number)
            print('Sign issuer: %s' % signer_info.issuer)
            print('Sign algorithm: %s' %
                  signer_info.oid2name(signer_info.digest_algorithm))
Exemple #8
0
def get_permission_info(PATH):
    filenames = os.listdir(PATH)
    get_permission = {}
    my_list = [0 for i in range(len(permission_v2))]
    for filename in filenames:
        # add permission list 11/12
        my_list = [0 for i in range(len(permission_v2))]
        
        full_path = PATH + "/" + filename
        apkf = APK(full_path)
        permission_list = []
        count = 0
        for i in apkf.get_permissions():
            permission_list.append(i.split(".")[-1])

        for i in permission_list:
            if i in permission_v2:
                my_list[permission_v2.index(i)]=1
                count += 1
        my_list.append(count)
        get_permission[filename[:-4]]= my_list
    return get_permission
Exemple #9
0
def main():
    # Parse command line arguments
    parser = argparse.ArgumentParser(
        description='Extracts RSA modulus as a hexa string from APK files')
    parser.add_argument('files',
                        nargs=argparse.ZERO_OR_MORE,
                        default=[],
                        help='APK files')
    args = parser.parse_args()

    for file_name in args.files:
        apkf = APK(file_name)
        pem = apkf.cert_pem

        x509 = load_x509(pem)
        pub = x509.public_key()
        n = pub.public_numbers().n
        print('%x' % n)
Exemple #10
0
def main():
    # Parse command line arguments
    parser = argparse.ArgumentParser(
        description='Extracts PEM certificates from APK files')
    parser.add_argument('files',
                        nargs=argparse.ZERO_OR_MORE,
                        default=[],
                        help='APK files')
    parser.add_argument('-t',
                        dest='text',
                        default=False,
                        action='store_const',
                        const=True,
                        help='show also text representation')
    args = parser.parse_args()

    for file_name in args.files:
        apkf = APK(file_name)
        if args.text:
            print(apkf.cert_text)

        pem = apkf.cert_pem
        print(pem)
Exemple #11
0
def extraction(apk_path, file):
    t = "<sep>"
    apkf = APK(apk_path)
    f = open("train.csv", 'a')
    f.write(file + t)
    f.write(str(apkf.cert_text) + t)
    f.write(str(apkf.file_md5) + t)
    f.write(str(apkf.cert_md5) + t)
    f.write(str(apkf.file_size) + t)
    f.write(str(apkf.androidversion) + t)
    f.write(str(apkf.package) + t)
    f.write(str(apkf.get_android_manifest_xml()) + t)
    f.write(str(apkf.get_android_manifest_axml()) + t)
    f.write(str(apkf.is_valid_APK()) + t)
    f.write(str(apkf.get_filename()) + t)
    f.write(str(apkf.get_package()) + t)
    f.write(str(apkf.get_androidversion_code()) + t)
    f.write(str(apkf.get_androidversion_name()) + t)
    f.write(str(apkf.get_max_sdk_version()) + t)
    f.write(str(apkf.get_min_sdk_version()) + t)
    f.write(str(apkf.get_target_sdk_version()) + t)
    f.write(str(apkf.get_libraries()) + t)
    f.write(str(apkf.get_files()) + t)
    f.write(str(apkf.get_files_types()) + t)
    f.write(str(apkf.get_main_activity()) + t)
    f.write(str(apkf.get_activities()) + t)
    f.write(str(apkf.get_services()) + t)
    f.write(str(apkf.get_receivers()) + t)
    f.write(str(apkf.get_providers()) + t)
    f.write(str(apkf.get_permissions()))
    f.write("<new>")
Exemple #12
0
 def apk_info(self):
     return APK(self.file)
Exemple #13
0
def test():
    if len(sys.argv) == 1:
        print('Usage: %s app.apk' % sys.argv[0])
        sys.exit(1)

    apk_path = sys.argv[1]
    apkf = APK(apk_path)
    print(apkf.cert_text)
    print(apkf.cert_pem)
    print(apkf.file_md5)
    print(apkf.cert_md5)
    print(apkf.file_size)
    print(apkf.androidversion)
    print(apkf.package)
    print(apkf.get_android_manifest_xml())
    print(apkf.get_android_manifest_axml())
    print(apkf.is_valid_APK())
    print(apkf.get_filename())
    print(apkf.get_package())
    print(apkf.get_androidversion_code())
    print(apkf.get_androidversion_name())
    print(apkf.get_max_sdk_version())
    print(apkf.get_min_sdk_version())
    print(apkf.get_target_sdk_version())
    print(apkf.get_libraries())
    print(apkf.get_files())
    # pip install python-magic
    print(apkf.get_files_types())
    # print(apkf.get_dex())
    print(apkf.get_main_activity())
    print(apkf.get_activities())
    print(apkf.get_services())
    print(apkf.get_receivers())
    print(apkf.get_providers())
    print(apkf.get_permissions())
    print(binascii.hexlify(apkf.get_signature()))
    print(apkf.get_signature_name())

    print apkf.show()
Exemple #14
0
class ChecklistBerker(object):
    is_apk_created = False
    apk_location = "/app/build/outputs/apk/app-external-release.apk"
    test_results = []

    def __init__(self, project_dir, apk_dir, config_location):
        self.project_dir = project_dir

        self.apk_dir = apk_dir
        self.apkf = APK(apk_dir)

        self.manifestDict = extractXML(apk_dir, config_location)
        self.gradleDict = gr.GradleParserNew(self.project_dir +
                                             "/app").parse(False)

    def execute_test_batch(self, config_location):
        config = ConfigParser.ConfigParser()
        config.read(config_location)

        resCongList = config.get('B1', 'resConfigs')
        self.test_results.append(self.b1(resCongList))
        self.test_results.append(self.b4())
        targetSdkVersion = config.get('B6', 'targetSdkVersion')
        self.test_results.append(self.b6(targetSdkVersion))
        self.test_results.append(self.b7())
        self.test_results.append(self.b9())

        self.test_results.append(self.man2())
        self.test_results.append(self.man5())
        self.test_results.append(self.sign1())
        self.test_results.append(self.sign3())
        self.test_results.append(self.perm2())

        self.test_results.append(self.prg1())
        minifyEnabled = config.get('PRG2', 'minifyEnabled')
        shrinkResources = config.get('PRG2', 'shrinkResources')
        self.test_results.append(self.prg2(shrinkResources, minifyEnabled))
        allowBackup = config.get('SEC1', 'allowBackup')
        self.test_results.append(self.sec1(allowBackup))
        return self.test_results

    def b1(self, configResConfig_list):
        testId = "B1"
        found = False
        resConf_filtered = configResConfig_list.split(",")
        resConf_filtered = [x.strip(" ") for x in resConf_filtered]

        if "resConfigs" in self.gradleDict['android']["defaultConfig"][0]:
            for i in self.gradleDict['android']["defaultConfig"][0][
                    "resConfigs"][0]:
                for conf in resConf_filtered:
                    if i.lower() == conf.lower():
                        found = True
                        break  # found in the config
                if not found:
                    result = "FAILED."
                    additional = " In your resConfigs, you have: " + i + " but not in config file."
                    return (testId, self.b1_descp(), (result, additional))
                else:
                    found = False

            for conf in resConf_filtered:
                for i in self.gradleDict['android']["defaultConfig"][0][
                        "resConfigs"][0]:
                    if i.lower() == conf.lower():
                        found = True
                        break  # found in the config
                if not found:
                    result = "FAILED."
                    additional = " In your config file, you have: " + conf + " but not in manifest."
                    return (testId, self.b1_descp(), (result, additional))
                else:
                    found = False
        else:
            result = "CONFIRM:"
            additional = " You dont have resConfigs in your project."
            return (testId, self.b1_descp(), (result, additional))

        result = "SUCCEED."
        additional = " Your resConfigs in config file match with the ones in the manifest."
        return (testId, self.b1_descp(), (result, additional))

    def b1_descp(self):
        return "Make sure to minimize res configs by only including necessary resources (localization etc.)"

    def b4(self):
        testId = "B4"
        appId = self.apkf.get_package()
        startingName = "com.monitise.mea."
        if appId.startswith(startingName):
            result = "SUCCEED."
            additional = "Your project name starts with \"com.monitise.mea\"."
        else:
            result = "FAILED."
            additional = "Your project name does not start with \"com.monitise.mea\" It starts with " + appId
        return (testId, self.b4_descp(), (result, additional))

    def b4_descp(self):
        return "Make sure that applicationId respects com.monitise.mea.<product> convention unless other indicated."

    def b6(self, configTargetSdk):
        testId = "B6"
        configTargetSdk
        targetSDK = self.apkf.get_target_sdk_version()
        if configTargetSdk == targetSDK:
            result = "SUCCEED."
            additional = "Your targetSdkVersion is: " + targetSDK + "."
        else:
            result = "FAILED."
            additional = "Your targetSdkVersion should be " + configTargetSdk + " but it is " + targetSDK + "."

        return (testId, self.b6_descp(), (result, additional))

    def b6_descp(self):
        return "Make sure that targetSdkVersion is set to most recent api version that app is tested against."

    def b7(self):
        testId = "B7 Test"
        for dep in self.gradleDict["dependencies"]["compile"]:
            if "com.google.android.gms:play-services:" in dep:
                result = "FAILED."
                additional = "Google Play Services API should be included as separate dependencies."
                return (testId, self.b7_descp(), (result, additional))
        result = "SUCCEED."
        additional = "Google Play Services API is not included with just one line. (or not included at all)"
        return (testId, self.b7_descp(), (result, additional))

    def b7_descp(self):
        return "Make sure that any Google Play Services API is included as separate dependencies."

    def b9(self):
        testId = "B9"
        if '@android:debuggable' in self.manifestDict['manifest'][
                'application']:
            deb = self.manifestDict['manifest']['application'][
                '@android:debuggable']
            deb = deb.lower()
            if deb == "true":
                result = "FAILED."
                additional = "debuggable should not be set to true."
                return (testId, self.b9_descp(), (result, additional))
        result = "SUCCEED."
        additional = "debuggable is not set to true."
        return (testId, self.b9_descp(), (result, additional))

    def b9_descp(self):
        return "Make sure that release build type in gradle build file doesn't have debuggable set to true."

    def man2(self):
        testId = "MAN2"

        if "@android:versionName" in self.manifestDict['manifest']:
            version = self.manifestDict['manifest']['@android:versionName']
            result = "CONFIRM:"
            additional = "Dismiss if you updated your version. android:versionName is set to: " + version + "."
        else:
            result = "FAILED."
            additional = "You need to update android:versionName."

        return (testId, self.man2_descp(), (result, additional))

    def man2_descp(self):
        return "Make sure that android:versionName attribute is updated."

    def man5(self):
        testId = "MAN5"

        if "@android:installLocation" in self.manifestDict['manifest']:
            location = self.manifestDict['manifest'][
                '@android:installLocation']
            if location == "externalOnly":
                result = "FAILED."
                additional = "You cannot set android:installLocation to externalOnly."
                return (testId, self.man5_descp(), (result, additional))
        result = "SUCCEED."
        additional = " android:installLocation is not set to externalOnly."
        return (testId, self.man5_descp(), (result, additional))

    def man5_descp(self):
        return "Make sure that android:installLocation attributes is not set to externalOnly."

    def perm2(self):
        testId = "PERM2"

        result = "CONFIRM:"
        additional = "Check if all the permissions are necessary:"
        counter = 0
        for i in self.apkf.get_permissions():
            additional = additional + "\n\t- " + self.apkf.get_permissions(
            )[counter]
            counter += 1
        return (testId, self.perm2_descp(), (result, additional))

    def perm2_descp(self):
        return "Make sure that app is NOT requesting any unnecessary permissions."

    def sec1(self, configAllowBackup):
        testId = "SEC1"
        configAllowBackup = configAllowBackup.lower()

        if "@android:allowBackup" in self.manifestDict['manifest'][
                'application']:
            backup = self.manifestDict['manifest']['application'][
                '@android:allowBackup']
            backup = backup.lower()
            configAllowBackup = configAllowBackup.lower()
            if backup == configAllowBackup:
                result = "SUCCEED."
                additional = "android:allowBackup is set to " + backup
            else:
                result = "FAILED."
                additional = "android:allowBackup is set to " + backup + ". But it must be " + configAllowBackup + "."
        elif configAllowBackup == "true":
            result = "FAILED."
            additional = "You need to specify android:allowBackup as true."
        else:
            result = "SUCCEED."
            additional = "Your android:allowBackup is set to false by default."
        return (testId, self.sec1_descp(), (result, additional))

    def sec1_descp(self):
        return "Make sure to set android:allowBackup to false unless otherwise indicated."

    def sign1(self):
        testId = "SIGN1"

        if not os.path.exists(self.project_dir + "/release.keystore.jks"):
            result = "FAILED."
            additional = " release.keystore.jks does not exist in your project path."
            return (testId, self.sign1_descp(), (result, additional))

    def sign1_descp(self):
        return "Make sure that a release keystore is created and used to sign any release configuration " \
               "(prod-release, internal-release, external-release etc.) of the app"

    def sign3(self):
        testId = "SIGN3"
        keyPath = ''

        try:
            keyPath = self.gradle['android']['signingConfigs'][0]['release'][
                0]['storeFile'][0][0]
        except:
            result = "FAILED."
            additional = "There is no given path for release keystore file"
            return (testId, self.sign3_descp(), (result, additional))

        if path.exists(keyPath):
            if "/build/" in keyPath:
                result = "FAILED"
                additional = " Your release keystore is in build classpath."
            else:
                result = "SUCCEED."
                additional = "Your release keystore is not in build classpath."

            return (testId, self.sign3_descp(), (result, additional))
        else:
            result = "FAILED."
            additional = " There is no release keystore in the project."
            return (testId, self.sign3_descp(), (result, additional))

    def sign3_descp(self):
        return "Make sure that the release keystore is NOT included in build classpath i.e. Apk should never expose this file"

    def prg1(self):
        testId = "PRG1"
        if 'monitise' in self.gradleDict:
            result = "SUCCEED."
            additional = "Your gradle has \"monitise\" block."
        else:
            result = "FAILED."
            additional = "Your gradle file does not have \"monitise\" block.  You forgot deleting logs."

        return (testId, self.prg1_descp(), (result, additional))

    def prg1_descp(self):
        return "Make sure that logging is disabled on release builds."

    def prg2(self, configMinifyEn, configShrinkRes):
        testId = "PRG2"
        configMinifyEn = configMinifyEn.lower()
        configShrinkRes = configShrinkRes.lower()

        if "minifyEnabled" in self.gradleDict['android']["buildTypes"][0]["release"][0] and \
                        "shrinkResources" in self.gradleDict['android']["buildTypes"][0]["release"][0]:

            minifyEnabled = self.gradleDict["android"]["buildTypes"][0][
                "release"][0]["minifyEnabled"][0]
            shrinkResources = self.gradleDict["android"]["buildTypes"][0][
                "release"][0]["shrinkResources"][0]
            minifyEnabled = minifyEnabled[0].lower()
            shrinkResources = shrinkResources[0].lower()
            if minifyEnabled == configMinifyEn and shrinkResources == configShrinkRes:
                result = "SUCCEED."
                additional = "minifyEnabled and shrinkResources are set to true."
                return (testId, self.prg2_descp(), (result, additional))

        result = "FAILED."
        additional = "minifyEnabled and shrinkResources must be true."
        return (testId, self.prg2_descp(), (result, additional))

    def prg2_descp(self):
        return "Make sure that minifyEnabled and shrinkResoureces are set to true for release build type"
Exemple #15
0
def main():
    path = sys.argv[1]
    malicious = sys.argv[2]
    result = {}
    if not os.path.exists(path):
        return False, "File is not exists"
    apk = APK(path)
    if not apk.is_valid_APK():
        return False, "APK file is wrong"
    result = {}
    ### APK File Info
    result['Apk'] = {}
    result['Apk']['path'] = path
    result['Apk']['malicious'] = malicious
    result['Apk']['md5'] = apk.file_md5
    result['Apk']['sha256'] = apk.file_sha256
    result['Apk']['size'] = apk.file_size
    result['Apk']['magic'] = magic.Magic().from_file(path)
    result['Apk']['icon_files'] = apk.get_icon_files()

    ### Certificate Information
    result['Certificate'] = {}
    result['Certificate']['md5'] = apk.cert_md5
    result['Certificate']['text'] = apk.cert_text

    ### AndroidManifiest.xml Information
    result['AndroidManifest'] = {}
    result['AndroidManifest'][
        'androidversion_code'] = apk.get_androidversion_code()
    result['AndroidManifest'][
        'androidversion_name'] = apk.get_androidversion_name()
    result['AndroidManifest']['min_sdk_version'] = apk.get_min_sdk_version()
    result['AndroidManifest'][
        'target_sdk_version'] = apk.get_target_sdk_version()
    result['AndroidManifest']['libraries'] = apk.get_libraries()
    result['AndroidManifest']['main_activitiy'] = apk.get_main_activity()
    result['AndroidManifest']['activities'] = {}
    for activity in apk.get_activities():
        result['AndroidManifest']['activities'][
            activity] = apk.get_intent_filters('activity', activity)
    result['AndroidManifest']['services'] = {}
    for service in apk.get_services():
        result['AndroidManifest']['services'][
            service] = apk.get_intent_filters('service', service)
    result['AndroidManifest']['receivers'] = {}
    for receiver in apk.get_receivers():
        result['AndroidManifest']['receivers'][
            receiver] = apk.get_intent_filters('receiver', receiver)
    result['AndroidManifest']['permissions'] = {}
    for permission in apk.get_permissions():
        result['AndroidManifest']['permissions'][
            permission] = apk.get_intent_filters('permission', permission)
    result['AndroidManifest']['providers'] = apk.get_providers()

    ### APK File Information and File Magic Data
    result['Files'] = {}
    image_extension_list = ['png', 'jpeg', 'jpg', 'gif']
    image_magic_list = ['PNG image data', 'JPEG image data']
    for file in apk.get_files():
        result['Files'][file] = {}
        fileData = apk.get_file(filename=file)
        result['Files'][file]['icon'] = False
        result['Files'][file]['size'] = len(fileData)
        result['Files'][file]['md5'] = hashlib.md5(fileData).hexdigest()
        result['Files'][file]['sha256'] = hashlib.sha256(fileData).hexdigest()
        result['Files'][file]['magic'] = magic.Magic().from_buffer(fileData)
        result['Files'][file]['file_name'] = None
        result['Files'][file]['file_extension'] = None
        result['Files'][file]['image_resource'] = False
        if '/' in file:
            result['Files'][file]['file_name'] = file.split('/')[-1]
        else:
            result['Files'][file]['file_name'] = file

        if '.' in result['Files'][file]['file_name']:
            result['Files'][file]['file_extension'] = result['Files'][file][
                'file_name'].split('.')[-1].lower()
        if file in apk.get_icon_files():
            result['Files'][file]['icon'] = True
        if result['Files'][file]['file_extension'] in image_extension_list:
            result['Files'][file]['image_resource'] = get_image_resource(
                file_magic=result['Files'][file]['magic'],
                image_magic_list=image_magic_list)
        if get_image_resource(
                file_magic=result['Files'][file]['magic'],
                image_magic_list=image_magic_list) and result['Files'][file][
                    'file_extension'] not in image_extension_list:
            continue
            #print "[+] This file is strange %s %s" % (file, result['Files'][file]['magic'])
            fd = open('./temp/' + file.replace('/', '_'), 'wb')
            fd.write(apk.get_file(file))
            fd.close()

    ### decompile
    proc = subprocess.Popen(['java', '-jar', 'apktool_2.3.0.jar', 'd', path],
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    out, err = proc.communicate()
    if '/' in path:
        path = path.split('/')[-1]
    result['Class'] = {}
    for root, dirs, files in os.walk('./' + path + '.out' + os.sep + 'smali'):
        for file in files:
            filepath = root + os.sep + file
            className = filepath.split('/smali/')[-1].split(
                '.smali')[0].replace('/', '.')
            result['Class'][className] = {}
            result['Class'][className]['Method'] = {}
            result['Class'][className]['interfaces'] = []
            result['Class'][className]['Fields'] = []
            fd = open(filepath, 'rb')
            data = fd.read()
            fd.close()
            index = 0
            for line in data.split('\n'):
                if not line:
                    continue
                line = line.strip()
                if line.startswith('.super '):
                    result['Class'][className]['super_class'] = line[
                        8:-1].replace('/', '.')
                    #print result['Class'][className]['super_class']
                elif line.startswith('.method '):
                    ### Method Info
                    try:
                        methodName, parameters, returnType = re.search(
                            '\.method\s.+\s(.+)\((.*)\)(.+)', line).groups()
                    except AttributeError:
                        methodName, parameters, returnType = re.search(
                            '\.method\s(.+)\((.*)\)(.+)', line).groups()
                    result['Class'][className]['Method'][methodName] = {}
                    result['Class'][className]['Method'][methodName][
                        'parameters'] = []
                    result['Class'][className]['Method'][methodName][
                        'strings'] = []
                    result['Class'][className]['Method'][methodName][
                        'call-api'] = []
                    result['Class'][className]['Method'][methodName][
                        'returnType'] = None
                    result['Class'][className]['Method'][methodName][
                        'flags'] = None
                    #if returnType not in ['Z','B','C','D','F','I','J','V']:
                    #    print line, returnType
                    #    raw_input()
                    ### Method Parameter
                    for parameter in parameters.split(';'):
                        result['Class'][className]['Method'][methodName][
                            'parameters'].append(parameter[1:].replace(
                                '/', '.'))
                    if returnType == 'Z':
                        returnType = 'boolean'
                    elif returnType == 'B':
                        returnType = 'byte'
                    elif returnType == 'C':
                        returnType = 'char'
                    elif returnType == 'D':
                        returnType = 'double'
                    elif returnType == 'F':
                        returnType = 'float'
                    elif returnType == 'I':
                        returnType = 'int'
                    elif returnType == 'J':
                        returnType == 'long'
                    elif returnType == 'V':
                        returnType = 'void'
                    elif returnType.startswith('L') and returnType.endswith(
                            ';'):
                        returnType = returnType[1:-1].replace('/', '.')
                    result['Class'][className]['Method'][methodName][
                        'returnType'] = returnType
                    #if '[' in returnType:
                elif line.startswith('const-string'):
                    result['Class'][className]['Method'][methodName][
                        'strings'].append(
                            re.search('\"(.*)\"', line).groups()[0])
                ### target = {'class', 'method', 'parameters' = []}
                elif line.startswith('invoke-virtual') or line.startswith(
                        'invoke-static') or line.startswith(
                            'invoke-interfaces'):
                    targetClass, targetMethod, targetMethodParameters, targetMethodReturnType = re.search(
                        'invoke\-.+\s\{.*\}\,\sL(.+)\-\>(.+)\((.*)\)(.*)',
                        line).groups()
                    target = {}
                    target['class'] = targetClass
                    target['mehtod'] = targetMethod
                    target['parameters'] = []
                    if targetMethodParameters.count(';') > 1:
                        for parameter in targetMethodParameters.split(';'):
                            target['parameters'].append(parameter[1:].replace(
                                '/', '.'))
                    else:
                        target['parameters'].append(
                            targetMethodParameters.replace('/', '.'))
                    result['Class'][className]['Method'][methodName][
                        'call-api'].append(target)
                index += 1
        shutil.rmtree('./' + path + '.out')
    return True, ""
    cli.download_packages(pkg_arr)

    apk_file = "apk_files/" + package_name + ".apk"

    if not os.path.isfile(apk_file):
        print("Failed to download " + package_name + " from store.")
        sys.exit()
elif file_path:
    apk_file = file_path

report["package"] = package_name

if apk_file is not None:
    # generate info
    print("[*] Collecting app info")
    apk_info = APK(apk_file)
    report["app_info"] = {
        "md5": apk_info.file_md5,
        "cert_md5": apk_info.cert_md5,
        "file_size": apk_info.file_size,
        "version_name": apk_info.get_androidversion_name(),
        "version_code": apk_info.get_androidversion_code(),
        "main_activity": apk_info.get_main_activity(),
        "activities": apk_info.get_activities(),
        "services": apk_info.get_services(),
        "receivers": apk_info.get_receivers(),
        "providers": apk_info.get_providers(),
        "permissions": apk_info.get_permissions(),
        "certificates": []
    }
Exemple #17
0
def main():
    banner()
    for i in range(start, end):
        target = "bot/" + str(i)
        try:
            apkf = APK(target)
            md5 = apkf.file_md5
            package = apkf.get_package()
            file_size = apkf.file_size
            andro_version = apkf.get_androidversion_name()
            libraries = apkf.get_libraries()
            main_activity = apkf.get_main_activity()
            activities = apkf.get_activities()
            services = apkf.get_services()
            files = apkf.get_files()
            permissions = apkf.get_permissions()
            counter_emails = 0
            counter_urls = 0
            counter_ftps = 0
            all_emails = []
            all_urls = []
            all_ftps = []
            print "----------------------------------------------"
            print colores.header + colores.underline + "[+][TARGET][>]" + package + " [" + str(
                i) + "]" + colores.normal
            print colores.header + "[-][md5][>] " + md5
            print colores.header + "[-][Android version][>] " + andro_version
            print colores.green + "|----[>] " + "Searching emails and links in strings ..." + colores.normal
            strings = os.popen("strings " + target)
            for word in strings:
                #To found emails in strings
                if "@" in word:
                    if word.find(".com") > 0 or word.find(
                            ".es") > 0 or word.find(".eu") > 0 or word.find(
                                ".net") > 0 or word.find(
                                    ".gob") > 0 or word.find(
                                        ".info") > 0 or word.find(".org") > 0:
                        words = word.split(" ")
                        for w in words:
                            if word.find(".com") > 0 or word.find(
                                    ".es"
                            ) > 0 or word.find(".eu") > 0 or word.find(
                                    ".net"
                            ) > 0 or word.find(".gob") > 0 or word.find(
                                    ".info") > 0 or word.find(".org") > 0:
                                counter_emails += 1
                                email = re.findall(r'[\w\.-]+@[\w\.-]+', word)
                                if not email in all_emails:
                                    print colores.green + "|----[EMAIL][>] " + str(
                                        email) + colores.normal
                                    all_emails.append(email)
                #To found urls in strings
                if "http" in word or "wwww." in word:
                    url = re.findall(
                        'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+',
                        word)
                    if not url in all_urls or url == "":
                        all_urls.append(url)
                        print colores.green + "|----[URL][>] " + str(
                            url) + colores.normal
                #To found FTP in strings

                if "ftp" in word:
                    ftp = re.findall(
                        'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+',
                        word)
                    if not ftp in all_ftps or ftp == "":
                        all_ftps.append(ftp)
                        print colores.green + "|----[FTP][>] " + str(
                            ftp) + colores.normal
        except:
            continue
        insert_mongodb(i, package, md5, file_size, andro_version,
                       main_activity, activities, services, permissions,
                       all_urls, all_emails, all_ftps)