Skip to content

Instantly share code, notes, and snippets.

@thurask
Last active April 25, 2022 16:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thurask/8731c5913ca4572ce7d164526d6b2975 to your computer and use it in GitHub Desktop.
Save thurask/8731c5913ca4572ce7d164526d6b2975 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""Rip APKs en masse using ADB. Requires ADB debug connection to be set up before running!!!"""
import argparse
import os
import subprocess
def _get_device_info(tid):
devinfo = subprocess.run(["adb", "devices", "-l"], capture_output=True)
try:
devw = devinfo.stdout.rstrip().decode("utf-8").splitlines()[1:]
devz = [_ for _ in devw if "transport_id:{0}".format(tid) in _][0]
devx = devz.split(" device ")
except IndexError:
raise SystemExit("\nNO DEVICES FOUND!")
return devx
def get_device_info(tid):
devx = _get_device_info(tid)
preamble = "CONNECTED TO {0}\n\t{1}".format(devx[0].strip(), devx[1].strip())
return preamble
def list_packages(tid):
spr = subprocess.run(["adb", "-t", tid, "shell", "pm", "list", "packages"], capture_output=True)
pkgs = spr.stdout.split(b"\n")
pkgx = [_.replace(b"package:", b"").rstrip().decode("utf-8") for _ in pkgs if _]
return pkgx
def _list_path(inpkg, tid):
spr = subprocess.run(["adb", "-t", tid, "shell", "pm", "path", inpkg], capture_output=True)
pathx = spr.stdout.replace(b"package:", b"").splitlines()
pathz = [_.rstrip().decode("utf-8") for _ in pathx]
return pathz
def list_paths(inpkgs, tid):
pathsx = {_: _list_path(_, tid) for _ in inpkgs}
return pathsx
def _get_dumpsys(pkgname, tid):
dumpsys = subprocess.run(["adb", "-t", tid, "shell", "dumpsys", "package", pkgname], capture_output=True)
dumpsyx = [_.rstrip() for _ in dumpsys.stdout.splitlines()]
return dumpsyx
def _format_pkgname(pkgname, pkgpath, tid):
dumpsyx = _get_dumpsys(pkgname, tid)
tofind_1 = [_ for _ in dumpsyx if b"versionCode" in _][0].lstrip().decode("utf-8").split(" ")
tofind_2 = [_ for _ in dumpsyx if b"versionName" in _][0].lstrip().decode("utf-8")
tofind_3 = [_ for _ in dumpsyx if b"primaryCpuAbi" in _][0].lstrip().decode("utf-8")
tosplit = [_ for _ in dumpsyx if b"splits" in _][0].lstrip().decode("utf-8")
pkg_arch = tofind_3.split("=")[-1].replace("null", "noarch")
pkg_vername = tofind_2.split("=")[-1].replace(" ", "_")
pkg_vercode = tofind_1[0].split("=")[-1]
pkg_minsdk = tofind_1[1].split("=")[-1]
pkg_split = os.path.basename(pkgpath).replace(".apk", "")
pkg_splitname = "" if pkg_split == "base" else "_{0}".format(pkg_split)
apkname = "{0}_{1}-{2}_minAPI{3}({4}){5}.apk".format(pkgname, pkg_vername, pkg_vercode, pkg_minsdk, pkg_arch, pkg_splitname)
return apkname
def _pull_package(pkgname, pkgpaths, tid):
for pkgpath in pkgpaths:
locname = _format_pkgname(pkgname, pkgpath, tid)
if locname in os.listdir(os.getcwd()):
continue
elif "/overlay/" in pkgpath:
continue
else:
subprocess.run(["adb", "-t", tid, "pull", "-a", "-z", "any", pkgpath, os.path.join(os.getcwd(), locname)])
def pull_packages(indict, tid):
for pkgname, pkgpaths in indict.items():
_pull_package(pkgname, pkgpaths, tid)
def main():
parser = argparse.ArgumentParser(description="Rip APKs en masse using ADB.")
parser.add_argument("tid", nargs="?", default="1", help="transport id (adb devices -l), default=1")
args = parser.parse_args()
print("GETTING DEVICE INFO...", end="\r")
dvx = get_device_info(args.tid)
print("GETTING DEVICE INFO... done!")
print(dvx)
print("GETTING PACKAGE NAMES...", end="\r")
names = list_packages(args.tid)
print("GETTING PACKAGE NAMES... done!")
print("GETTING PACKAGE PATHS...", end="\r")
paths = list_paths(names, args.tid)
print("GETTING PACKAGE PATHS... done!")
print("PULLING PACKAGES...", end="\r")
pull_packages(paths, args.tid)
print("PULLING PACKAGES... done!")
print("COMPLETE!")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment