Files
are/main.py
2026-07-09 14:00:11 +02:00

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()