def get_apk_info(self): apk = APK(self.apk_file) app_icon_file = apk.get_app_icon() app_icon_data = apk.get_file(app_icon_file) size = (256, 256) buffered = BytesIO() im = Image.open(BytesIO(app_icon_data)) im = im.resize(size, Image.ANTIALIAS) im.save(buffered, "PNG") app_icon_b64 = "data:image/png;base64," + base64.b64encode( buffered.getvalue()).decode('utf-8') self.package_name = apk.get_package() self.app_name = apk.get_app_name() self.report_saver.package_name = self.package_name self.report_saver.app_name = self.app_name self.report_saver.version = apk.get_androidversion_code() self.report_saver.app_icon = app_icon_b64 permission_parser = PermissionParser(mode='groups') permission_values = permission_parser.transform( apk.get_permissions()).flatten().tolist() permission_labels = permission_parser.labels() self.report_saver.permissions_actual = { permission_labels[i]: bool(v) for i, v in enumerate(permission_values) }
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 retrieve_content_from_apk(self): a = APK(self.filename) package_name = a.get_package() resources = a.get_android_resources() # .get_strings_resources() self.client_id = resources.get_string(package_name, "PSA_API_CLIENT_ID_PROD")[1] self.client_secret = resources.get_string( package_name, "PSA_API_CLIENT_SECRET_PROD")[1] self.host_brandid_prod = resources.get_string(package_name, "HOST_BRANDID_PROD")[1] self.culture = self.__get_cultures_code( a.get_file("res/raw/cultures.json"), self.country_code) ## Get Customer id self.site_code = BRAND[package_name][ "brand_code"] + "_" + self.country_code + "_ESP" pfx_cert = a.get_file("assets/MWPMYMA1.pfx") save_key_to_pem(pfx_cert, b"y5Y2my5B")
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 find_hidden_dex(apk: APK): files = apk.get_files() hidden_dex_names = [ x for x in files if re.match(r"assets/[a-z0-9]+/[a-z0-9]+", x) ] if len(hidden_dex_names) == 1: hidden_dex_name = hidden_dex_names[0] data = apk.get_file(hidden_dex_name) dex = decrypt_dex(data) if dex is not None: return dex return decrypt_dex_b(data) return None
def get_apk_info(self): apk = APK(self.apk_file) app_icon_file = apk.get_app_icon() app_icon_data = apk.get_file(app_icon_file) size = (256, 256) buffered = BytesIO() im = Image.open(BytesIO(app_icon_data)) im = im.resize(size, Image.ANTIALIAS) im.save(buffered, "PNG") app_icon_b64 = "data:image/png;base64," + base64.b64encode( buffered.getvalue()).decode('utf-8') self.package_name = apk.get_package() self.app_name = apk.get_app_name() self.report_saver.package_name = self.package_name self.report_saver.app_name = self.app_name self.report_saver.version = apk.get_androidversion_code() self.report_saver.app_icon = app_icon_b64
script_dir = dir_path = os.path.dirname(os.path.realpath(__file__)) if sys.version_info < (3, 6): raise RuntimeError("This application requires Python 3.6+") if not argv[1].endswith(".apk"): print("No apk given") sys.exit(1) print("APK loading...") a = APK(argv[1]) package_name = a.get_package() resources = a.get_android_resources() # .get_strings_resources() client_id = resources.get_string(package_name, "PSA_API_CLIENT_ID_PROD")[1] client_secret = resources.get_string(package_name, "PSA_API_CLIENT_SECRET_PROD")[1] HOST_BRANDID_PROD = resources.get_string(package_name, "HOST_BRANDID_PROD")[1] pfx_cert = a.get_file("assets/MWPMYMA1.pfx") REMOTE_REFRESH_TOKEN = None print("APK loaded !") client_email = input(f"{BRAND[package_name]['app_name']} email: ") client_password = getpass(f"{BRAND[package_name]['app_name']} password: "******"What is your country code ? (ex: FR, GB, DE, ES...)\n") ## Get Customer id site_code = BRAND[package_name]["brand_code"] + "_" + country_code + "_ESP" try: res = requests.post(HOST_BRANDID_PROD + "/GetAccessToken", headers={ "Connection": "Keep-Alive", "Content-Type": "application/json",
class XAPK: def __init__(self, folder): self.folder = Path(folder) for x in self.folder.glob('*.apk'): self.apk_src = Path(x) break for x in self.folder.glob('*.obb'): self.obb_src = Path(x) break self.apk = APK(self.apk_src) self.manifest = self.make_manifest() self.icon = self.apk.get_file(self.apk.get_app_icon()) def make_manifest(self): apk_size = self.apk_src.stat().st_size if self.obb_src: obb_size = self.obb_src.stat().st_size else: obb_size = 0 total_size = apk_size + obb_size filename = self.apk.get_filename() manifest = {} manifest['xapk_version'] = 1 manifest['package_name'] = self.apk.get_package() manifest['name'] = self.apk.get_app_name() # manifest['locales_name'] = {} # TODO manifest['version_code'] = self.apk.get_androidversion_code() manifest['version_name'] = self.apk.get_androidversion_name() manifest['min_sdk_version'] = self.apk.get_min_sdk_version() manifest['target_sdk_version'] = self.apk.get_target_sdk_version() manifest['permissions'] = self.apk.get_declared_permissions() manifest['total_size'] = total_size manifest['expansions'] = [] if obb_size: main_obb = {} main_obb[ 'file'] = 'Android/obb/{package_name}/main.{version_code}.{package_name}.obb'.format( **manifest) main_obb['install_location'] = 'EXTERNAL_STORAGE' main_obb[ 'install_path'] = 'Android/obb/{package_name}/main.{version_code}.{package_name}.obb'.format( **manifest) manifest['expansions'].push(main_obb) return manifest def save(self): self.name = '{package_name}_v{version_name}.xapk'.format( **self.manifest) zip_path = self.folder.joinpath(self.name) zip_dir = tempfile.mkdtemp() try: print('copying apk to temp directory...') apk_name = '{package_name}.apk'.format(**self.manifest) apk_src = self.apk_src.resolve() apk_dest = PurePath(zip_dir).joinpath(apk_name) shutil.copy2(apk_src, apk_dest) print('apk: OK') if self.manifest.get('expansions'): print('copying obb to temp directory...') obb_name = self.manifest['expansions'][0]['install_path'] obb_src = self.obb_src.resolve() obb_dest = PurePath(zip_dir).joinpath(obb_name) os.makedirs(Path(obb_dest).parent, exist_ok=True) shutil.copy2(obb_src, obb_dest) print('obb: OK') else: print('no obb found') print('creating icon in temp directory...') icon = self.icon icon_dest = PurePath(zip_dir).joinpath('icon.png') with open(icon_dest, 'wb') as iconfile: iconfile.write(icon) print('icon: OK') print('creating manifest in temp directory...') manifest_dest = PurePath(zip_dir).joinpath('manifest.json') with open(manifest_dest, 'w') as manifestfile: s = json.dumps(self.manifest, separators=(':', ',')) manifestfile.write(s) print('manifest: OK') print('creating xapk archive...') with zipfile.ZipFile(zip_path, 'w', compression=zipfile.ZIP_DEFLATED) as zfd: for root, dirs, files in os.walk(zip_dir): for f in files: filename = os.path.join(root, f) zfd.write(filename, os.path.relpath(filename, zip_dir)) print('xapk: OK') finally: print('cleaning up temp directory...') shutil.rmtree(zip_dir) print('cleanup: OK')
class ApkFileSearch(object): def __init__(self, apk_file, search_strings, file_types, case_insensitive=False, save_matched_files_dir=None): self.apk = APK(apk_file) self.search_strings = search_strings self.file_types = file_types self.save_matched_files_dir = None if save_matched_files_dir: self.save_matched_files_dir = os.path.join( save_matched_files_dir, os.path.splitext(os.path.basename(apk_file))[0]) os.makedirs(self.save_matched_files_dir) flags = 0 if case_insensitive: flags = re.IGNORECASE self.patterns = [ re.compile(search_string, flags=flags) for search_string in search_strings ] def search(self): """iterate through files in the APK and apply search_strings over files that are of type file_types if no search strings specified, consider all files a match if no file_types specified, apply search strings to all files if no search strings and no file types, then return all files """ apk_files = self.apk.get_files_types() search_results = [] for file_path, file_type in apk_files.iteritems(): file_ext = os.path.splitext(os.path.basename(file_path))[1] #if file type filter on, and this file is not that type, then skip if self.file_types and not any( interested_type in file_type.lower() or interested_type in file_ext for interested_type in self.file_types): continue search_result = None file_data = self.apk.get_file(file_path) if self.search_strings: for pattern in self.patterns: match = pattern.search(file_data) if match: search_result = { 'file_path': file_path, 'file_type': file_type, 'search_string': pattern.pattern } search_results.append(search_result) else: search_result = { 'file_path': file_path, 'file_type': file_type, 'search_string': None } search_results.append(search_result) #write individual files if search_result and self.save_matched_files_dir: #save original structure to avoid duplicate filename collisions save_file_path = os.path.join(self.save_matched_files_dir, file_path) if not os.path.exists(os.path.dirname(save_file_path)): os.makedirs(os.path.dirname(save_file_path)) with open(save_file_path, 'wb') as f: f.write(file_data) if 'Android binary XML' in file_type: with open(save_file_path, 'r+') as axml_f: decoded_axml = AXMLPrinter(axml_f.read()).buff axml_f.seek(0) axml_f.write(decoded_axml) axml_f.truncate() return search_results
help= "Add <path> elements containing the mbn path, as extracted from modem.conf files", ) parser.add_argument( "--output", type=Path, default=Path(__file__).parent / 'res/xml/service_provider_sim_configs.xml', help="Write resulting ", ) args = parser.parse_args() oem_modem_config_dir = args.oem_dir / "modem-config" apk_path = args.oem_dir / args.overlay apk = APK(apk_path.as_posix()) print(f"Opened {apk}") file = apk.get_file("res/xml/service_providers.xml") from xml.etree import ElementTree as ET """ NOTE: Use get_xml_obj to get an immutable representation of the tree Use get_xml to get a formatted string representation Use get_buff to get a oneline representation without formatting tokens ET keeps the formatting internally, and spits this out in `.write()`. Inserted elements are not formatted properly. """ et = ET.fromstring(AXMLPrinter(file).get_xml()) assert et.tag == "service_provider_sim_configs" mbn_paths = set()