Esempio n. 1
0
    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)
Esempio n. 2
0
    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
Esempio n. 3
0
    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
Esempio n. 4
0
 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)
Esempio n. 5
0
    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")
Esempio n. 6
0
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
Esempio n. 7
0
    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
Esempio n. 8
0
    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
Esempio n. 9
0
    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
Esempio n. 10
0
    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)
Esempio n. 12
0
    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
Esempio n. 13
0
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}')