예제 #1
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>")
예제 #2
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()
예제 #3
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)
예제 #4
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"