class App(object): """ this class describes an app """ def __init__(self, app_path, output_dir=None): """ create a App instance :param app_path: local file path of app :return: """ assert app_path is not None self.logger = logging.getLogger(self.__class__.__name__) self.app_path = app_path self.output_dir = output_dir if output_dir is not None: if not os.path.isdir(output_dir): os.makedirs(output_dir) from androguard.core.bytecodes.apk import APK self.apk = APK(self.app_path) self.package_name = self.apk.get_package() self.main_activity = self.apk.get_main_activity() self.permissions = self.apk.get_permissions() self.activities = self.apk.get_activities() self.possible_broadcasts = self.get_possible_broadcasts() self.dumpsys_main_activity = None self.hashes = self.get_hashes() def get_package_name(self): """ get package name of current app :return: """ return self.package_name def get_main_activity(self): """ get package name of current app :return: """ if self.main_activity is not None: return self.main_activity else: self.logger.warning("Cannot get main activity from manifest. Using dumpsys result instead.") return self.dumpsys_main_activity def get_start_intent(self): """ get an intent to start the app :return: Intent """ package_name = self.get_package_name() if self.get_main_activity(): package_name += "/%s" % self.get_main_activity() return Intent(suffix=package_name) def get_start_with_profiling_intent(self, trace_file, sampling=None): """ get an intent to start the app with profiling :return: Intent """ package_name = self.get_package_name() if self.get_main_activity(): package_name += "/%s" % self.get_main_activity() if sampling is not None: return Intent(prefix="start --start-profiler %s --sampling %d" % (trace_file, sampling), suffix=package_name) else: return Intent(prefix="start --start-profiler %s" % trace_file, suffix=package_name) def get_stop_intent(self): """ get an intent to stop the app :return: Intent """ package_name = self.get_package_name() return Intent(prefix="force-stop", suffix=package_name) def get_possible_broadcasts(self): possible_broadcasts = set() for receiver in self.apk.get_receivers(): intent_filters = self.apk.get_intent_filters('receiver', receiver) actions = intent_filters['action'] if 'action' in intent_filters else [] categories = intent_filters['category'] if 'category' in intent_filters else [] categories.append(None) for action in actions: for category in categories: intent = Intent(prefix='broadcast', action=action, category=category) possible_broadcasts.add(intent) return possible_broadcasts def get_hashes(self, block_size=2 ** 8): """ Calculate MD5,SHA-1, SHA-256 hashes of APK input file @param block_size: """ md5 = hashlib.md5() sha1 = hashlib.sha1() sha256 = hashlib.sha256() f = open(self.app_path, 'rb') while True: data = f.read(block_size) if not data: break md5.update(data) sha1.update(data) sha256.update(data) return [md5.hexdigest(), sha1.hexdigest(), sha256.hexdigest()]
def testAPKManifest(self): from androguard.core.bytecodes.apk import APK a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk", testzip=True) self.assertEqual(a.get_app_name(), "TestsAndroguardApplication") self.assertEqual(a.get_app_icon(), "res/drawable-hdpi/icon.png") self.assertEqual(a.get_app_icon(max_dpi=120), "res/drawable-ldpi/icon.png") self.assertEqual(a.get_app_icon(max_dpi=160), "res/drawable-mdpi/icon.png") self.assertEqual(a.get_app_icon(max_dpi=240), "res/drawable-hdpi/icon.png") self.assertIsNone(a.get_app_icon(max_dpi=1)) self.assertEqual(a.get_main_activity(), "tests.androguard.TestActivity") self.assertEqual(a.get_package(), "tests.androguard") self.assertEqual(a.get_androidversion_code(), '1') self.assertEqual(a.get_androidversion_name(), "1.0") self.assertEqual(a.get_min_sdk_version(), "9") self.assertEqual(a.get_target_sdk_version(), "16") self.assertIsNone(a.get_max_sdk_version()) self.assertEqual(a.get_permissions(), []) self.assertEqual(a.get_declared_permissions(), []) self.assertTrue(a.is_valid_APK())
class App(object): def __init__(self, app_path, root_path, app_name): print("Root path:"+root_path) assert app_path is not None self.logger = logging.getLogger(self.__class__.__name__) self.app_path = app_path from androguard.core.bytecodes.apk import APK self.apk = APK(self.app_path) self.package_name = self.apk.get_package() self.main_activity = self.apk.get_main_activity() self.permissions = self.apk.get_permissions() self.activities = self.apk.get_activities() if app_name is not None: self.app_name = app_name else: self.app_name = self.apk.get_app_name() print("Main activity:"+self.main_activity) print("Package name:"+self.package_name) self.output_path=root_path+self.package_name def get_package_name(self): """ get package name of current app :return: """ return self.package_name
def run(self): """Run androguard to extract static android information @return: list of static features """ self.key = "apkinfo" apkinfo = {} if "file" not in self.task["category"] or not HAVE_ANDROGUARD: return f = File(self.task["target"]) if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type(): if not os.path.exists(self.file_path): raise CuckooProcessingError( "Sample file doesn't exist: \"%s\"" % self.file_path) try: a = APK(self.file_path) if a.is_valid_APK(): manifest = {} apkinfo["files"] = self._apk_files(a) manifest["package"] = a.get_package() # manifest["permissions"]=a.get_details_permissions_new() manifest["main_activity"] = a.get_main_activity() manifest["activities"] = a.get_activities() manifest["services"] = a.get_services() manifest["receivers"] = a.get_receivers() # manifest["receivers_actions"]=a.get__extended_receivers() manifest["providers"] = a.get_providers() manifest["libraries"] = a.get_libraries() apkinfo["manifest"] = manifest # apkinfo["certificate"] = a.get_certificate() static_calls = {} if self.check_size(apkinfo["files"]): vm = DalvikVMFormat(a.get_dex()) vmx = uVMAnalysis(vm) static_calls["all_methods"] = self.get_methods(vmx) static_calls[ "is_native_code"] = analysis.is_native_code(vmx) static_calls["is_dynamic_code"] = analysis.is_dyn_code( vmx) static_calls[ "is_reflection_code"] = analysis.is_reflection_code( vmx) # static_calls["dynamic_method_calls"]= analysis.get_show_DynCode(vmx) # static_calls["reflection_method_calls"]= analysis.get_show_ReflectionCode(vmx) # static_calls["permissions_method_calls"]= analysis.get_show_Permissions(vmx) # static_calls["crypto_method_calls"]= analysis.get_show_CryptoCode(vmx) # static_calls["native_method_calls"]= analysis.get_show_NativeMethods(vmx) else: log.warning("Dex size bigger than: %s", self.options.decompilation_threshold) apkinfo["static_method_calls"] = static_calls except (IOError, OSError, BadZipfile) as e: raise CuckooProcessingError("Error opening file %s" % e) return apkinfo
def run(self): """Run androguard to extract static android information @return: list of static features """ self.key = "apkinfo" apkinfo = {} if "file" not in self.task["category"]: return from androguard.core.bytecodes.apk import APK from androguard.core.bytecodes.dvm import DalvikVMFormat from androguard.core.analysis.analysis import uVMAnalysis from androguard.core.analysis import analysis f = File(self.task["target"]) if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type(): if not os.path.exists(self.file_path): raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path) try: a = APK(self.file_path) if a.is_valid_APK(): manifest = {} apkinfo["files"] = self._apk_files(a) manifest["package"] = a.get_package() # manifest["permissions"]=a.get_details_permissions_new() manifest["main_activity"] = a.get_main_activity() manifest["activities"] = a.get_activities() manifest["services"] = a.get_services() manifest["receivers"] = a.get_receivers() # manifest["receivers_actions"]=a.get__extended_receivers() manifest["providers"] = a.get_providers() manifest["libraries"] = a.get_libraries() apkinfo["manifest"] = manifest # apkinfo["certificate"] = a.get_certificate() static_calls = {} if self.check_size(apkinfo["files"]): vm = DalvikVMFormat(a.get_dex()) vmx = uVMAnalysis(vm) static_calls["all_methods"] = self.get_methods(vmx) static_calls["is_native_code"] = analysis.is_native_code(vmx) static_calls["is_dynamic_code"] = analysis.is_dyn_code(vmx) static_calls["is_reflection_code"] = analysis.is_reflection_code(vmx) # static_calls["dynamic_method_calls"]= analysis.get_show_DynCode(vmx) # static_calls["reflection_method_calls"]= analysis.get_show_ReflectionCode(vmx) # static_calls["permissions_method_calls"]= analysis.get_show_Permissions(vmx) # static_calls["crypto_method_calls"]= analysis.get_show_CryptoCode(vmx) # static_calls["native_method_calls"]= analysis.get_show_NativeMethods(vmx) else: log.warning("Dex size bigger than: %s", self.options.decompilation_threshold) apkinfo["static_method_calls"] = static_calls except (IOError, OSError, zipfile.BadZipfile) as e: raise CuckooProcessingError("Error opening file %s" % e) return apkinfo
def get_apk_entry(self): """Get the entry point for this APK. The entry point is denoted by a package and main activity name.""" logging.getLogger("androguard.axml").setLevel(logging.WARNING) logging.getLogger("androguard.core.api_specific_resources").setLevel( logging.WARNING) filetype = self.get_type() if "Zip archive data" not in filetype and "Java archive data" not in filetype: return "", "" from androguard.core.bytecodes.apk import APK try: a = APK(self.file_path) if not a.is_valid_APK(): return "", "" package = a.get_package() if not package: log.warning("Unable to find the main package, this analysis " "will probably fail.") return "", "" main_activity = a.get_main_activity() if main_activity: log.debug("Picked package %s and main activity %s.", package, main_activity) return package, main_activity activities = a.get_activities() for activity in activities: if "main" in activity or "start" in activity: log.debug( "Choosing package %s and main activity due to " "its name %s.", package, activity) return package, activity if activities and activities[0]: log.debug("Picked package %s and the first activity %s.", package, activities[0]) return package, activities[0] except Exception as e: log.warning("Error extracting package and main activity: %s.", e) return "", ""
def testAPKManifest(self): from androguard.core.bytecodes.apk import APK a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk", testzip=True) self.assertEqual(a.get_app_name(), "TestsAndroguardApplication") self.assertEqual(a.get_app_icon(), "res/drawable-hdpi/icon.png") self.assertEqual(a.get_app_icon(max_dpi=120), "res/drawable-ldpi/icon.png") self.assertEqual(a.get_app_icon(max_dpi=160), "res/drawable-mdpi/icon.png") self.assertEqual(a.get_app_icon(max_dpi=240), "res/drawable-hdpi/icon.png") self.assertIsNone(a.get_app_icon(max_dpi=1)) self.assertEqual(a.get_main_activity(), "tests.androguard.TestActivity") self.assertEqual(a.get_package(), "tests.androguard") self.assertEqual(a.get_androidversion_code(), '1') self.assertEqual(a.get_androidversion_name(), "1.0") self.assertEqual(a.get_min_sdk_version(), "9") self.assertEqual(a.get_target_sdk_version(), "16") self.assertIsNone(a.get_max_sdk_version()) self.assertEqual(a.get_permissions(), []) self.assertEqual(a.get_declared_permissions(), []) self.assertTrue(a.is_valid_APK())
def get_apk_entry(self): """Get the entry point for this APK. The entry point is denoted by a package and main activity name.""" filetype = self.get_type() if "Zip archive data" not in filetype and "Java archive data" not in filetype: return "", "" from androguard.core.bytecodes.apk import APK try: a = APK(self.file_path) if not a.is_valid_APK(): return "", "" package = a.get_package() if not package: log.warning("Unable to find the main package, this analysis " "will probably fail.") return "", "" main_activity = a.get_main_activity() if main_activity: log.debug("Picked package %s and main activity %s.", package, main_activity) return package, main_activity activities = a.get_activities() for activity in activities: if "main" in activity or "start" in activity: log.debug("Choosing package %s and main activity due to " "its name %s.", package, activity) return package, activity if activities and activities[0]: log.debug("Picked package %s and the first activity %s.", package, activities[0]) return package, activities[0] except Exception as e: log.warning("Error extracting package and main activity: %s.", e) return "", ""
def extract_attributes(sha256): with NamedTemporaryFile() as f: f.write(default_storage.open(sha256).read()) f.seek(0) sign = ApplicationSignature.compute_from_apk(f.name) package = sign.handle sign = sign.to_dict() a = APK(f.name) sign['uploaded_at'] = datetime.now() sign['sha256'] = sha256 sign['activities'] = a.get_activities() sign['features'] = a.get_features() sign['libraries'] = a.get_libraries() sign['main_activity'] = a.get_main_activity() sign['min_sdk_version'] = a.get_min_sdk_version() sign['max_sdk_version'] = a.get_max_sdk_version() sign['target_sdk_version'] = a.get_target_sdk_version() sign['permissions'] = a.get_permissions() sign['aosp_permissions'] = a.get_requested_aosp_permissions() sign['third_party_permissions'] = a.get_requested_third_party_permissions() sign['providers'] = a.get_providers() sign['receivers'] = a.get_receivers() sign['services'] = a.get_services() sign['is_valid'] = a.is_valid_APK() sign['is_signed'] = a.is_signed() sign['is_signed_v1'] = a.is_signed_v1() sign['is_signed_v2'] = a.is_signed_v2() sign['is_signed_v3'] = a.is_signed_v3() if not es.exists(settings.ELASTICSEARCH_APK_INDEX, id=sha256): es.index(index=settings.ELASTICSEARCH_APK_INDEX, id=sha256, body=sign) else: es.update(index=settings.ELASTICSEARCH_APK_INDEX, id=sha256, body={'doc': sign}, retry_on_conflict=5) del a, sign, f gc.collect() return package
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) apkinfo["APKiD"] = self._scan_APKiD(self.file_path) try: a = APK(self.file_path) if a.is_valid_APK(): manifest = {} apkinfo["files"] = self._apk_files(a) apkinfo["encrypted_assets"] = self.find_encrypted_assets(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["receivers_info"] = get_receivers_info(a) manifest["providers"] = a.get_providers() manifest["libraries"] = a.get_libraries() apkinfo["manifest"] = manifest apkinfo["icon"] = get_apk_icon(self.file_path) certificate = get_certificate(self.file_path) if certificate: apkinfo["certificate"] = certificate #vm = DalvikVMFormat(a.get_dex()) #strings = vm.get_strings() strings = self._get_strings(self.file_path) for subdir, dirs, files in os.walk(self.dropped_path): for file in files: path = os.path.join(subdir, file) try: extra_strings = self._get_strings(path) strings = list(set(extra_strings + strings)) except: pass apkinfo["dex_strings"] = strings static_calls = {} if self.options.decompilation: if self.check_size(apkinfo["files"]): vm = DalvikVMFormat(a.get_dex()) vmx = uVMAnalysis(vm) # Be less verbose about androguard logging messages. logging.getLogger("andro.runtime").setLevel(logging.CRITICAL) static_calls["all_methods"] = get_methods(vmx) static_calls["is_native_code"] = analysis.is_native_code(vmx) static_calls["is_dynamic_code"] = analysis.is_dyn_code(vmx) static_calls["is_reflection_code"] = analysis.is_reflection_code(vmx) static_calls["is_crypto_code"] = is_crypto_code(vmx) static_calls["dynamic_method_calls"] = get_show_DynCode(vmx) static_calls["reflection_method_calls"] = get_show_ReflectionCode(vmx) static_calls["permissions_method_calls"] = get_show_Permissions(vmx) static_calls["crypto_method_calls"] = get_show_CryptoCode(vmx) static_calls["native_method_calls"] = get_show_NativeMethods(vmx) classes = list() for cls in vm.get_classes(): classes.append(cls.name) static_calls["classes"] = classes else: log.warning("Dex size bigger than: %s", self.options.decompilation_threshold) apkinfo["static_method_calls"] = static_calls except (IOError, OSError, BadZipfile) as e: raise CuckooProcessingError("Error opening file %s" % e) return apkinfo
class App(object): """ this class describes an app """ def __init__(self, app_path, output_dir=None): """ create a App instance :param app_path: local file path of app :return: """ assert app_path is not None self.logger = logging.getLogger(self.__class__.__name__) self.app_path = app_path self.output_dir = output_dir if output_dir is not None: if not os.path.isdir(output_dir): os.makedirs(output_dir) from androguard.core.bytecodes.apk import APK self.apk = APK(self.app_path) self.package_name = self.apk.get_package() self.main_activity = self.apk.get_main_activity() self.permissions = self.apk.get_permissions() self.activities = self.apk.get_activities() self.possible_broadcasts = self.get_possible_broadcasts() self.dumpsys_main_activity = None self.hashes = self.get_hashes() def get_package_name(self): """ get package name of current app :return: """ return self.package_name def get_main_activity(self): """ get package name of current app :return: """ if self.main_activity is not None: return self.main_activity else: self.logger.warning( "Cannot get main activity from manifest. Using dumpsys result instead." ) return self.dumpsys_main_activity def get_start_intent(self): """ get an intent to start the app :return: Intent """ package_name = self.get_package_name() if self.get_main_activity(): package_name += "/%s" % self.get_main_activity() return Intent(suffix=package_name) def get_start_with_profiling_intent(self, trace_file, sampling=None): """ get an intent to start the app with profiling :return: Intent """ package_name = self.get_package_name() if self.get_main_activity(): package_name += "/%s" % self.get_main_activity() if sampling is not None: return Intent(prefix="start --start-profiler %s --sampling %d" % (trace_file, sampling), suffix=package_name) else: return Intent(prefix="start --start-profiler %s" % trace_file, suffix=package_name) def get_stop_intent(self): """ get an intent to stop the app :return: Intent """ package_name = self.get_package_name() return Intent(prefix="force-stop", suffix=package_name) def get_possible_broadcasts(self): possible_broadcasts = set() for receiver in self.apk.get_receivers(): intent_filters = self.apk.get_intent_filters('receiver', receiver) actions = intent_filters[ 'action'] if 'action' in intent_filters else [] categories = intent_filters[ 'category'] if 'category' in intent_filters else [] categories.append(None) for action in actions: for category in categories: intent = Intent(prefix='broadcast', action=action, category=category) possible_broadcasts.add(intent) return possible_broadcasts def get_hashes(self, block_size=2**8): """ Calculate MD5,SHA-1, SHA-256 hashes of APK input file @param block_size: """ md5 = hashlib.md5() sha1 = hashlib.sha1() sha256 = hashlib.sha256() f = open(self.app_path, 'rb') while True: data = f.read(block_size) if not data: break md5.update(data) sha1.update(data) sha256.update(data) return [md5.hexdigest(), sha1.hexdigest(), sha256.hexdigest()]
def get_apk_lautc(apk): a = APK(apk, False, "r") return a.get_main_activity()
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
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'
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()
def run(apk_path: str, arch: str): apk = APK(apk_path) apk_path = Path(apk_path) gadget_so_paths = { 'arm': 'libfrida-gadget-12.6.10-android-arm.so', 'arm64': 'libfrida-gadget-12.6.10-android-arm64.so' } if arch not in gadget_so_paths: raise Exception("Can't find the target arch: " + arch) p_gadget_so = FILE_DIR.joinpath(gadget_so_paths[arch]) if not p_gadget_so.exists(): raise Exception("Can't find the target so file: " + str(p_gadget_so.resolve())) # Set main activity main_activity = apk.get_main_activity() main_activity = main_activity.split('.') main_activity[-1] += '.smali' # APK decompile with apktool decompiled_path = TEMP_DIR.joinpath(str(apk_path.resolve())[:-4]) if decompiled_path.exists(): shutil.rmtree(decompiled_path) decompiled_path.mkdir() result = run_apktool( ['d', '-o', str(decompiled_path.resolve()), '-f'], str(apk_path.resolve())) if result: # Add internet permissions android_manifest = decompiled_path.joinpath("AndroidManifest.xml") txt = android_manifest.read_text() pos = txt.index('</manifest>') permission = 'android.permission.INTERNET' if permission not in txt: permissions_txt = "<uses-permission android:name='%s'/>" % permission txt = txt[:pos] + permissions_txt + txt[pos:] if ':extractNativeLibs="false"' in txt: txt = txt.replace(':extractNativeLibs="false"', ':extractNativeLibs="true"') android_manifest.write_text(txt) # Read main activity smali code target_smali = None for smali_dir in decompiled_path.glob("smali*/"): target_smali = smali_dir.joinpath(*main_activity) if target_smali.exists(): break if not target_smali or not target_smali.exists(): raise Exception("Not Found, target class file: " + ".".join(main_activity)) text = target_smali.read_text() text = text.replace( "invoke-virtual {v0, v1}, Ljava/lang/Runtime;->exit(I)V", "") text = text.split("\n") # Find onCreate method and inject loadLibary code for frida gadget idx = 0 flag = False while idx != len(text): line = text[idx].strip() if line.startswith('.method') and "onCreate(" in line: locals_line_bit = text[idx + 1].split(".locals ") locals_variable_count = int(locals_line_bit[1]) locals_line_bit[1] = str(locals_variable_count + 1) new_locals_line = ".locals ".join(locals_line_bit) text[idx + 1] = new_locals_line load_str = ' const-string v%d, "%s"' % ( locals_variable_count, p_gadget_so.name[3:-3]) load_library = ' invoke-static {v%d}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V' % ( locals_variable_count) text.insert(idx + 2, load_library) text.insert(idx + 2, load_str) flag = True break idx += 1 if not flag: raise Exception("Not Found, onCreate") target_smali.write_text( "\n".join(text)) # rewrite main_activity smali file # Copy gadget library to app library directory lib = decompiled_path.joinpath('lib') if not lib.exists(): lib.mkdir() arch_dirnames = {'arm': 'armeabi-v7a', 'arm64': 'arm64-v8a'} if arch not in arch_dirnames: raise Exception('The architecture "%s" is not support' % arch) arch_dirname = arch_dirnames[arch] lib = lib.joinpath(arch_dirname) if not lib.exists(): lib.mkdir() shutil.copy(p_gadget_so, lib.joinpath(p_gadget_so.name)) # Rebuild with apktool, print apk_path if process is success result = run_apktool('b', str(decompiled_path.resolve())) if result: apk_path = decompiled_path.joinpath('dist', apk_path.name) print('Gadget APK: ' + str(apk_path.resolve())) else: shutil.rmtree(decompiled_path)
def run(self): """Run androguard to extract static android information @return: list of static features """ self.key = "apkinfo" apkinfo = {} if "file" not in self.task["category"] or not HAVE_ANDROGUARD: return f = File(self.task["target"]) #if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type(): if not os.path.exists(self.file_path): raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path) try: a = APK(self.file_path) if a.is_valid_APK(): manifest = {} apkinfo["files"] = self._apk_files(a) manifest["package"] = a.get_package() apkinfo["hidden_payload"] = [] for file in apkinfo["files"]: if self.file_type_check(file): apkinfo["hidden_payload"].append(file) apkinfo["files_flaged"] = self.files_name_map manifest["permissions"]= get_permissions(a) manifest["main_activity"] = a.get_main_activity() manifest["activities"] = a.get_activities() manifest["services"] = a.get_services() manifest["receivers"] = a.get_receivers() manifest["receivers_actions"] = get_extended_receivers(a) manifest["providers"] = a.get_providers() manifest["libraries"] = a.get_libraries() apkinfo["manifest"] = manifest apkinfo["icon"] = get_apk_icon(self.file_path) certificate = get_certificate(self.file_path) if certificate: apkinfo["certificate"] = certificate #vm = DalvikVMFormat(a.get_dex()) #strings = vm.get_strings() strings = self._get_strings(self.file_path) apkinfo["interesting_strings"] = find_strings(strings) apkinfo["dex_strings"] = strings static_calls = {} if self.options.decompilation: if self.check_size(apkinfo["files"]): vm = DalvikVMFormat(a.get_dex()) vmx = uVMAnalysis(vm) static_calls["all_methods"] = get_methods(vmx) static_calls["is_native_code"] = analysis.is_native_code(vmx) static_calls["is_dynamic_code"] = analysis.is_dyn_code(vmx) static_calls["is_reflection_code"] = analysis.is_reflection_code(vmx) static_calls["is_crypto_code"] = is_crypto_code(vmx) static_calls["dynamic_method_calls"] = get_show_DynCode(vmx) static_calls["reflection_method_calls"] = get_show_ReflectionCode(vmx) static_calls["permissions_method_calls"] = get_show_Permissions(vmx) static_calls["crypto_method_calls"] = get_show_CryptoCode(vmx) static_calls["native_method_calls"] = get_show_NativeMethods(vmx) classes = list() for cls in vm.get_classes(): classes.append(cls.name) static_calls["classes"] = classes else: log.warning("Dex size bigger than: %s", self.options.decompilation_threshold) apkinfo["static_method_calls"] = static_calls except (IOError, OSError, BadZipfile) as e: raise CuckooProcessingError("Error opening file %s" % e) return apkinfo
from androguard.core.analysis.analysis import VMAnalysis from androguard.core.bytecodes.apk import APK from androguard.core.bytecodes.dvm import DalvikVMFormat from core.analysis import * if __name__ == '__main__': a = APK("1_1.apk") print len(a.get_activities()) print a.get_main_activity() d = DalvikVMFormat(a.get_dex()) dx = VMAnalysis(d) print dx.get_method_signature()
def get_apk_lautc(self, apk): # todo 得到activity a = APK(apk, False, "r") return a.get_main_activity()
def analyze(path): try: start = process_time() hashfunctions = dict(md5=hashlib.md5, sha1=hashlib.sha1, sha256=hashlib.sha256, sha512=hashlib.sha512) a = APK(path) certs = set( a.get_certificates_der_v3() + a.get_certificates_der_v2() + [a.get_certificate_der(x) for x in a.get_signature_names()]) for cert in certs: x509_cert = x509.Certificate.load(cert) issuer = { 'commonName': None, 'organizationName': None, 'organizationalUnitName': None, 'countryName': None, 'stateOrProvinceName': None, 'localityName': None } subject = { 'commonName': None, 'organizationName': None, 'organizationalUnitName': None, 'countryName': None, 'stateOrProvinceName': None, 'localityName': None } strIssuer = get_certificate_name_string(x509_cert.issuer, short=False) strSubject = get_certificate_name_string(x509_cert.subject, short=False) arrIssuer = strIssuer.split(',') for i in arrIssuer: if i.lstrip().split('=')[0] == 'commonName': issuer['commonName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'organizationName': issuer['organizationName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'organizationalUnitName': issuer['organizationalUnitName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'countryName': issuer['countryName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'stateOrProvinceName': issuer['stateOrProvinceName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'localityName': issuer['localityName'] = i.lstrip().split('=')[1] arrSubject = strSubject.split(',') for i in arrSubject: if i.lstrip().split('=')[0] == 'commonName': subject['commonName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'organizationName': subject['organizationName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'organizationalUnitName': subject['organizationalUnitName'] = i.lstrip().split( '=')[1] elif i.lstrip().split('=')[0] == 'countryName': subject['countryName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'stateOrProvinceName': subject['stateOrProvinceName'] = i.lstrip().split('=')[1] elif i.lstrip().split('=')[0] == 'localityName': subject['localityName'] = i.lstrip().split('=')[1] for k, v in hashfunctions.items(): if k == 'md5': md5 = v(cert).hexdigest() elif k == 'sha1': sha1 = v(cert).hexdigest() elif k == 'sha256': sha256 = v(cert).hexdigest() elif k == 'sha512': sha512 = v(cert).hexdigest() md5 = md5 appName = a.get_app_name() fileSize = os.stat(a.get_filename()).st_size sha1 = sha1 sha256 = sha256 sha512 = sha512 timestamp = time.time() dateTime = datetime.fromtimestamp(timestamp) timeOfSubmit = dateTime.strftime("%Y-%m-%d %H:%M:%S") package = a.get_package() androidversionCode = a.get_androidversion_code() androidversionName = a.get_androidversion_name() minSDKVersion = a.get_min_sdk_version() maxSDKVersion = a.get_max_sdk_version() targetSDKVersion = a.get_target_sdk_version() mainActivity = a.get_main_activity() attributes = { 'validFrom': x509_cert['tbs_certificate']['validity'] ['not_before'].native.strftime("%Y-%m-%d %H:%M:%S"), 'validTo': x509_cert['tbs_certificate']['validity'] ['not_after'].native.strftime("%Y-%m-%d %H:%M:%S"), 'serialNumber': hex(x509_cert.serial_number), 'hashAlgorithm': x509_cert.hash_algo, 'signatureAlgorithm': x509_cert.signature_algo } certificateAttributes = json.dumps(attributes) certificateIssuer = json.dumps(issuer) certificateSubject = json.dumps(subject) declaredPermissions = json.dumps(a.get_declared_permissions()) requestedPermissions = json.dumps(a.get_permissions()) activities = json.dumps(a.get_activities()) services = json.dumps(a.get_services()) receivers = json.dumps(a.get_receivers()) providers = json.dumps(a.get_providers()) stop = process_time() analysisTime = stop - start connect = mysql.connect() cursor = connect.cursor() sql = "INSERT INTO tbl_apkinfo (md5, appName, fileSize, analysisTime, sha1, sha256, sha512, firstSubmission, lastSubmission, package, androidversionCode, androidversionName, minSDKVersion, maxSDKVersion, targetSDKVersion, mainActivity, certificateAttributes, certificateIssuer, certificateSubject, declaredPermissions, requestedPermissions, activities, services, providers, receivers) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" param = (md5, appName, fileSize, analysisTime, sha1, sha256, sha512, timeOfSubmit, timeOfSubmit, package, androidversionCode, androidversionName, minSDKVersion, maxSDKVersion, targetSDKVersion, mainActivity, certificateAttributes, certificateIssuer, certificateSubject, declaredPermissions, requestedPermissions, activities, services, providers, receivers) cursor.execute(sql, param) connect.commit() connect.close() androaxml_main(path, os.path.join(app.config['OUTPUT_PATH'], md5 + '.xml')) return True except: return False