Skip to content

Instantly share code, notes, and snippets.

@miticollo
Last active July 28, 2024 10:06
Show Gist options
  • Save miticollo/12e3fff5ba8fab7dd707c874105a508f to your computer and use it in GitHub Desktop.
Save miticollo/12e3fff5ba8fab7dd707c874105a508f to your computer and use it in GitHub Desktop.
How to build frida-server (≥ 16.2.2) for iOS jailbroken devices

Here, I'll show you how to compile frida-server (≥ 16.2.2) for rootfull, rootless and RootHide jailbreaks.

Old Instructions

If you want to compile an old version of Frida (< 16.2.2) you can use my old guide.

Build Instructions

Requirements

macOS

macOS is required because you need to use Apple's proprietary software like Xcode, lipo, and codesign.

Warning

Before starting, read carefully up to the end.

Build

  1. Install the latest version of Xcode with command-line tools from the App Store. Without it, you won't have iPhoneOS SDKs.
  2. Download Xcode 11.7 directly from Apple at the following link: Xcode_11.7.xip. You will need to authenticate with your Apple ID to download it. Then set the following env:
    export XCODE11=/Applications/Xcode-11.7.app

Tip

To better manage multiple Xcode versions, you can use a CLI tool called xcodes. Alternatively, if you prefer an equivalent GUI app, you can use XcodesApp.

  1. Once downloaded, opening the .xip archive will begin extracting it. After extraction, rename the app to avoid conflicting with your primary installation of Xcode and move it to /Applications/ (e.g., mv Xcode.app /Applications/Xcode-11.7.app).
  2. Download this script, change gdb_codesign to frida-cert, and then run it.
  3. Run brew install dpkg to install dpkg-deb.

Note

To compile Frida I use gmake. If you don't want to install it you can use make shipped by Apple with Xcode Command Line Tools.

  1. Clone the frida-core project:
    git clone https://github.com/frida/frida-core.git
    cd frida-core
  2. (Optional) Check out the latest stable release:
    git checkout "$(git describe --tags "$(git rev-list --tags --max-count=1)")"
    To go back to origin/main, run git switch -.
  3. (Optional) Select your preferred Xcode version:
    export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer  
  4. Export the identity previously created in an enviroment variable called IOS_CERTID:
    export IOS_CERTID=frida-cert
  5. To package everything you must set the following env:
    gmake git-submodules
    FRIDA_VERSION=$(releng/frida_version.py)
    export FRIDA_VERSION
  6. (Optional) If you want to edit frida-server behaviour, you can do it now!

Warning

If you don't want to cross-compile Frida for rootfull remove it from for loop. But to compile RootHide rootless is always required!

  1. Build frida-server and frida-agent.dylib for 3 different architectures:
    mkdir -vp release-assets
    for jb in rootless rootfull; do
      for arch in arm64 arm64e arm64eoabi; do
        MESON_BUILD_ROOT="$(pwd)/build-${arch}-${jb}"
        export MESON_BUILD_ROOT
        if [ "${jb}" = "rootless" ]; then
          ./configure --prefix='/var/jb' --host=ios-"${arch}" --enable-server
        else
          ./configure --host=ios-"${arch}" --enable-server --with-devkits=core
        fi
        gmake -j$(($(/usr/sbin/sysctl -n hw.logicalcpu) + 1))
      done
      frida_ios_universal_path="$(pwd)/ios-${jb}-assets/$(if [ "${jb}" = "rootless" ]; then echo "var/jb/"; fi)"
      mkdir -vp "${frida_ios_universal_path}"/usr/{bin,lib/frida}/
      python ./releng/mkfatmacho.py "${frida_ios_universal_path}/usr/bin/frida-server" "$(pwd)/build-"{arm64,arm64e,arm64eoabi}"-${jb}/server/frida-server"
      codesign -vf -s "-" --preserve-metadata=entitlements "${frida_ios_universal_path}/usr/bin/frida-server"
      lipo "$(pwd)/build-"{arm64,arm64e}"-${jb}/lib/agent/frida-agent.dylib" -create -output "${frida_ios_universal_path}/usr/lib/frida/frida-agent.dylib"
      install_name_tool -id 'FridaAgent' "${frida_ios_universal_path}/usr/lib/frida/frida-agent.dylib"
      codesign -s "$IOS_CERTID" -fv --timestamp=none --generate-entitlement-der "${frida_ios_universal_path}/usr/lib/frida/frida-agent.dylib"
      arch=$(if [ "${jb}" = "rootless" ]; then echo "arm64"; else echo "arm"; fi)
      ./tools/package-server-fruity.sh "iphoneos-${arch}" "${frida_ios_universal_path}" release-assets/"frida_${FRIDA_VERSION}_iphoneos-${arch}.deb"
    done
    mkdir -vp "$(pwd)/ios-roothide-assets/var/jb/usr/"{bin,lib/frida}/
    cp -v "$(pwd)/ios-rootless-assets/var/jb/usr/bin/frida-server" "$(pwd)/ios-roothide-assets/var/jb/usr/bin/"
    cp -v "$(pwd)/ios-rootless-assets/var/jb/usr/lib/frida/frida-agent.dylib" "$(pwd)/ios-roothide-assets/var/jb/usr/lib/frida/"
    ./tools/package-server-fruity.sh "iphoneos-arm64e" "$(pwd)/ios-roothide-assets/var/jb/" release-assets/"frida_${FRIDA_VERSION}_iphoneos-arm64e.deb"

Note

To properly instrument all applications, all necessary architectures must be in place. For instance, to instrument Safari, the frida-agent.dylib for ARM64e is required. However, for Spotify, the required architecture is ARM64. If the frida-agent.dylib does not contain both slices, you will likely encounter an Incompatible Mach-O image error when using the frida CLI tool.
To check what I said, compare the output of the following two commands:

file /Applications/MobileSafari.app/MobileSafari
file /var/containers/Bundle/Application/<UUID>/Spotify.app/Spotify
  1. Check the release-assets/ directory to find your DEBs file. Enjoy!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment