Created
August 20, 2026 17:16
-
-
Save Forgo7ten/d0f2d495f329af4511a8dd5a6984cd06 to your computer and use it in GitHub Desktop.
frida-update-ios.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -Eeuo pipefail | |
| # | |
| # Frida version | |
| # | |
| FRIDA_VER="${1:-}" | |
| if [ -z "$FRIDA_VER" ]; then | |
| echo "Usage: $0 <frida-version>" | |
| echo "Example: $0 16.1.4" | |
| exit 1 | |
| fi | |
| # | |
| # Only allow reasonable Frida version strings. | |
| # | |
| # Prevent accidental path characters such as / or spaces, | |
| # especially because this script runs as root. | |
| # | |
| case "$FRIDA_VER" in | |
| *[!0-9A-Za-z._-]*) | |
| echo "[-] Invalid Frida version: $FRIDA_VER" | |
| exit 1 | |
| ;; | |
| esac | |
| # | |
| # Must be root | |
| # | |
| if [ "$(id -u)" -ne 0 ]; then | |
| echo "[-] This script must be run as root." | |
| exit 1 | |
| fi | |
| # | |
| # Dopamine / rootless paths | |
| # | |
| JBROOT="/var/jb" | |
| PLIST="${JBROOT}/Library/LaunchDaemons/re.frida.server.plist" | |
| BACKUP="${PLIST}.backup" | |
| SERVER="${JBROOT}/usr/sbin/frida-server" | |
| DEB="/tmp/frida_${FRIDA_VER}_iphoneos-arm64.deb" | |
| URL="https://github.com/frida/frida/releases/download/${FRIDA_VER}/frida_${FRIDA_VER}_iphoneos-arm64.deb" | |
| # | |
| # Confirm rootless environment | |
| # | |
| if [ ! -d "$JBROOT" ]; then | |
| echo "[-] ${JBROOT} does not exist." | |
| echo "[-] This does not look like a Dopamine/rootless environment." | |
| exit 1 | |
| fi | |
| # | |
| # Find rootless launchctl. | |
| # | |
| # Prefer the Procursus/rootless version if present. | |
| # | |
| if [ -x "${JBROOT}/bin/launchctl" ]; then | |
| LAUNCHCTL="${JBROOT}/bin/launchctl" | |
| elif command -v launchctl >/dev/null 2>&1; then | |
| LAUNCHCTL="$(command -v launchctl)" | |
| else | |
| echo "[-] launchctl not found." | |
| exit 1 | |
| fi | |
| echo "[*] Frida version : ${FRIDA_VER}" | |
| echo "[*] Jailbreak root: ${JBROOT}" | |
| echo "[*] launchctl : ${LAUNCHCTL}" | |
| echo | |
| # | |
| # ------------------------------------------------------------ | |
| # STEP 1 | |
| # | |
| # Download FIRST. | |
| # | |
| # Do not stop the currently working Frida until we know that | |
| # the new package has been downloaded successfully. | |
| # ------------------------------------------------------------ | |
| # | |
| echo "[*] Downloading Frida ${FRIDA_VER}..." | |
| rm -f "$DEB" | |
| if command -v curl >/dev/null 2>&1; then | |
| curl \ | |
| --fail \ | |
| --location \ | |
| --show-error \ | |
| --output "$DEB" \ | |
| "$URL" | |
| elif command -v wget >/dev/null 2>&1; then | |
| wget \ | |
| -O "$DEB" \ | |
| "$URL" | |
| else | |
| echo "[-] Neither curl nor wget is installed." | |
| exit 1 | |
| fi | |
| # | |
| # Basic download sanity check | |
| # | |
| if [ ! -s "$DEB" ]; then | |
| echo "[-] Download failed or downloaded file is empty." | |
| rm -f "$DEB" | |
| exit 1 | |
| fi | |
| echo "[+] Package downloaded:" | |
| ls -lh "$DEB" | |
| echo | |
| # | |
| # ------------------------------------------------------------ | |
| # STEP 2 | |
| # | |
| # Check existing plist | |
| # ------------------------------------------------------------ | |
| # | |
| HAD_OLD_PLIST=0 | |
| if [ -f "$PLIST" ]; then | |
| HAD_OLD_PLIST=1 | |
| echo "[*] Existing Frida plist found:" | |
| echo " $PLIST" | |
| # | |
| # Validate XML/plist before preserving it. | |
| # | |
| if command -v plutil >/dev/null 2>&1; then | |
| echo "[*] Checking existing plist..." | |
| if ! plutil -lint "$PLIST"; then | |
| echo "[-] Existing plist is invalid." | |
| echo "[-] Aborting before changing anything." | |
| rm -f "$DEB" | |
| exit 1 | |
| fi | |
| fi | |
| else | |
| echo "[!] Existing Frida plist not found." | |
| echo "[!] The plist provided by the new package will be used." | |
| fi | |
| echo | |
| # | |
| # ------------------------------------------------------------ | |
| # STEP 3 | |
| # | |
| # Backup customized plist | |
| # ------------------------------------------------------------ | |
| # | |
| if [ "$HAD_OLD_PLIST" -eq 1 ]; then | |
| echo "[*] Backing up existing plist..." | |
| rm -f "$BACKUP" | |
| cp -p \ | |
| "$PLIST" \ | |
| "$BACKUP" | |
| if [ ! -f "$BACKUP" ]; then | |
| echo "[-] Failed to create plist backup." | |
| rm -f "$DEB" | |
| exit 1 | |
| fi | |
| echo "[+] Backup created:" | |
| echo " $BACKUP" | |
| fi | |
| echo | |
| # | |
| # ------------------------------------------------------------ | |
| # Recovery function | |
| # | |
| # If something fails after this point, try to put the old | |
| # plist back and start Frida again. | |
| # ------------------------------------------------------------ | |
| # | |
| RECOVERY_REQUIRED=1 | |
| recover() | |
| { | |
| EXIT_CODE=$? | |
| if [ "$RECOVERY_REQUIRED" -eq 0 ]; then | |
| return | |
| fi | |
| echo | |
| echo "[-] Update failed." | |
| echo "[*] Attempting recovery..." | |
| # | |
| # Stop whatever Frida package may have started. | |
| # | |
| if [ -f "$PLIST" ]; then | |
| "$LAUNCHCTL" unload "$PLIST" 2>/dev/null || true | |
| fi | |
| # | |
| # Restore previous plist. | |
| # | |
| if [ -f "$BACKUP" ]; then | |
| echo "[*] Restoring previous plist..." | |
| mv -f \ | |
| "$BACKUP" \ | |
| "$PLIST" | |
| chown root:wheel "$PLIST" 2>/dev/null || true | |
| chmod 644 "$PLIST" 2>/dev/null || true | |
| echo "[*] Reloading previous Frida service..." | |
| "$LAUNCHCTL" load "$PLIST" 2>/dev/null || true | |
| fi | |
| rm -f "$DEB" | |
| echo "[-] Recovery finished." | |
| exit "$EXIT_CODE" | |
| } | |
| trap recover ERR INT TERM | |
| # | |
| # ------------------------------------------------------------ | |
| # STEP 4 | |
| # | |
| # Stop current Frida | |
| # ------------------------------------------------------------ | |
| # | |
| if [ "$HAD_OLD_PLIST" -eq 1 ]; then | |
| echo "[*] Stopping existing Frida service..." | |
| # | |
| # unload returns an error when the service isn't currently | |
| # loaded, which is harmless for an upgrade. | |
| # | |
| "$LAUNCHCTL" unload "$PLIST" 2>/dev/null || true | |
| fi | |
| # | |
| # Extra safety: terminate a leftover frida-server only if | |
| # launchctl didn't stop it. | |
| # | |
| sleep 1 | |
| echo "[*] Current Frida processes:" | |
| ps aux | grep '[f]rida-server' || true | |
| echo | |
| # | |
| # ------------------------------------------------------------ | |
| # STEP 5 | |
| # | |
| # Install new Frida | |
| # ------------------------------------------------------------ | |
| # | |
| echo "[*] Installing Frida ${FRIDA_VER}..." | |
| dpkg -i "$DEB" | |
| echo "[+] dpkg completed." | |
| echo | |
| # | |
| # ------------------------------------------------------------ | |
| # STEP 6 | |
| # | |
| # Verify server binary | |
| # ------------------------------------------------------------ | |
| # | |
| if [ ! -x "$SERVER" ]; then | |
| echo "[-] Installation completed but frida-server was not found:" | |
| echo " $SERVER" | |
| false | |
| fi | |
| echo "[*] Installed frida-server:" | |
| echo " $SERVER" | |
| echo "[*] Installed version:" | |
| "$SERVER" --version | |
| echo | |
| # | |
| # ------------------------------------------------------------ | |
| # STEP 7 | |
| # | |
| # Restore customized plist | |
| # ------------------------------------------------------------ | |
| # | |
| if [ "$HAD_OLD_PLIST" -eq 1 ]; then | |
| echo "[*] Restoring customized plist..." | |
| # | |
| # dpkg may have installed a new plist and may even have | |
| # started Frida automatically. | |
| # | |
| # Stop that instance before restoring our configuration. | |
| # | |
| "$LAUNCHCTL" unload "$PLIST" 2>/dev/null || true | |
| mv -f \ | |
| "$BACKUP" \ | |
| "$PLIST" | |
| chown root:wheel "$PLIST" 2>/dev/null || true | |
| chmod 644 "$PLIST" | |
| fi | |
| # | |
| # Validate the final plist. | |
| # | |
| if command -v plutil >/dev/null 2>&1; then | |
| echo "[*] Checking final plist..." | |
| plutil -lint "$PLIST" | |
| fi | |
| # | |
| # ------------------------------------------------------------ | |
| # STEP 8 | |
| # | |
| # Start Frida | |
| # ------------------------------------------------------------ | |
| # | |
| echo "[*] Starting Frida..." | |
| # | |
| # In case the package already loaded it. | |
| # | |
| "$LAUNCHCTL" unload "$PLIST" 2>/dev/null || true | |
| "$LAUNCHCTL" load "$PLIST" | |
| # | |
| # Give launchd a moment. | |
| # | |
| sleep 1 | |
| # | |
| # ------------------------------------------------------------ | |
| # STEP 9 | |
| # | |
| # Verify | |
| # ------------------------------------------------------------ | |
| # | |
| echo | |
| echo "[*] Checking frida-server process..." | |
| if ps aux | grep '[f]rida-server'; then | |
| echo | |
| echo "[+] frida-server is running." | |
| else | |
| echo | |
| echo "[-] frida-server does not appear to be running." | |
| false | |
| fi | |
| # | |
| # Everything succeeded. | |
| # | |
| RECOVERY_REQUIRED=0 | |
| trap - ERR INT TERM | |
| # | |
| # Cleanup | |
| # | |
| rm -f "$DEB" | |
| # | |
| # Backup is temporary; the original plist is already restored. | |
| # | |
| rm -f "$BACKUP" | |
| echo | |
| echo "========================================" | |
| echo "[+] Frida update completed successfully" | |
| echo "========================================" | |
| echo | |
| echo "Version:" | |
| "$SERVER" --version |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment