209 lines
5.6 KiB
Python
209 lines
5.6 KiB
Python
import argparse
|
|
import adbutils
|
|
import sys
|
|
from pathlib import Path
|
|
import os
|
|
import tomllib
|
|
import tomli_w
|
|
import subprocess
|
|
|
|
def rip(config, d):
|
|
# packages = [x.removeprefix("package:") for x in d.shell("pm list packages -e").splitlines() if "package:" in x]
|
|
# if args.package not in packages:
|
|
# sys.exit("Could not find your package!")
|
|
|
|
package = config["package"]
|
|
|
|
version_name = [x.strip().removeprefix("versionName=") for x in d.shell(f"pm dump {package}").splitlines() if x.strip().startswith("versionName")]
|
|
if len(version_name) == 0:
|
|
sys.exit(f"Could not find package {package}")
|
|
|
|
if len(version_name) > 1:
|
|
sys.exit(f"Found multiple version names: {", ".join(version_name)}")
|
|
|
|
version_name = version_name[0]
|
|
|
|
print(f"Ripping {package} v{version_name}")
|
|
|
|
files = [x.removeprefix("package:") for x in d.shell(f"pm path {package}").splitlines()]
|
|
|
|
dump_path = Path(version_name) / "_original"
|
|
os.makedirs(dump_path, exist_ok=True)
|
|
|
|
for file in files:
|
|
file_base = file.split("/")[-1]
|
|
print(f"Downloading {file_base} ... ", end="", flush=True)
|
|
d.sync.pull(file, dump_path / file_base)
|
|
print(f"✅")
|
|
|
|
|
|
def decompile(config):
|
|
apk_path = Path("_original")
|
|
if not os.path.isdir(apk_path):
|
|
sys.exit("Could not find original APKs in this folder. Did you run 'are rip'?")
|
|
|
|
apks = os.listdir(apk_path)
|
|
if not "base.apk" in apks:
|
|
sys.exit("Could not find base.apk")
|
|
|
|
subprocess.call(["apktool.bat", "d", apk_path / "base.apk", "-o", "src/base"])
|
|
|
|
def build(config):
|
|
source_dir = Path("src")
|
|
if not os.path.isdir(source_dir):
|
|
sys.exit("Could not find decompiled sources")
|
|
|
|
out_dir = Path("_dist")
|
|
sources = os.listdir(source_dir)
|
|
for source in sources:
|
|
subprocess.call(["apktool.bat", "b", source_dir / source, "-o", out_dir / f"{source}.apk"])
|
|
|
|
def sign(config):
|
|
originals_path = Path("_original")
|
|
unsigned_path = Path("_dist")
|
|
|
|
if not os.path.isdir(originals_path):
|
|
sys.exit("Could not find original APKs")
|
|
|
|
if not os.path.isdir(unsigned_path):
|
|
sys.exit("Could not find unsigned dist APKs. Did you run 'are build' yet?")
|
|
|
|
originals_apks = os.listdir(originals_path)
|
|
unsigned_apks = os.listdir(unsigned_path)
|
|
all_apks = list(set(originals_apks).union(set(unsigned_apks)))
|
|
|
|
|
|
apk_paths = []
|
|
for apk in all_apks:
|
|
if apk in unsigned_apks:
|
|
apk_paths.append(unsigned_path / apk)
|
|
else:
|
|
apk_paths.append(originals_path / apk)
|
|
|
|
command_apks = [ii for i in zip(["-a" for x in range(len(apk_paths))], apk_paths) for ii in i ]
|
|
print(*command_apks)
|
|
subprocess.run(["uber-apk-signer.bat", "--allowResign", *command_apks, "-o", Path("_signed")])
|
|
|
|
def install(config, d):
|
|
signed_path = Path("_signed")
|
|
signed_apks = [signed_path / x for x in os.listdir(signed_path) if x.endswith(".apk")]
|
|
|
|
subprocess.run(["adb", "install-multiple", "-f", *signed_apks])
|
|
|
|
def init(args):
|
|
config_path = Path("are.toml")
|
|
|
|
if os.path.exists(config_path.absolute()):
|
|
sys.exit("A are.toml config file already exists here")
|
|
|
|
project_data = {
|
|
"package": args.package
|
|
}
|
|
|
|
with open(config_path.absolute(), "wb+") as f:
|
|
tomli_w.dump(project_data, f)
|
|
|
|
print("Project initialized!")
|
|
|
|
def find_config():
|
|
project_path = Path(".").absolute()
|
|
for i in range(2):
|
|
config_path = project_path / "are.toml"
|
|
if os.path.isfile(config_path):
|
|
with open(config_path, "rb") as f:
|
|
return (project_path, tomllib.load(f))
|
|
else:
|
|
project_path = project_path.parent
|
|
|
|
sys.exit("Could not find project file 'are.toml'. Please run 'are init'")
|
|
|
|
|
|
def check():
|
|
try:
|
|
apktool = subprocess.run(["apktool.bat", "--version"], stdout=subprocess.DEVNULL)
|
|
except Exception as e:
|
|
print(e)
|
|
sys.exit("apktool not found")
|
|
|
|
try:
|
|
apktool = subprocess.run(["uber-apk-signer.bat", "--version"], stdout=subprocess.DEVNULL)
|
|
except Exception as e:
|
|
print(e)
|
|
sys.exit("uber-apk-signer not found")
|
|
|
|
print("✅ All good!")
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
prog='are',
|
|
description='Android Reverse Engineering Shortcuts',
|
|
)
|
|
|
|
subparsers = parser.add_subparsers(dest='command', required=True)
|
|
|
|
# -- check command
|
|
check_parser = subparsers.add_parser('check')
|
|
|
|
# -- init command
|
|
init_parser = subparsers.add_parser('init')
|
|
init_parser.add_argument("package", help="The name of the package")
|
|
|
|
# -- rip command
|
|
rip_parser = subparsers.add_parser('rip')
|
|
|
|
# -- decompile
|
|
decompile_parser = subparsers.add_parser("decompile")
|
|
|
|
# -- build
|
|
build_parser = subparsers.add_parser("build")
|
|
|
|
|
|
# -- sign command
|
|
sign_parser = subparsers.add_parser('sign')
|
|
|
|
# -- install command
|
|
install_parser = subparsers.add_parser('install')
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
if args.command == "check":
|
|
check()
|
|
return
|
|
|
|
config = None
|
|
path = None
|
|
if args.command == "init":
|
|
init(args)
|
|
else:
|
|
path, config = find_config()
|
|
|
|
|
|
if args.command == "decompile":
|
|
decompile(config)
|
|
return
|
|
elif args.command == "build":
|
|
build(config)
|
|
return
|
|
elif args.command == "sign":
|
|
sign(config)
|
|
return
|
|
|
|
|
|
|
|
adb = adbutils.AdbClient(host="127.0.0.1", port=5037)
|
|
d = adb.device()
|
|
|
|
if args.command == "rip":
|
|
rip(config, d)
|
|
|
|
elif args.command == "install":
|
|
install(config, d)
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|