def testAPKIntentFilters(self): from androguard.core.bytecodes.apk import APK a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True) activities = a.get_activities() receivers = a.get_receivers() services = a.get_services() filter_list = [] for i in activities: filters = a.get_intent_filters("activity", i) if len(filters) > 0: filter_list.append(filters) for i in receivers: filters = a.get_intent_filters("receiver", i) if len(filters) > 0: filter_list.append(filters) for i in services: filters = a.get_intent_filters("service", i) if len(filters) > 0: filter_list.append(filters) pairs = zip(filter_list, [{'action': ['android.intent.action.MAIN'], 'category': ['android.intent.category.LAUNCHER']}, {'action': ['android.service.notification.NotificationListenerService']}, {'action': ['android.intent.action.BOOT_COMPLETED', 'android.intent.action.MY_PACKAGE_REPLACED'], 'category': ['android.intent.category.HOME']}, {'action': ['android.appwidget.action.APPWIDGET_UPDATE']}]) self.assertTrue(any(x != y for x, y in pairs))
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 testFrameworkResAPK(self): from androguard.core.bytecodes.apk import APK a = APK("examples/tests/lineageos_nexus5_framework-res.apk") self.assertEqual(a.get_app_name(), 'Android System') self.assertEqual(a.get_package(), 'android')
def perform_analysis(self): if self.apk_file and os.path.exists(self.apk_file): try: apk = APK(self.apk_file) except Exception, ex: print ex return self.permissions = apk.get_permissions() # duplicate permissions check if (len(self.permissions) != len(set(self.permissions))): self.permission_duplicate = True # remove duplicate permissions self.permissions = list(set(self.permissions)) # uses-features features_name = apk.get_elements('uses-feature', 'android:name') if len(features_name) > 0: package_name = apk.get_package() features_used = apk.get_elements('uses-feature', 'android:required') for i in xrange(len(features_name)): if features_name[i] != '': if(features_used[i] != '%s.false' % package_name): self.features.append(features_name[i]) self.features = list(set(self.features))
def on_complete(self): receivers = self.get_results("apkinfo", {}).get("manifest", {}).get("receivers", {}) activities = self.get_results("apkinfo", {}).get("manifest", {}).get("activities", {}) services = self.get_results("apkinfo", {}).get("manifest", {}).get("services", {}) app_path = self.get_results("target",{}).get("file",{}).get("path", None) if not app_path: return False if not os.path.exists(app_path): return False app_apk = APK(app_path) dvm = DalvikVMFormat(app_apk.get_dex()) classes = set() for cls in dvm.get_classes(): classes.add(cls.name) for receiver in receivers: if self.convert_class(receiver) not in classes: return True for activity in activities: if self.convert_class(activity) not in classes: return True for service in services: if self.convert_class(service) not in classes: return True
def testAPKCert(self): """ Test if certificates are correctly unpacked from the SignatureBlock files :return: """ from androguard.core.bytecodes.apk import APK import binascii a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk", skip_analysis=True) cert = a.get_certificate_der(a.get_signature_name()) expected = "308201E53082014EA00302010202045114FECF300D06092A864886F70D010105" \ "05003037310B30090603550406130255533110300E060355040A1307416E6472" \ "6F6964311630140603550403130D416E64726F6964204465627567301E170D31" \ "33303230383133333430375A170D3433303230313133333430375A3037310B30" \ "090603550406130255533110300E060355040A1307416E64726F696431163014" \ "0603550403130D416E64726F696420446562756730819F300D06092A864886F7" \ "0D010101050003818D00308189028181009903975EC93F0F3CCB54BD1A415ECF" \ "3505993715B8B9787F321104ACC7397D186F01201341BCC5771BB28695318E00" \ "6E47C888D3C7EE9D952FF04DF06EDAB1B511F51AACDCD02E0ECF5AA7EC6B51BA" \ "08C601074CF2DA579BD35054E4F77BAAAAF0AA67C33C1F1C3EEE05B5862952C0" \ "888D39179C0EDD785BA4F47FB7DF5D5F030203010001300D06092A864886F70D" \ "0101050500038181006B571D685D41E77744F5ED20822AE1A14199811CE649BB" \ "B29248EB2F3CC7FB70F184C2A3D17C4F86B884FCA57EEB289ECB5964A1DDBCBD" \ "FCFC60C6B7A33D189927845067C76ED29B42D7F2C7F6E2389A4BC009C01041A3" \ "6E666D76D1D66467416E68659D731DC7328CB4C2E989CF59BB6D2D2756FDE7F2" \ "B3FB733EBB4C00FD3B" self.assertEqual(binascii.hexlify(cert).decode("ascii").upper(), expected)
def extract_features(file_path): #result = [] a = APK(file_path) #print(a.get_permissions()) #d = DalvikVMFormat(a.get_dex()) #dx = Analysis(d) #vm = dvm.DalvikVMFormat(a.get_dex()) #vmx = analysis.Analysis(vm) #d.set_Analysis(dx) #d.set_decompiler(DecompilerDAD(d, dx)) ''' try: a = APK(file_path) print(a.get_permissions()) d = DalvikVMFormat(a.get_dex()) dx = Analysis(d) vm = dvm.DalvikVMFormat(a.get_dex()) vmx = analysis.uAnalysis(vm) d.set_Analysis(dx) d.set_decompiler(DecompilerDAD(d, dx)) except: return None ''' return a.get_permissions()
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
class ApkAnalysis: def __init__(self, apk_name): self.apk_name = apk_name self.apk = INPUT_APK_DIR + self.apk_name + ".apk" # analyze the dex file self.a = APK(self.apk) # get the vm analysis self.d = DalvikVMFormat(self.a.get_dex()) self.dx = VMAnalysis(self.d) self.gx = GVMAnalysis(self.dx, None) self.d.set_vmanalysis(self.dx) self.d.set_gvmanalysis(self.gx) # create the cross reference self.d.create_xref() self.d.create_dref() def get_all_activities_results(self): activity_names = self.a.get_activities() return [ StaticAnalysisResult(self.apk_name, None, a, VulnType.selected_activities.value, True) for a in activity_names ] def get_smart_input(self): return GetFieldType(self).analyze()
def do_operate(self, args): """ := operate apk path_to_apk := operate dex path_to_classes.dex """ try: if args.split()[0] == "apk": if args.split()[1]: self.logger.log("info", "Loading : {} ...".format(args.split()[1].split("/")[-1])) from androguard.core.bytecodes.apk import APK self.apk = APK(args.split()[1]) if self.apk: print(self.t.yellow("\n\t--> Loaded : {} (!)\n".format(args.split()[1].split("/")[-1]))) self.package = self.apk.get_package() from core.brains.apk.components import Components # Load activies, services, broadcast receivers, and # content providers self.components = Components(self.apk) self.components.enumerate_components() self.permissions = self.apk.get_permissions() self.files = self.apk.get_files() self.files_type = self.apk.get_files_types() # Process virtual machine self.process_vm() else: CommandError("APK not loaded (!)") else: CommandError("Unkown command (!)") except ImportError as e: CommandError(e.message) except IndexError as e: CommandError("Not enough arguments (!)")
def action(self, platformName, platformVersion, deviceName, app): # desired_caps = {'platformName': 'Android', 'platformVersion': '9', 'deviceName': '835c6ae1', # 'app': r'C:\Python37\crm_6.74.0_246_debug_auto.apk', # 'automationName': 'flutter','appPackage': 'com.ibaibu.crmflutter'} #app = r'C:\Python37\crm_6.74.0_246_debug_auto.apk' try: if platformName == 'ios': desired_caps = { 'platformName': platformName, 'platformVersion': platformVersion, 'deviceName': deviceName, 'bundleId': 'bundleId', 'udid': 'udid', 'app': '...ipa', "skipServerInstallation": True } else: appPackage = APK(app, False, "r").get_package() appActivity = APK(app, False, "r").get_main_activity() desired_caps = { 'platformName': platformName, 'platformVersion': platformVersion, 'deviceName': '835c6ae1', 'appPackage': appPackage, 'appActivity': appActivity, 'automationName': 'flutter', "skipServerInstallation": True } self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps) except Exception as e: return ({"code": 1001, "msg": "fail", "data": e}) return ({"code": 200, "msg": "success"})
def testAPKCertFingerprint(self): """ Test if certificates are correctly unpacked from the SignatureBlock files Check if fingerprints matches :return: """ from androguard.core.bytecodes.apk import APK import binascii from cryptography.hazmat.primitives import hashes from hashlib import md5, sha1, sha256 a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk", skip_analysis=True) cert = a.get_certificate(a.get_signature_name()) cert_der = a.get_certificate_der(a.get_signature_name()) # Keytool are the hashes collected by keytool -printcert -file CERT.RSA for h, h2, keytool in [(hashes.MD5, md5, "99:FF:FC:37:D3:64:87:DD:BA:AB:F1:7F:94:59:89:B5"), (hashes.SHA1, sha1, "1E:0B:E4:01:F9:34:60:E0:8D:89:A3:EF:6E:27:25:55:6B:E1:D1:6B"), (hashes.SHA256, sha256, "6F:5C:31:60:8F:1F:9E:28:5E:B6:34:3C:7C:8A:F0:7D:E8:1C:1F:B2:14:8B:53:49:BE:C9:06:44:41:44:57:6D")]: hash_x509 = binascii.hexlify(cert.fingerprint(h())).decode("ascii") x = h2() x.update(cert_der) hash_hashlib = x.hexdigest() self.assertEqual(hash_x509.lower(), hash_hashlib.lower()) self.assertEqual(hash_x509.lower(), keytool.replace(":", "").lower())
def testAPKPermissions(self): from androguard.core.bytecodes.apk import APK a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True) self.assertEqual(a.get_package(), "a2dp.Vol") self.assertListEqual( sorted(a.get_permissions()), sorted([ "android.permission.RECEIVE_BOOT_COMPLETED", "android.permission.CHANGE_WIFI_STATE", "android.permission.ACCESS_WIFI_STATE", "android.permission.KILL_BACKGROUND_PROCESSES", "android.permission.BLUETOOTH", "android.permission.BLUETOOTH_ADMIN", "com.android.launcher.permission.READ_SETTINGS", "android.permission.RECEIVE_SMS", "android.permission.MODIFY_AUDIO_SETTINGS", "android.permission.READ_CONTACTS", "android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS", "android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.READ_PHONE_STATE", "android.permission.BROADCAST_STICKY", "android.permission.GET_ACCOUNTS" ]))
def classify(file, ch): vector = {} result = 0 name, sdk, size = 'unknown', 'unknown', 'unknown' app = APK(file) perm = app.get_permissions() name, sdk, size = meta_fetch(file) for p in permissions: if p in perm: vector[p] = 1 else: vector[p] = 0 data = [v for v in vector.values()] data = np.array(data) if ch == 0: ANN = load_model('static/models/ANN.h5') #print(data) result = ANN.predict([data[sel.support_].tolist()]) print(result) if result < 0.02: # return 'Benign(safe)' result = 'Benign(safe)' else: # return 'Malware' result = 'Malware' if ch == 1: SVC = pickle.load(open('static/models/svc_ga.pkl', 'rb')) result = SVC.predict([data[sel.support_]]) if result == 'benign': result = 'Benign(safe)' else: result = 'Malware' return result, name, sdk, size
def testDifferentStringLocales(self): """ Test if the resolving of different string locales works """ a = APK("examples/tests/a2dp.Vol_137.apk") arsc = a.get_android_resources() p = arsc.get_packages_names()[0] self.assertEqual( sorted(["\x00\x00", "da", "de", "el", "fr", "ja", "ru"]), sorted(arsc.get_locales(p))) item = "SMSDelayText" strings = { "\x00\x00": "Delay for reading text message", "da": "Forsinkelse for læsning af tekst besked", "de": "Verzögerung vor dem Lesen einer SMS", "el": "Χρονοκαθυστέρηση ανάγνωσης μηνυμάτων SMS", "fr": "Délai pour lire un SMS", "ja": "テキストメッセージ読み上げの遅延", "ru": "Задержка зачитывания SMS", } for k, v in strings.items(): e = etree.fromstring(arsc.get_string_resources(p, k)) self.assertEqual(e.find("string[@name='{}']".format(item)).text, v)
def __init__(self, apk_path: str): self.logger = logging.getLogger('{0}.{1}'.format( __name__, self.__class__.__name__)) if not os.path.isfile(apk_path): raise FileNotFoundError( 'The input application file "{0}" was not found'.format( apk_path)) self.apk_path = apk_path self.apk = APK(self.apk_path) self.hashes = self.get_hashes() self.package_name = self.apk.get_package() self.main_activities = self.apk.get_main_activities() # This is the variable that holds the list of intents that should be used to start the app. Every # time an intent is used to start the app, the code should check if the intent is valid (it starts # an existing activity), if it's not valid then the intent should be removed from this list. self.start_intents = self.get_start_intents() self.permissions = self.apk.get_permissions() self.activities = self.apk.get_activities() self.possible_broadcasts = self.get_possible_broadcasts()
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 extract_manifest(apk_file_path): """Extracts the AndroidManifest.xml file from an APK and write it in a new file. Parameters: ----------- apk_file_path: str APK relative file path """ apk = APK(apk_file_path) app_name = apk.get_app_name() axml = apk.get_android_manifest_axml() version = apk.get_androidversion_name() manifest = minidom.parseString(axml.get_buff()).toprettyxml() # Building filename app_name = app_name.replace(' ', '') version = version.replace(' ', '_') manifest_filename = "{}-{}.xml".format(app_name, version) manifest_path = os.path.join(config.DATA_FOLDER, manifest_filename) with open(manifest_path, 'w', encoding='utf8') as file: file.write(manifest)
def getPermissionFromManifest(Apack): SetApk = APK(Apack) ManifestPermissions = SetApk.get_permissions() for permission in ManifestPermissions: if "android.permission" in permission: PermissionDeclared.append(permission) connection = pymysql.connect(host='localhost',user='******',password='',db='dbplaystore') try: with connection.cursor() as cursor: sql = "SELECT `perm_id`, `name` FROM permissions" try: cursor.execute(sql) result = cursor.fetchall() for row in result: perm_name = row if permission in perm_name: permID = row[0] DBConnector.createDeclaredPermission(title, permID) except Exception as e: print(e) connection.commit() finally: connection.close() with open("/home/fypj/Desktop/FYPJ" + AppName + "Declared permissions", "w+") as outfile: json.dump(PermissionDeclared, outfile)
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() # FIXME. eba 6/12/19 start intent hardcoded, since the function is not working well # FIXME. eba 6/12/19 replace with a json config self.main_activity = self.apk.get_main_activity() # self.main_activity = "com.google.android.wearable.fitness.passive.ui.PassiveActivity" 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()
class AndroguardAnalysis(object): def __init__(self, app_path): self.app_path = app_path from androguard.core.bytecodes.apk import APK self.a = APK(app_path) self.d = None self.dx = None def get_detailed_analysis(self): from androguard.misc import AnalyzeDex self.d, self.dx = AnalyzeDex(self.a.get_dex(), raw=True) def get_developer_name(self): developer = "Unknown" if (self.a.is_signed()): try: signatures = self.a.get_signature_names() for signature in signatures: cert = self.a.get_certificate(signature) issuer = get_certificate_name_string(cert.issuer) attr_list = issuer.split(',') for attr in attr_list: if attr.startswith( " organizationName") or attr.startswith( "organizationName"): developer = attr.split('=')[1] except ValueError: print("certificat endommagée ... ") return developer
def get_apis(path): application = APK(path) application_dex = DalvikVMFormat(application.get_dex()) application_x = Analysis(application_dex) methods = set() cs = [cc.get_name() for cc in application_dex.get_classes()] for method in application_dex.get_methods(): g = application_x.get_method(method) if method.get_code() == None: continue for i in g.get_basic_blocks().get(): for ins in i.get_instructions(): output = ins.get_output() match = re.search(r'(L[^;]*;)->[^\(]*\([^\)]*\).*', output) if match and match.group(1) not in cs: methods.add(match.group()) methods = list(methods) return methods
def addAPK(self, filename, data): """ Add an APK file to the Session and run analysis on it. :param filename: (file)name of APK file :param data: binary data of the APK file :return: a tuple of SHA256 Checksum and APK Object """ digest = hashlib.sha256(data).hexdigest() log.debug("add APK:%s" % digest) apk = APK(data, True) self.analyzed_apk[digest] = [apk] self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename dx = Analysis() self.analyzed_vms[digest] = dx for dex in apk.get_all_dex(): # we throw away the output... FIXME? self.addDEX(filename, dex, dx, postpone_xref=True) # Postponed dx.create_xref() log.debug("added APK:%s" % digest) return digest, apk
def testAdaptiveIcon(self): # See https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive.html from androguard.core.bytecodes.apk import APK from androguard.core.bytecodes.axml import AXMLPrinter a = APK("examples/tests/com.android.example.text.styling.apk") self.assertEqual(a.get_app_icon(), "res/mipmap-anydpi-v26/ic_launcher.xml") x = AXMLPrinter(a.get_file(a.get_app_icon())).get_xml().decode("UTF-8") self.assertIn("adaptive-icon", x) # * ldpi (low) ~120dpi # * mdpi (medium) ~160dpi # * hdpi (high) ~240dpi # * xhdpi (extra-high) ~320dpi # * xxhdpi (extra-extra-high) ~480dpi # * xxxhdpi (extra-extra-extra-high) ~640dpi self.assertIsNone(a.get_app_icon(max_dpi=120)) # No LDPI icon self.assertIn("mdpi", a.get_app_icon(max_dpi=160)) self.assertIn("hdpi", a.get_app_icon(max_dpi=240)) self.assertIn("xhdpi", a.get_app_icon(max_dpi=320)) self.assertIn("xxhdpi", a.get_app_icon(max_dpi=480)) self.assertIn("xxxhdpi", a.get_app_icon(max_dpi=640)) self.assertIn(".png", a.get_app_icon(max_dpi=65533)) self.assertIn(".xml", a.get_app_icon(max_dpi=65534))
def run(self): """Run Google play unofficial python api the get the google play information @return: list of google play features """ self.key = "googleplay" googleplay = {} if not HAVE_GOOGLEPLAY: log.error("Unable to import the GooglePlay library, has it been " "installed properly?") return if "file" not in self.task["category"]: return f = File(self.task["target"]) if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type(): if not os.path.exists(self.file_path): raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path) android_id = self.options.get("android_id") google_login = self.options.get("google_login") google_password = self.options.get("google_password") # auth_token = self.options.get("auth_token", None) if not android_id and not google_login and not google_password: raise CuckooProcessingError("Google Play Credentials not configured, skip") try: a = APK(self.file_path) if a.is_valid_APK(): package = a.get_package() # Connect api = GooglePlayAPI(android_id) api.login(google_login, google_password, None) # Get the version code and the offer type from the app details app_data = api.details(package) app_detail = app_data.docV2.details.appDetails if not app_detail.installationSize: return googleplay googleplay["title"] = app_detail.title googleplay["app_category"] = app_detail.appCategory._values googleplay["version_code"] = app_detail.versionCode googleplay["app_type"] = app_detail.appType googleplay["content_rating"] = app_detail.contentRating googleplay["developer_email"] = app_detail.developerEmail googleplay["developer_name"] = app_detail.developerName googleplay["developer_website"] = app_detail.developerWebsite googleplay["installation_size"] = app_detail.installationSize googleplay["num_downloads"] = app_detail.numDownloads googleplay["upload_date"] = app_detail.uploadDate googleplay["permissions"] = app_detail.permission._values except (IOError, OSError, zipfile.BadZipfile) as e: raise CuckooProcessingError("Error opening file %s" % e) return googleplay
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 __init__(self, app_path): """ :param app_path: local file path of app, should not be None analyse app specified by app_path """ self.app_path = app_path from androguard.core.bytecodes.apk import APK self.a = APK(app_path)
def get_permissions(path): application = APK(path) permissions = application.get_permissions() permissions = list(set(permissions)) permissions.sort() return permissions
def __init__(self, folder): self.folder = Path(folder) for x in self.folder.glob('*.apk'): self.apk_src = Path(x) for x in self.folder.glob('*.obb'): self.obb_src = Path(x) self.apk = APK(self.apk_src) self.manifest = self.make_manifest() self.icon = self.apk.get_file(self.apk.get_app_icon())
def extract_features(file_path): a = APK(file_path) # d = DalvikVMFormat(a.get_dex()) # dx = Analysis(d) # vm = dvm.DalvikVMFormat(a.get_dex()) # vmx = analysis.Analysis(vm) # d.set_vmanalysis(dx) # d.set_decompiler(DecompilerDAD(d, dx)) return a.get_permissions()
def extract_permissions(file): a = APK(file) d = DalvikVMFormat(a.get_dex()) dx = VMAnalysis(d) vm = dvm.DalvikVMFormat(a.get_dex()) vmx = analysis.uVMAnalysis(vm) d.set_vmanalysis(dx) d.set_decompiler(DecompilerDAD(d, dx)) return a.get_permissions()
def frosting_analysis(sha256): BLOCK_TYPES = { # 0x7109871a: 'SIGNv2', # 0xf05368c0: 'SIGNv3', 0x2146444e: 'Google metadata', 0x42726577: 'Verity padding', 0x6dff800d: 'Source stamp V2 X509 cert', # JSON with some metadata, used by Chinese company Meituan 0x71777777: 'Meituan metadata', # Dependencies metadata generated by Gradle and encrypted by Google Play. # "...The data is compressed, encrypted by a Google Play signing key..." # https://developer.android.com/studio/releases/gradle-plugin#dependency-metadata 0x504b4453: 'Dependency metadata', } with NamedTemporaryFile() as f: f.write(default_storage.open(sha256).read()) f.seek(0) try: a = APK(f.name) a.parse_v2_v3_signature() frosting_data = { 'is_frosted': 0x2146444e in a._v2_blocks, 'v2_signature_blocks': [] } for b in a._v2_blocks: if b in BLOCK_TYPES.keys(): frosting_data['v2_signature_blocks'].append({ 'value': str(hex(b)), 'comment': BLOCK_TYPES[b], 'content': binascii.b2a_base64( a._v2_blocks[b]).decode('utf-8').strip() }) else: frosting_data['v2_signature_blocks'].append({ 'value': str(hex(b)), 'comment': 'Unknown', 'content': binascii.b2a_base64( a._v2_blocks[b]).decode('utf-8').strip() }) es.update(index=settings.ELASTICSEARCH_APK_INDEX, id=sha256, body={'doc': { 'frosting_data': frosting_data }}, retry_on_conflict=5) except Exception as e: pass
def testPartialSignature(self): from androguard.core.bytecodes.apk import APK a = APK("examples/tests/partialsignature.apk", skip_analysis=True) self.assertIn("META-INF/CERT.RSA", a.get_files()) self.assertIn("META-INF/6AD89F48.RSA", a.get_files()) self.assertNotIn("META-INF/CERT.RSA", a.get_signature_names()) self.assertIn("META-INF/6AD89F48.RSA", a.get_signature_names())
def install_app_and_install_frida(app_path): app = APK(app_path) package_name = app.get_package() logger.info("Start ADB") adb = ADB() logger.info("Install APP") adb.install_app(app_path) logger.info("Frida Initialize") push_and_start_frida_server(adb) return package_name
def create_perm_vector(apk_file): try: a = APK(apk_file) except: return None perms = a.get_permissions() for permission in PERMISSIONS: hit = 1 if permission in perms else 0 perm_vector.append(hit) return list(perm_vector)
def find_hidden_dex(apk: APK) -> Optional[DalvikVMFormat]: files = apk.get_files() hidden_dex_names = [ x for x in files if re.match(r"assets/[a-zA-Z0-9]+", x) ] if len(hidden_dex_names) == 1: hidden_dex_name = hidden_dex_names[0] data = apk.get_file(hidden_dex_name) return decrypt_dex(data) return None
def parse_apk(path): """ Parse an apk file to my custom bytecode output :param path: the path to the :rtype: string """ # Load our example APK a = APK(path) # Create DalvikVMFormat Object #d = DalvikVMFormat(a) return a.get_dex()
def parse_apk(apk_path): apk = APK(apk_path) package = apk.get_package() version_code = apk.get_androidversion_code() version_name = apk.get_androidversion_name() tmp_icon = save_icon(apk, package) return {"version_code": version_code, "version_name": version_name, "tmp_icon": tmp_icon, "package": package}
def testNewZipWithNewFile(self): from androguard.core.bytecodes.apk import APK try: from unittest.mock import patch, MagicMock except: from mock import patch, MagicMock a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True) with patch('zipfile.ZipFile') as zipFile: mockZip = MagicMock() zipFile.return_value=mockZip a.new_zip("testout.apk", new_files={'res/menu/menu.xml': 'content'}) self.assertTrue(mockZip.writestr.call_count == 48) self.assertTrue(mockZip.close.called)
def testNewZipWithoutModification(self): from androguard.core.bytecodes.apk import APK try: from unittest.mock import patch, MagicMock except: from mock import patch, MagicMock a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True) with patch('zipfile.ZipFile') as zipFile: mockZip = MagicMock() zipFile.return_value=mockZip a.new_zip("testout.apk") self.assertEqual(mockZip.writestr.call_count, 48) self.assertTrue(mockZip.close.called)
def AnalyzeAPK(_file, session=None, raw=False): """ Analyze an android application and setup all stuff for a more quickly analysis! If session is None, no session is used at all. This is the default behaviour. If you like to continue your work later, it might be a good idea to use a session. A default session can be created by using :meth:`~get_default_session`. :param _file: the filename of the android application or a buffer which represents the application :type _file: string (for filename) or bytes (for raw) :param session: A session (default: None) :param raw: boolean if raw bytes are supplied instead of a filename :rtype: return the :class:`~androguard.core.bytecodes.apk.APK`, list of :class:`~androguard.core.bytecodes.dvm.DalvikVMFormat`, and :class:`~androguard.core.analysis.analysis.Analysis` objects """ log.debug("AnalyzeAPK") if session: log.debug("Using existing session {}".format(session)) if raw: data = _file filename = hashlib.md5(_file).hexdigest() else: with open(_file, "rb") as fd: data = fd.read() filename = _file digest = session.add(filename, data) return session.get_objects_apk(filename, digest) else: log.debug("Analysing without session") a = APK(_file, raw=raw) # FIXME: probably it is not necessary to keep all DalvikVMFormats, as # they are already part of Analysis. But when using sessions, it works # this way... d = [] dx = Analysis() for dex in a.get_all_dex(): df = DalvikVMFormat(dex, using_api=a.get_target_sdk_version()) dx.add(df) d.append(df) df.set_decompiler(decompiler.DecompilerDAD(d, dx)) dx.create_xref() return a, d, dx
def analyze_apk(filename, raw=False, decompiler=None): """ Analyze an android application and setup all stuff for a more quickly analysis ! :param filename: the filename of the android application or a buffer which represents the application :type filename: string :param raw: True is you would like to use a buffer (optional) :type raw: boolean :param decompiler: ded, dex2jad, dad (optional) :type decompiler: string :rtype: return the :class:`APK`, :class:`DalvikVMFormat`, and :class:`VMAnalysis` objects """ a = APK(filename, raw) d, dx = analyze_dex(a.get_dex(), raw=True, decompiler=decompiler) return a, d, dx
def perform_analysis(self): if self.apk_file and os.path.exists(self.apk_file): try: apk = APK(self.apk_file) except Exception, ex: print ex return # Intents self.intents = apk.get_elements('action', 'android:name') # Create DalvikFormat dalvik_vm_format = None try: dalvik_vm_format = DalvikVMFormat( apk.get_dex() ) except Exception, ex: print ex return
class GetFieldType: predictions = {} def __init__(self, args): self.apk = args.apk self.verbosity = args.verbosity self.output_location = args.output_location self.file_identifier = args.apk.split('.')[0] self.file_identifier = self.file_identifier[-24:] # print "Analyzing " + self.apk # print " Output Location " + self.output_location # print "File Identifier " + self.file_identifier # analyze the dex file print "From LOCATION = ",self.apk self.a = APK(self.apk) # get the vm analysis self.d = DalvikVMFormat(self.a.get_dex()) self.dx = VMAnalysis(self.d) self.gx = GVMAnalysis(self.dx, None) self.d.set_vmanalysis(self.dx) self.d.set_gvmanalysis(self.gx) # create the cross reference self.d.create_xref() self.d.create_dref() print 'CWD: ', os.getcwd() predictor = Predict_Input(self.output_location,self.file_identifier) self.predictions = predictor.predict(self.apk, self.apk[:-4],self.output_location,self.file_identifier) try: # get the classes for this apk # store them in a dict self.classes = self.get_class_dict() # Find the R$layout class self.Rlayout = self.get_RLayout(self.d.get_classes()) # Find the R$id class self.Rid = self.get_Rid(self.d.get_classes()) # Store all fields referenced in R$id self.fields, self.field_refs = self.get_fields(self.Rid) except Exception, e: print e
def extract_apk_permisson(name,category): path = '/media/新加卷/begin_android_english/'+category+'/'+name+'.apk' try: apk=APK(path) if apk.is_valid_APK(): package=apk.get_package() permissions=apk.get_permissions() # clean repeat permission simple_permissions=set() for p in permissions: p=p.split('.')[-1] if PERMISSIONS.has_key(p): simple_permissions.add(p) insert_sql='insert into apk_permission(package,category' attrs=',' for permission in simple_permissions: attrs=attrs+permission+',' attrs=attrs.rstrip(',') values="values ('%s','%s',"%(package,category) for i in range(len(simple_permissions)): values=values+'1,' values=values.rstrip(',') values=values+')' insert_sql=insert_sql+attrs+') '+values #print insert_sql db.insert(insert_sql) print ('analysis %s'%(path)) else: print('%s is not valid apk'%(path)) except: etype, evalue, tracebackObj = sys.exc_info()[:3] print ('apk:%s errortype:%s errorvalue:%s'%(path,etype,evalue)) finally: sql = "update apk set state = 0 where package='%s'"%name print sql db1.update(sql) print 1
def testFallback(self): a = APK("examples/tests/com.teleca.jamendo_35.apk") # Should use the fallback self.assertEqual(a.get_app_name(), "Jamendo") res_parser = a.get_android_resources() res_id = int(a.get_element('application', 'label')[1:], 16) # Default Mode, no config self.assertEqual(len(res_parser.get_res_configs(res_id)), 2) # With default config, but fallback self.assertEqual(len(res_parser.get_res_configs(res_id, axml.ARSCResTableConfig.default_config())), 1) # With default config but no fallback self.assertEqual(len(res_parser.get_res_configs(res_id, axml.ARSCResTableConfig.default_config(), fallback=False)), 0) # Also test on resolver: self.assertListEqual(list(map(itemgetter(1), res_parser.get_resolved_res_configs(res_id))), ["Jamendo", "Jamendo"]) self.assertListEqual(list(map(itemgetter(1), res_parser.get_resolved_res_configs(res_id, axml.ARSCResTableConfig.default_config()))), ["Jamendo"])
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 androsign_main(args_apk, args_hash, args_all, show): from androguard.core.bytecodes.apk import APK from androguard.util import get_certificate_name_string import hashlib import traceback from colorama import Fore, Style from asn1crypto import x509 # Keep the list of hash functions in sync with cli/entry_points.py:sign hashfunctions = dict(md5=hashlib.md5, sha1=hashlib.sha1, sha256=hashlib.sha256, sha512=hashlib.sha512, ) if args_hash.lower() not in hashfunctions: print("Hash function {} not supported!" .format(args_hash.lower()), file=sys.stderr) print("Use one of {}" .format(", ".join(hashfunctions.keys())), file=sys.stderr) sys.exit(1) for path in args_apk: try: a = APK(path) print("{}, package: '{}'".format(os.path.basename(path), a.get_package())) print("Is signed v1: {}".format(a.is_signed_v1())) print("Is signed v2: {}".format(a.is_signed_v2())) certs = set(a.get_certificates_der_v2() + [a.get_certificate_der(x) for x in a.get_signature_names()]) if len(certs) > 0: print("Found {} unique certificates".format(len(certs))) for cert in certs: if show: x509_cert = x509.Certificate.load(cert) print("Issuer:", get_certificate_name_string(x509_cert.issuer, short=True)) print("Subject:", get_certificate_name_string(x509_cert.subject, short=True)) print("Serial Number:", hex(x509_cert.serial_number)) print("Hash Algorithm:", x509_cert.hash_algo) print("Signature Algorithm:", x509_cert.signature_algo) print("Valid not before:", x509_cert['tbs_certificate']['validity']['not_before'].native) print("Valid not after:", x509_cert['tbs_certificate']['validity']['not_after'].native) if not args_all: print("{} {}".format(args_hash.lower(), hashfunctions[args_hash.lower()](cert).hexdigest())) else: for k, v in hashfunctions.items(): print("{} {}".format(k, v(cert).hexdigest())) print() except: print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr) traceback.print_exc(file=sys.stderr) if len(args_apk) > 1: print()
def testAPKPermissions(self): from androguard.core.bytecodes.apk import APK a = APK("examples/tests/a2dp.Vol_137.apk", testzip=True) self.assertEqual(a.get_package(), "a2dp.Vol") self.assertListEqual(sorted(a.get_permissions()), sorted(["android.permission.RECEIVE_BOOT_COMPLETED", "android.permission.CHANGE_WIFI_STATE", "android.permission.ACCESS_WIFI_STATE", "android.permission.KILL_BACKGROUND_PROCESSES", "android.permission.BLUETOOTH", "android.permission.BLUETOOTH_ADMIN", "com.android.launcher.permission.READ_SETTINGS", "android.permission.RECEIVE_SMS", "android.permission.MODIFY_AUDIO_SETTINGS", "android.permission.READ_CONTACTS", "android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS", "android.permission.WRITE_EXTERNAL_STORAGE", "android.permission.READ_PHONE_STATE", "android.permission.BROADCAST_STICKY", "android.permission.GET_ACCOUNTS"]))
def addAPK(self, filename, data): """ Add an APK file to the Session and run analysis on it. :param filename: (file)name of APK file :param data: binary data of the APK file :return: a tuple of SHA256 Checksum and APK Object """ digest = hashlib.sha256(data).hexdigest() log.debug("add APK:%s" % digest) apk = APK(data, True) self.analyzed_apk[digest] = [apk] self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename dx = Analysis() self.analyzed_vms[digest] = dx for dex in apk.get_all_dex(): # we throw away the output... FIXME? self.addDEX(filename, dex, dx) log.debug("added APK:%s" % digest) return digest, apk
class AndroguardAnalysis(object): """ analysis result of androguard """ def __init__(self, app_path): """ :param app_path: local file path of app, should not be None analyse app specified by app_path """ self.app_path = app_path from androguard.core.bytecodes.apk import APK self.a = APK(app_path) def get_detailed_analysis(self): from androguard.misc import AnalyzeDex self.d, self.dx = AnalyzeDex(self.a.get_dex(), raw=True)
class StaticAnalysis: def __init__(self): print "Static Analysis" self.apk = None def load_apk(self, apk): if apk is not None and os.path.isfile(apk): self.apk = APK(apk) else: raise IOError("{0} could not be loaded".format(apk)) def get_apk_package(self): try: return self.apk.get_package() except Exception, e: raise e
def main(): parser = get_parser() args = parser.parse_args() hashfunctions = dict(md5=hashlib.md5, sha1=hashlib.sha1, sha256=hashlib.sha256, sha512=hashlib.sha512, ) if args.hash.lower() not in hashfunctions: print("Hash function {} not supported!".format(args.hash.lower()), file=sys.stderr) print("Use one of {}".format(", ".join(hashfunctions.keys())), file=sys.stderr) sys.exit(1) for path in args.apk: try: a = APK(path) print("{}, package: '{}'".format(os.path.basename(path), a.get_package())) print("Is signed v1: {}".format(a.is_signed_v1())) print("Is signed v2: {}".format(a.is_signed_v2())) certs = set(a.get_certificates_der_v2() + [a.get_certificate_der(x) for x in a.get_signature_names()]) if len(certs) > 0: print("Found {} unique certificates".format(len(certs))) for cert in certs: if args.show: x509_cert = x509.Certificate.load(cert) print("Issuer:", get_certificate_name_string(x509_cert.issuer, short=True)) print("Subject:", get_certificate_name_string(x509_cert.subject, short=True)) print("Serial Number:", hex(x509_cert.serial_number)) print("Hash Algorithm:", x509_cert.hash_algo) print("Signature Algorithm:", x509_cert.signature_algo) print("Valid not before:", x509_cert['tbs_certificate']['validity']['not_before'].native) print("Valid not after:", x509_cert['tbs_certificate']['validity']['not_after'].native) if not args.all: print("{} {}".format(args.hash.lower(), hashfunctions[args.hash.lower()](cert).hexdigest())) else: for k, v in hashfunctions.items(): print("{} {}".format(k, v(cert).hexdigest())) print() except: print(Fore.RED + "Error in {}".format(os.path.basename(path)) + Style.RESET_ALL, file=sys.stderr) traceback.print_exc(file=sys.stderr) if len(args.apk) > 1: print()
def do_operate(self, *args): """ := operate apk path_to_apk := operate dex path_to_classes.dex """ # Locals arg0 = args[0].split(" ")[0] arg1 = args[0].split(" ")[1] try: if arg0 == "apk": if arg1: self.logger.log("info", "Loading : {} ..." .format(arg1.split("/")[-1])) from androguard.core.bytecodes.apk import APK self.apk = APK(arg1) if self.apk: print(self.t.yellow("\n\t--> Loaded : {} (!)\n" .format(arg1.split("/")[-1]))) self.package = self.apk.get_package() from core.brains.apk.components import Components # Load activies, services, broadcast receivers, and # content providers self.components = Components(self.apk) self.components.enumerate_components() self.permissions = self.apk.get_permissions() self.files = self.apk.get_files() self.files_type = self.apk.get_files_types() # Process DVM self.process_vm(apk=True) else: CommandError("APK not loaded (!)") elif arg0 == "dex": if arg1: self.logger.log("info", "Loading : {} ..." .format(arg1.split("/")[-1])) self.dex = arg1 self.process_vm(dex=True) except ImportError as e: CommandError("operate : {}".format(e))
class GetFieldType: def __init__(self, args): self.apk = args.apk self.verbosity = args.verbosity print "Analyzing " + self.apk # analyze the dex file self.a = APK(self.apk) # get the vm analysis self.d = DalvikVMFormat(self.a.get_dex()) self.dx = VMAnalysis(self.d) self.gx = GVMAnalysis(self.dx, None) self.d.set_vmanalysis(self.dx) self.d.set_gvmanalysis(self.gx) # create the cross reference self.d.create_xref() self.d.create_dref() try: # get the classes for this apk # store them in a dict self.classes = self.get_class_dict() # Find the R$layout class self.Rlayout = self.get_RLayout(self.d.get_classes()) # Find the R$id class self.Rid = self.get_Rid(self.d.get_classes()) # Store all fields referenced in R$id self.fields, self.field_refs = self.get_fields(self.Rid) except Exception, e: print e