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>")
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()
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)
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"