mirror of
https://github.com/NohamR/pyzule-rw.git
synced 2026-10-10 18:39:41 +00:00
chore: python package
This commit is contained in:
152
cyan/tbhutils.py
Normal file
152
cyan/tbhutils.py
Normal file
@@ -0,0 +1,152 @@
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import zipfile
|
||||
import platform
|
||||
import plistlib
|
||||
import subprocess
|
||||
from glob import glob
|
||||
from argparse import Namespace
|
||||
from importlib import resources # type: ignore
|
||||
from typing import Optional, Any
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
|
||||
def validate_inputs(args: Namespace) -> Optional[str]:
|
||||
if not (
|
||||
args.i.endswith(".ipa")
|
||||
or args.i.endswith(".app")
|
||||
):
|
||||
return "the input file must be an ipa/app"
|
||||
|
||||
if not os.path.exists(args.i):
|
||||
return f"{args.i} does not exist"
|
||||
|
||||
if os.path.exists(args.o):
|
||||
try:
|
||||
overwrite = input(
|
||||
f"[<] {args.o} already exists, overwrite it? [Y/n] "
|
||||
if args.output is not None
|
||||
else "[<] no output was specified. overwrite the input? [Y/n] "
|
||||
).strip().lower()
|
||||
except KeyboardInterrupt:
|
||||
sys.exit("[>] bye!")
|
||||
|
||||
if overwrite not in ("y", "yes", ""):
|
||||
print("[>] quitting.")
|
||||
sys.exit(0)
|
||||
|
||||
if args.f is not None:
|
||||
# dictionary ensures unique names
|
||||
args.f = {os.path.basename(f): os.path.normpath(f) for f in args.f}
|
||||
nonexistent = [f for f in args.f.values() if not os.path.exists(f)]
|
||||
|
||||
if len(nonexistent) != 0:
|
||||
print("[!] please ensure the following file(s) exist:")
|
||||
for ne in nonexistent:
|
||||
print(f"[?] - {ne}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_app(path: str, tmpdir: str, is_ipa: bool) -> tuple[str, str]:
|
||||
payload = f"{tmpdir}/Payload"
|
||||
|
||||
if is_ipa:
|
||||
print("[*] extracting ipa..")
|
||||
|
||||
try:
|
||||
with zipfile.ZipFile(path) as ipa:
|
||||
names = ipa.namelist()
|
||||
|
||||
if not any(name.startswith("Payload/") for name in names):
|
||||
raise KeyError
|
||||
elif not any(name.endswith(".app/Info.plist") for name in names):
|
||||
sys.exit("[!] no Info.plist, invalid app")
|
||||
|
||||
ipa.extractall(tmpdir)
|
||||
app = glob(f"{payload}/*.app")[0]
|
||||
plist = f"{app}/Info.plist"
|
||||
except (KeyError, IndexError):
|
||||
sys.exit("[!] couldn't find either Payload or app folder, invalid ipa")
|
||||
except zipfile.BadZipFile:
|
||||
sys.exit(f"[!] {path} is not a zipfile (ipa)")
|
||||
|
||||
print("[*] extracted ipa")
|
||||
else:
|
||||
if not os.path.isfile((plist := f"{path}/Info.plist")):
|
||||
sys.exit("[!] no Info.plist, invalid app")
|
||||
|
||||
print("[*] copying app..")
|
||||
shutil.copytree(path, (app := f"{payload}/{os.path.basename(path)}"))
|
||||
print("[*] copied app")
|
||||
|
||||
return app, plist
|
||||
|
||||
|
||||
def get_tools_dir() -> tuple[str, str]:
|
||||
mach = platform.machine()
|
||||
system = platform.system()
|
||||
|
||||
if "iPhone" in mach or "iPad" in mach:
|
||||
mach = "arm64"
|
||||
|
||||
with resources.files() as files: # type: ignore
|
||||
return (
|
||||
str(files), # type: ignore
|
||||
str(files / "tools" / system / mach) # type: ignore
|
||||
)
|
||||
|
||||
|
||||
def get_plist(path: str) -> dict[str, Any]:
|
||||
try:
|
||||
with open(path, "rb") as f:
|
||||
return plistlib.load(f)
|
||||
except Exception:
|
||||
sys.exit(f"[!] couldn't read {path}")
|
||||
|
||||
|
||||
def delete_if_exists(path: str, bn: str) -> bool:
|
||||
is_file = os.path.isfile(path)
|
||||
|
||||
try:
|
||||
if is_file:
|
||||
os.remove(path)
|
||||
else:
|
||||
shutil.rmtree(path)
|
||||
|
||||
print(f"[?] {bn} already existed, replacing")
|
||||
return True
|
||||
except FileNotFoundError:
|
||||
return False
|
||||
|
||||
|
||||
def extract_deb(deb: str, tweaks: dict[str, str], tmpdir: str) -> None:
|
||||
with TemporaryDirectory(prefix=tmpdir + "/", delete=False) as t2:
|
||||
if platform.system() == "Linux":
|
||||
tool = ["ar", "-x", deb, f"--output={t2}"]
|
||||
else:
|
||||
tool = ["tar", "-xf", deb, f"--directory={t2}"]
|
||||
|
||||
try:
|
||||
subprocess.run(tool, check=True)
|
||||
except Exception:
|
||||
sys.exit(f"[!] couldn't extract {os.path.basename(deb)}")
|
||||
|
||||
# it's not always "data.tar.gz"
|
||||
data_tar = glob(f"{t2}/data.*")[0]
|
||||
subprocess.run(["tar", "-xf", data_tar, f"--directory={t2}"])
|
||||
|
||||
for hi in sum((
|
||||
glob(f"{t2}/**/*.dylib", recursive=True),
|
||||
glob(f"{t2}/**/*.bundle", recursive=True),
|
||||
glob(f"{t2}/**/*.appex", recursive=True),
|
||||
glob(f"{t2}/**/*.framework", recursive=True)
|
||||
), []): # type: ignore
|
||||
if os.path.islink(hi):
|
||||
continue # symlinks are broken iirc
|
||||
|
||||
tweaks[os.path.basename(hi)] = hi
|
||||
|
||||
print(f"[*] extracted {os.path.basename(deb)}")
|
||||
del tweaks[deb]
|
||||
|
||||
Reference in New Issue
Block a user