def getSecondRoundToken(self, first_token, params): if self.gsfId is not None: params['androidId'] = "{0:x}".format(self.gsfId) params['Token'] = first_token params['check_email'] = '1' params['token_request_options'] = 'CAA4AQ==' params['system_partition'] = '1' params['_opt_is_called_from_account_manager'] = '1' params.pop('Email') params.pop('EncryptedPasswd') headers = self.deviceBuilder.getAuthHeaders(self.gsfId) headers['app'] = 'com.android.vending' response = self.session.post(AUTH_URL, data=params, headers=headers, verify=ssl_verify) data = response.text.split() params = {} for d in data: if "=" not in d: continue k, v = d.split("=", 1) params[k.strip().lower()] = v.strip() if 'error' in params: raise ConnectionError('') if "auth" in params: return params["auth"] elif "error" in params: Log.error(f'Google Play - server says: " + {params["error"]}') sys.exit(4) else: Log.error('Google Play - auth token not found') sys.exit(4)
def executeRequestApi2(self, path, post_data=None, content_type=CONTENT_TYPE_URLENC, params=None): if self.authSubToken is None: Log.error('You need to login before executing any request') sys.exit(4) headers = self.getHeaders() headers["Content-Type"] = content_type if post_data is not None: response = self.session.post(path, data=str(post_data), headers=headers, params=params, verify=ssl_verify, timeout=60) else: response = self.session.get(path, headers=headers, params=params, verify=ssl_verify, timeout=60) message = googleplay_pb2.ResponseWrapper.FromString(response.content) if message.commands.displayErrorMessage != "": raise ConnectionError(message.commands.displayErrorMessage) return message
def download_app(self): download_url = '' file_name = '' component_search_result = self.search_component() for asset in component_search_result.get('assets', {}): if asset.get('contentType', '') in ('application/vnd.android.package-archive', 'application/x-itunes-ipa'): download_url = asset.get('downloadUrl') file_name = download_url.split('/')[-1] if download_url.split( '/')[-1] != '' else f'{self.group_id}-{self.version}.apk' break if not download_url: Log.error( f'NexusRepo: Unable to find download URL: {len(component_search_result)}' ) response = self.session.get(download_url, allow_redirects=True) if response.status_code != 200: Log.error( f'NexusRepo: Failed to download application. Request return status code: {response.status_code}' ) sys.exit(4) path_to_save = os.path.join(self.download_path, file_name) if not os.path.exists(self.download_path): os.mkdir(self.download_path) with open(path_to_save, 'wb') as file: file.write(response.content) return path_to_save
def getAuthSubToken(self, email, passwd): requestParams = self.deviceBuilder.getLoginParams(email, passwd) requestParams['service'] = 'androidmarket' requestParams['app'] = 'com.android.vending' headers = self.deviceBuilder.getAuthHeaders(self.gsfId) headers['app'] = 'com.android.vending' with requests.Session() as s: s.headers = { 'User-Agent': 'GoogleAuth/1.4', 'device': "{0:x}".format(self.gsfId) } response = s.post(AUTH_URL, data=requestParams, verify=ssl_verify) data = response.text.split() params = {} for d in data: if "=" not in d: continue k, v = d.split("=", 1) params[k.strip().lower()] = v.strip() if "token" in params: master_token = params["token"] second_round_token = self.getSecondRoundToken( master_token, requestParams) self.authSubToken = second_round_token elif "error" in params: Log.error(f'Google Play - server says: " + {params["error"]}') sys.exit(4) else: Log.error('Google Play - auth token not found') sys.exit(4)
def connect(self): self.session = requests.session() api_url = self.nexus_url + '/service/rapture/session' body = {'username': self.login, 'password': self.password} json_response = self.session.post(api_url, data=body, verify=False) if json_response.status_code == 403: Log.error('NexusRepo: Incorrect authentication credentials') elif json_response.status_code == 500: Log.error( "NexusRepo: Nexus Repo server error 500 during authentication")
def download_file(url, download_path, file_path): with requests.get(url, stream=True) as r: if r.status_code != 200: Log.error( f'Failed to download application. Request return status code: {r.status_code}"' ) sys.exit(4) if not os.path.exists(download_path): os.mkdir(download_path) Log.info( f'Creating directory {download_path} for downloading app from AppStore' ) with open(file_path, 'wb') as f: for chunk in r.iter_content(chunk_size=1 * 1024 * 1024): f.write(chunk) f.close() if os.path.exists(file_path): Log.info('Application successfully downloaded') else: Log.info( 'Failed to download application. ' 'Seems like something is wrong with your file path or app file is broken' ) return file_path
def download(self, packageName, versionCode=None, offerType=1): if self.authSubToken is None: Log.error( 'Google Play - You need to login before executing any request') sys.exit(4) if versionCode is None: appDetails = self.details(packageName).get('details').get( 'appDetails') versionCode = appDetails.get('versionCode') headers = self.getHeaders() params = { 'ot': str(offerType), 'doc': packageName, 'vc': str(versionCode) } response = requests.post(PURCHASE_URL, headers=headers, params=params, timeout=60) response = googleplay_pb2.ResponseWrapper.FromString(response.content) if response.commands.displayErrorMessage != "": Log.error(f'Google Play - {response.commands.displayErrorMessage}') sys.exit(4) else: downloadToken = response.payload.buyResponse.downloadToken if downloadToken is not None: params['dtok'] = downloadToken response = requests.get(DELIVERY_URL, headers=headers, params=params, timeout=60) response = googleplay_pb2.ResponseWrapper.FromString(response.content) if response.commands.displayErrorMessage != "": Log.error(f'Google Play - {response.commands.displayErrorMessage}') sys.exit(4) elif response.payload.deliveryResponse.appDeliveryData.downloadUrl == "": Log.error('Google Play - App not purchased') sys.exit(4) else: result = {'docId': packageName, 'additionalData': [], 'splits': []} downloadUrl = response.payload.deliveryResponse.appDeliveryData.downloadUrl cookie = response.payload.deliveryResponse.appDeliveryData.downloadAuthCookie[ 0] cookies = {str(cookie.name): str(cookie.value)} result['file'] = self._deliver_data(downloadUrl, cookies) for split in response.payload.deliveryResponse.appDeliveryData.split: a = { 'name': split.name, 'file': self._deliver_data(split.downloadUrl, None) } result['splits'].append(a) return result, appDetails
def search_component(self): search_url = f"{self.nexus_url}/service/rest/v1/search?repository={self.repo_name}&name={self.artifact_id}" \ f"&version={self.version}&group={self.group_id}" json_response = self.session.get(search_url, verify=False) component_search_result = json_response.json().get('items', {}) if component_search_result: Log.info( f'NexusRepo: Search length: {len(component_search_result)}') Log.info( f'NexusRepo: Successfully find component: {component_search_result}' ) return component_search_result[-1] else: Log.info( f'NexusRepo: Unable to find component in repository - {self.repo_name}, name - {self.artifact_id},' f' version - {self.version}&group_id={self.group_id}') return None
def download_app(self): SAPISIDHASH = self.calculate_sapisid_hash() url_template = f'https://firebaseappdistribution-pa.clients6.google.com/v1/projects/{self.project_id}' \ f'/apps/{self.app_id}/releases/{self.app_code}:getLatestBinary?alt=json&key={self.api_key}' headers = { 'Origin': self.url, 'X-Goog-Authuser': '******', 'Authorization': SAPISIDHASH } cookies = { 'SID': self.SID, 'HSID': self.HSID, 'SSID': self.SSID, 'APISID': self.APISID, 'SAPISID': self.SAPISID } req = requests.get(url_template, headers=headers, cookies=cookies) if req.status_code == 200: Log.info('Firebase - Start downloading application') elif req.status_code == 401: Log.info( f'Firebase - Failed to download application. ' f'Seems like you are not authorized. Request return status code: {req.status_code}' ) sys.exit(4) elif req.status_code == 403: Log.info( f'Firebase - Failed to download application. Seems like you dont have permissions for downloading.' f' Please contact your administrator. Request return status code: {req.status_code}' ) sys.exit(4) file_url = req.json().get('fileUrl', '') if not file_url: Log.info( 'It seems like Firebase API was changed or request was malformed. Please contact your administrator' ) sys.exit(4) app_file = requests.get(file_url, allow_redirects=True) if self.file_name is None: self.file_name = self.app_code path_to_file = f'{self.download_path}/{self.file_name}.{self.file_extension}' if not os.path.exists(self.download_path): os.mkdir(self.download_path) Log.info( f'Firebase - Creating directory {self.download_path} for downloading app from Firebase' ) with open(path_to_file, 'wb') as file: file.write(app_file.content) if os.path.exists(path_to_file): Log.info('Firebase - Application successfully downloaded') else: Log.info( 'Firebase - Failed to download application. ' 'Seems like something is wrong with your file path or app file is broken' ) return path_to_file
def login(self, email, password, gsfId, authSubToken): if email is not None and password is not None: Log.info( 'Google Play - Logging in with email and password, you should copy token after' ) encryptedPass = encrypt_password(email, password).decode('utf-8') params = self.deviceBuilder.getLoginParams(email, encryptedPass) params['service'] = 'ac2dm' params['add_account'] = '1' params['callerPkg'] = 'com.google.android.gms' headers = self.deviceBuilder.getAuthHeaders(self.gsfId) headers['app'] = 'com.google.android.gsm' with requests.Session() as s: s.headers = {'User-Agent': 'GoogleAuth/1.4'} response = s.post(AUTH_URL, data=params, verify=ssl_verify) data = response.text.split() params = {} for d in data: if "=" not in d: continue k, v = d.split("=", 1) params[k.strip().lower()] = v.strip() if params["auth"] != '': ac2dmToken = params["auth"] elif "error" in params: if "NeedsBrowser" in params["error"]: Log.error( 'Google Play - Security check is needed, ' 'try to visit https://accounts.google.com/b/0/DisplayUnlockCaptcha to unlock.' ) Log.error( f'Google Play - server says: "{params["error"]}"') sys.exit(4) self.gsfId = self.checkin(email, ac2dmToken) self.getAuthSubToken(email, encryptedPass) self.uploadDeviceConfig() Log.info( f'Google Play - gsfId: {self.gsfId}, authSubToken: {self.authSubToken}' ) Log.info( f'Google Play - You should copy these parameters and use them for next scans instead ' f'of email and password:'******'Google Play - "--google_play_gsfid {self.gsfId} --google_play_auth_token {self.authSubToken}"' ) elif gsfId is not None and authSubToken is not None: self.gsfId = gsfId self.setAuthSubToken(authSubToken) Log.info('Google Play - Logging in with gsfid and auth token') else: Log.error('Google Play - Login failed.') sys.exit(4)
def google_play_download(package_name, email=None, password=None, gsfId=None, authSubToken=None, file_name=None, download_with_creds=False): try: gp_api = GooglePlayAPI() Log.info('Google Play - Google Play integration, trying to login') gp_api.login(email, password, gsfId, authSubToken) if email is not None and password is not None and download_with_creds is False: sys.exit(0) else: download_path = 'downloaded_apps' downloaded_file, app_details = gp_api.download(package_name) if file_name is None: file_name = package_name app_version = app_details.get('versionString') path_to_file = f'{download_path}/{file_name}-v{app_version}.apk' Log.info('Google Play - Successfully logged in Play Store') Log.info(f'Google Play - Downloading {package_name} apk to {path_to_file}') if not os.path.exists(download_path): os.mkdir(download_path) Log.info(f'Google Play - Creating directory {download_path} for downloading app from Google Play Store') with open(path_to_file, 'wb') as file: for chunk in downloaded_file.get('file').get('data'): file.write(chunk) if os.path.exists(path_to_file): Log.info('Google Play - Application successfully downloaded!') else: Log.info('Google Play - Failed to download application. ' 'Seems like something is wrong with your file path or app file is broken') sys.exit(4) return path_to_file except Exception as e: Log.error(f'Google Play - Failed to download application. Seems like something goes wrong.' f' {e}') Log.info('Google Play - Try to reinitialize your account by logging in with your password and email') sys.exit(4)
def download_app(self): try: Store = StoreClient(self.sess) _login_iTunes(Store, self.apple_id, self.pass2FA) except StoreException as e: Log.error("Store %s failed! Message: %s%s" % (e.req, e.err_msg, " (errorType %s)" % e.err_type if e.err_type else '')) Log.info( 'Failed to download application. Seems like your credentials are incorrect ' 'or your 2FA code expired.') sys.exit(4) try: if self.app_id is None: Log.info( f'Trying to find app in App Store with bundle id {self.bundle_id}' ) found_by_bundle_resp = Store.find_app_by_bundle(self.bundle_id) resp_info = found_by_bundle_resp.json() if found_by_bundle_resp.status_code != 200 or resp_info[ 'resultCount'] != 1: Log.error( 'Application with your bundle id not found, probably you enter invalid bundle' ) sys.exit(4) app_info = resp_info['results'][0] Log.info( f'Successfully found application by bundle id ({self.bundle_id}) ' f'with name: "{app_info["trackName"]}", version: {app_info["version"]},' f' app_id: {app_info["trackId"]}') self.app_id = app_info["trackId"] Log.info(f'Trying to purchase app with id {self.app_id}') purchase_resp = Store.purchase(self.app_id) if purchase_resp.status_code == 200: Log.info( f'App was successfully purchased for {self.apple_id} account' ) elif purchase_resp.status_code == 500: Log.info( f'This app was purchased before for {self.apple_id} account' ) Log.info( f'Retrieving download info for app with id: {self.app_id}') download_resp = Store.download(self.app_id) if not download_resp.songList: Log.error( 'Failed to get app download info! Check your parameters') sys.exit(3) downloaded_app_info = download_resp.songList[0] app_name = downloaded_app_info.metadata.bundleDisplayName app_id = downloaded_app_info.songId app_bundle_id = downloaded_app_info.metadata.softwareVersionBundleId app_version = downloaded_app_info.metadata.bundleShortVersionString Log.info( f'Downloading app is {app_name} ({app_bundle_id}) with app_id {app_id} and version {app_version}' ) if self.appstore_file_name is None: file_name = '%s-%s.ipa' % (app_name, app_version) else: file_name = '%s-%s.ipa' % (self.appstore_file_name, app_version) file_path = os.path.join(self.download_path, file_name) Log.info(f'Downloading ipa to {file_path}') download_file(downloaded_app_info.URL, self.download_path, file_path) with zipfile.ZipFile(file_path, 'a') as ipa_file: Log.info('Creating iTunesMetadata.plist with metadata info') metadata = downloaded_app_info.metadata.as_dict() metadata["apple-id"] = self.apple_id metadata["userName"] = self.apple_id ipa_file.writestr( zipfile.ZipInfo("iTunesMetadata.plist", get_zipinfo_datetime()), plistlib.dumps(metadata)) appContentDir = [ c for c in ipa_file.namelist() if c.startswith('Payload/') and len(c.strip('/').split('/')) == 2 ][0] appContentDir = appContentDir.rstrip('/') scManifestData = ipa_file.read(appContentDir + '/SC_Info/Manifest.plist') scManifest = plistlib.loads(scManifestData) sinfs = {c.id: c.sinf for c in downloaded_app_info.sinfs} for i, sinfPath in enumerate(scManifest['SinfPaths']): ipa_file.writestr(appContentDir + '/' + sinfPath, sinfs[i]) except StoreException as e: Log.error("Store %s failed! Message: %s%s" % (e.req, e.err_msg, " (errorType %s)" % e.err_type if e.err_type else '')) Log.info( 'Failed to download application. Seems like your app_id does not exist or you did not purchase ' 'this app from apple account before.') sys.exit(4) return file_path
def _login_iTunes(Store, apple_id, pass2FA): Log.info('Logging into iTunes') Store.authenticate(apple_id, pass2FA) Log.info(f'Successfully logged in as {Store.account_name}')