from dataclasses import dataclass
import os
import sys
import hashlib


@dataclass
class Patch:
    offset: int
    patch: bytes


@dataclass
class PatchItem:
    binary_name: str
    binary_path: str
    md5: str
    patches: list[Patch]


# include: metadata_codegen
METADATA: dict[str, PatchItem] = {
    "Entonal_Studio_APP": PatchItem(
        binary_name="Entonal Studio",
        binary_path="/Applications/Entonal Studio.app/Contents/MacOS/Entonal Studio",
        md5="15c08d1f94943ea0ed3f3a90bb1f32e5",
        patches=[
            Patch(offset=0x170A4EC, patch=b"\xfc\x00"),
            Patch(offset=0x170A4EF, patch=b"\x14"),
            Patch(offset=0x16AF854, patch=b"\x17\x00"),
            Patch(offset=0x16AF857, patch=b"\x14"),
            Patch(offset=0x16FCC8C, patch=b"F"),
            Patch(offset=0x16FCC8F, patch=b"\x14"),
        ],
    ),
    "Entonal_Studio_AU": PatchItem(
        binary_name="Entonal Studio",
        binary_path="/Library/Audio/Plug-Ins/Components/Entonal Studio.component/Contents/MacOS/Entonal Studio",
        md5="5f2827915d83ee9c1408e32754a5fa0e",
        patches=[
            Patch(offset=0x16DD3B4, patch=b"\xfc\x00"),
            Patch(offset=0x16DD3B7, patch=b"\x14"),
            Patch(offset=0x16833FC, patch=b"\x17\x00"),
            Patch(offset=0x16833FF, patch=b"\x14"),
            Patch(offset=0x16D0744, patch=b"F"),
            Patch(offset=0x16D0747, patch=b"\x14"),
        ],
    ),
    "Entonal_Studio_MIDIAPP": PatchItem(
        binary_name="Entonal Studio Midi Effect",
        binary_path="/Applications/Entonal Studio Midi Effect.app/Contents/MacOS/Entonal Studio Midi Effect",
        md5="521195c73f95a563ca9cb518ee9ecebc",
        patches=[
            Patch(offset=0x15A73E4, patch=b"\xfc\x00"),
            Patch(offset=0x15A73E7, patch=b"\x14"),
            Patch(offset=0x154AD98, patch=b"\x17\x00"),
            Patch(offset=0x154AD9B, patch=b"\x14"),
            Patch(offset=0x159675C, patch=b"F"),
            Patch(offset=0x159675F, patch=b"\x14"),
        ],
    ),
    "Entonal_Studio_MIDIAU": PatchItem(
        binary_name="Entonal Studio Midi Effect",
        binary_path="/Library/Audio/Plug-Ins/Components/Entonal Studio Midi Effect.component/Contents/MacOS/Entonal Studio Midi Effect",
        md5="c0899fb95f1672a7c20f6f86686f4ef8",
        patches=[
            Patch(offset=0x157CDF8, patch=b"\xfc\x00"),
            Patch(offset=0x157CDFB, patch=b"\x14"),
            Patch(offset=0x1521528, patch=b"\x17\x00"),
            Patch(offset=0x152152B, patch=b"\x14"),
            Patch(offset=0x156CD30, patch=b"F"),
            Patch(offset=0x156CD33, patch=b"\x14"),
        ],
    ),
    "Entonal_Studio_MIDIVST": PatchItem(
        binary_name="Entonal Studio Midi Effect",
        binary_path="/Library/Audio/Plug-Ins/VST/Entonal Studio Midi Effect.vst/Contents/MacOS/Entonal Studio Midi Effect",
        md5="d14ca6bb869949558b52453a901fda4a",
        patches=[
            Patch(offset=0x154AB08, patch=b"\xfc\x00"),
            Patch(offset=0x154AB0B, patch=b"\x14"),
            Patch(offset=0x14EEF7C, patch=b"\x17\x00"),
            Patch(offset=0x14EEF7F, patch=b"\x14"),
            Patch(offset=0x153A850, patch=b"F"),
            Patch(offset=0x153A853, patch=b"\x14"),
        ],
    ),
    "Entonal_Studio_VST": PatchItem(
        binary_name="Entonal Studio",
        binary_path="/Library/Audio/Plug-Ins/VST/Entonal Studio.vst/Contents/MacOS/Entonal Studio",
        md5="b369c71196803d5698e7aba9e022993c",
        patches=[
            Patch(offset=0x16AD380, patch=b"\xfc\x00"),
            Patch(offset=0x16AD383, patch=b"\x14"),
            Patch(offset=0x16530DC, patch=b"\x17\x00"),
            Patch(offset=0x16530DF, patch=b"\x14"),
            Patch(offset=0x16A0478, patch=b"F"),
            Patch(offset=0x16A047B, patch=b"\x14"),
        ],
    ),
    "Entonal_Studio_VST3": PatchItem(
        binary_name="Entonal Studio",
        binary_path="/Library/Audio/Plug-Ins/VST3/Entonal Studio.vst3/Contents/MacOS/Entonal Studio",
        md5="04d50f6d59b11affd7ad3b402bf9ae9a",
        patches=[
            Patch(offset=0x16EE2F0, patch=b"\xfc\x00"),
            Patch(offset=0x16EE2F3, patch=b"\x14"),
            Patch(offset=0x16940B0, patch=b"\x17\x00"),
            Patch(offset=0x16940B3, patch=b"\x14"),
            Patch(offset=0x16E13FC, patch=b"F"),
            Patch(offset=0x16E13FF, patch=b"\x14"),
        ],
    ),
}

print("Entonal Studio v1.2.5 Patcher by 0x24a")
print("Only for security research. Works for macOS arm64.")
print("Secondary modification/republication is prohibited.")
print()
if os.popen("whoami").read().strip() != "root":
    print("You must run this script as root.")
    print(f"Run: sudo python3 {sys.argv[0]}")
    exit(1)
for name, patch_item in METADATA.items():
    print(f"Patching component {name}...")
    if not os.path.exists(patch_item.binary_path) or not os.path.isfile(
        patch_item.binary_path
    ):
        print(
            f"\tBinary {patch_item.binary_path} not found or is not a file. Skipping."
        )
        continue
    print("\t1/5 Checking checksum")
    with open(patch_item.binary_path, "rb") as f:
        binary_hash = hashlib.md5(f.read()).hexdigest()
        if binary_hash != patch_item.md5:
            print(
                f"\tChecksum mismatch: expected {patch_item.md5}, got {binary_hash}. Skipping."
            )
            continue
    print("\t2/5 Backing up original binary")
    os.popen(
        f'sudo cp "{patch_item.binary_path}" "{patch_item.binary_path}.bak"'
    ).read()
    print("\t3/5 Applying patches")
    with open(patch_item.binary_path, "r+b") as f:
        for patch in patch_item.patches:
            f.seek(patch.offset)
            f.write(patch.patch)
    print("\t4/5 Running codesign")
    os.popen(f'sudo codesign -f -s - "{patch_item.binary_path}"').read()
    print("\t5/5 Done")
