def __init__(self, apk_name, source): self.apk_name = apk_name self.error = False self.source = source if self.source not in ["device", "playstore"]: self.error = True print_err("[-] Specify correct source to download from.") print "[*] Valid source options: \"device\" or \"playstore\""
def _get_destination_path(self, path, apk_name): if path.endswith(".apk"): dir_name, file_name = os.path.split(path) else: dir_name, file_name = path, apk_name + ".apk" if not dir_name.startswith("/"): dir_name = os.path.abspath(dir_name) if not os.path.exists(dir_name): print_err("[-] Given path does not esists. Trying to create.") os.mkdir(dir_name) return os.path.join(dir_name, file_name)
def __init__(self): # Overide credentials if present in .config config_file = os.path.expanduser("~") + '/.apk/gplaycreds.conf' if os.path.isfile(config_file): self.fail = False credentials = config_file self.configparser = ConfigParser.ConfigParser() self.configparser.read(credentials) self.config = dict() for key, value in self.configparser.items("Credentials"): self.config[key] = value self.verbose = True else: print_err("[-] Config file not found.") print "[*] Please put credentials.conf file here: %s" % config_file self.fail = True
def __init__(self, apk_path): self.expected_keystore_path = os.path.join(os.path.expanduser("~"), ".apk/keystore.jks") if os.path.isfile(apk_path): self.error = False self.apk_path = apk_path if os.path.isabs(apk_path): self.apk_path = apk_path else: self.apk_path = os.path.abspath(apk_path) self.signed = False else: print_err("[-] Couldn't find the specified APK file.") self.error = True for binary in ["keytool", "jarsigner"]: exit = os.system("type {} >/dev/null 2>&1".format(binary)) if exit != 0: print_err("[-] {} does not exists in system path. Please fix!". format(binary)) self.error = True
def decompile(self, destination): exit_code = os.system("type apk2java >/dev/null 2>&1") if exit_code != 0: print_err("[-] apk2java doesn't exist! Please install from: %s." % a2j_url) return if not os.path.exists(self.apk_path): print_err("[-] The APK file does not exist.") return print "[*] Proceeding now." if not destination: print "Using current directory as destination" destination = os.getcwd() if not destination.startswith("/"): # The path is not absolute, os.path.isabs checks the same thing. destination = os.path.abspath(destination) if not os.path.isdir(destination): print_err("[-] Destination does not exists. Exiting.") return log_file_name = ".".join([os.path.basename(self.apk_path), "log"]) log_file_path = os.path.join(destination, log_file_name) print "[*] Log file path: {}.".format(log_file_path) with open(log_file_path, "w") as out: command = shlex.split("apk2java {} {}".format(self.apk_path, destination)) process = subprocess.Popen(command, stdout=out, stderr=out) print "[*] Waiting for apk2java to finish." process.wait() expected_dir_name = "_".join([self.apk_path, "src"]) expected_dir_path = os.path.join(destination, expected_dir_name) if not os.path.exists(expected_dir_path): print_err("[-] Some error occured. Can't find source. Check logs - {}.".format(log_file_path)) else: print_success("[+] Please find the source here: {}".format(expected_dir_path))
def _download_from_playstore(self, destination): gplay = GPlayDownloader() if not gplay.fail: success, error = gplay.connect_to_googleplay_api() if not success: print_err("Cannot login to GooglePlay. {}".format(error)) return data = gplay.playstore_api.details(self.apk_name) doc = data.docV2 vc = doc.details.appDetails.versionCode if not doc: print_err("[-] Couldn't find details for the APK.") return if not doc.detailsUrl or not doc.title: print_err("[-] No APK found to be downloaded.") print "[*] Here's a search result for your query string.\n" nb_results = 10 gplay.search(list(), self.apk_name, nb_results) print "\n\n[*] Use the AppID from above result to download desired app." else: print "[+] Downloading APK: %s." % doc.title # Prepare destination path destination = self._get_destination_path( destination, self.apk_name) data = gplay.playstore_api.download(self.apk_name, vc, progress_bar=True) # file_name = destination + "/" + doc.docid + ".apk" # if destination.endswith(".apk"): # file_name = destination with open(destination, "w") as f: f.write(data) print_success("[+] APK file saved here - %s." % destination)
def sign(self): if self.error: return keystore_path = self.expected_keystore_path print "[*] The script will use {} by default if it exists.".format( self.expected_keystore_path) if not os.path.isfile(self.expected_keystore_path): print_err("[-] Default keystore doesn't exist.") choice = raw_input( "[*] Do you want to create keystore now? (yes/no): ") if "yes" in choice.lower(): if not self._gen_keystore(): print_err("[-] Failed to create keystore. Exiting.") return print_success("[+] Keystore generated for you.") else: choice = raw_input( "[*] Do you want to specify path to keystore? (yes/no): ") if "no" in choice: print_err("[-] No keystore selected. Exiting.") return else: user_keystore_path = raw_input( "[*] Enter keystore path: ").strip() if not os.path.isfile(user_keystore_path): print_err( "[-] Provided keystore file does not exist. Please, check again." ) return else: keystore_path = user_keystore_path else: keystore_path = self.expected_keystore_path print "[*] Using keystore store at - {}.".format(keystore_path) print "[*] Running zipalign on APK before signing." aligned_apk_path = self.zipalign() if aligned_apk_path: print_success("[+] APK zipalign'ed and saved as - {}".format( aligned_apk_path)) else: print_err("[-] Failed to zipalign APK. Exiting") return print "[*] Signing APK now." success = self._sign(keystore_path, aligned_apk_path) if success: print_success("[+] APK successfully signed.") print_success("[+] Please find the signed APK here: {}".format( aligned_apk_path)) else: print_err("[-] Failed to sign the APK.")
def _download_from_device(self, destination): exit_code, _ = commands.getstatusoutput("type adb >/dev/null 2>&1") if exit_code != 0: print_err("[-] adb doesn't exist! Please install.") return command = "adb shell pm list packages | grep -i %s" % self.apk_name status, output = commands.getstatusoutput(command) if status != 0: print_err( "[-] Error: adb failed to find packages with given string.") print_err("[-] Also check connection with device.") return apks = {} count = 0 for line in output.split("\n"): if line: if re.match("^package:", line): apks[count] = re.sub("^package:", "", line) count += 1 if count == 0: print_err("[-] No APK found. Exiting.") return print "[+] Found %d APK(s) with given string." % count print "[*] Please, select from the list below:" for i in xrange(count): print "\t[%d]: %s" % (i, apks[i]) while True: choice = int(input("[*] Enter a number: ")) if choice not in range(count): print_err("[-] Invalid choice.") continue break full_path_command = "adb shell pm path %s" % apks[choice] output = commands.getoutput(full_path_command.strip()) full_path = re.sub("^package:", "", output) print "[+] Pulling package from: %s." % full_path destination = _get_destination_path(destination, apks[choice]) pull_package_command = "adb pull %s %s" % (full_path.strip(), destination) status, output = commands.getstatusoutput(pull_package_command) if status == 0: print_success("[+] Pulled APK successfully. Find here: %s." % destination) else: print_err("[-] adb failed to pull package. Output below: ") print output