#!/bin/bash # Requires ideviceinfo (libimobiledevice), pzb, jtool2, jq build_kernel_string () { # $1 = product type ie. iPhone12,1 # $2 = product version ie. 13.2.2 short_product_type=$(echo "$1" | sed 's/iPhone//g; s/iPad//g; s/,//g') short_product_version=$(echo "$2" | sed 's/\.//g') echo "$short_product_type-$short_product_version" } find_kernel_file() { # $1 = URL string # $2 = HardwareModel pzb -g BuildManifest.plist "$1" 1>/dev/null found_kernel_file="" ctr=0 while true; do plist_parse=$(plutil -extract BuildIdentities.$ctr.Info.DeviceClass xml1 -o - BuildManifest.plist) if [[ ! "$?" -eq "0" ]]; then break fi curr_id=$(echo $plist_parse | sed -n "s/.*\(.*\)<\/string>.*/\1/p" | tr [a-z] [A-Z]) kernel_file=$(plutil -extract BuildIdentities.$ctr.Manifest.KernelCache.Info.Path xml1 -o - BuildManifest.plist | sed -n "s/.*\(.*\)<\/string>.*/\1/p") if [[ "$2" == "$curr_id" ]]; then found_kernel_file=$kernel_file break fi ((ctr++)) done rm BuildManifest.plist if [[ "$found_kernel_file" == "" ]]; then echo "Failed to find kernel file from BuildManifest for model: $2" exit 1 fi echo "$found_kernel_file" } if [[ "$#" == "0" ]]; then echo "Usage: pullkernel [uuid] {version}" exit 0 fi target_uuid=$1 echo "Pulling kernel for $target_uuid..." device_info=$(ideviceinfo -u $target_uuid) if [[ "$device_info" == ERROR* ]]; then echo "Failed to find device with UUID $target_uuid!" exit 0 fi product_type=$(echo "$device_info" | grep ProductType | sed 's/ProductType: //g') device_name=$(echo "$device_info" | grep DeviceName | sed 's/DeviceName: //g') product_version=$(echo "$device_info" | grep ProductVersion | sed 's/ProductVersion: //g') build_version=$(echo "$device_info" | grep BuildVersion | sed 's/BuildVersion: //g') hardware_model=$(echo "$device_info" | grep HardwareModel | sed 's/HardwareModel: //g') if [[ "$#" == "2" ]]; then requested_version="$2" echo "Finding Build ID for requested version $requested_version..." all_ipsw_info=$(curl https://api.ipsw.me/v4/device/$product_type?type=ipsw 2>/dev/null) build_id=$(echo "$all_ipsw_info" | jq -r '.firmwares[] | select (.version == "'$requested_version'") | .buildid') echo "Found Build ID: $build_id" product_version="$requested_version" build_version="$build_id" fi kernel_string=$(build_kernel_string $product_type $product_version) echo "Device name: $device_name" echo "Product type: $product_type" echo "Product version: $product_version" echo "Build version: $build_version" echo "Kernel string: $kernel_string" final_kernel_path="/Users/ben/Desktop/kernels/$kernel_string" if [[ -e $final_kernel_path ]]; then echo "Kernel already found, exiting..." exit 0 fi # Download the kernel cd /tmp url_string="https://api.ipsw.me/v4/ipsw/download/$product_type/$build_version" echo "URL: $url_string" echo "Fetching files..." pzb_kernel_string=$(find_kernel_file $url_string $hardware_model) # pzb_kernel_string=$(pzb -l "$url_string" | grep kernelcache | tail -1 | cut -d' ' -f5) if [[ $(echo $pzb_kernel_string | wc -c) -lt 3 ]]; then echo "Failed to find kernel string." exit 0 fi echo "Pulling kernel file $pzb_kernel_string..." pzb -g $pzb_kernel_string $url_string if [[ ! -e $pzb_kernel_string ]]; then echo "Failed to download kernel file." exit 0 fi echo "Decompressing with jtool2..." jtool2 -dec $pzb_kernel_string if [[ ! -e kernel ]]; then echo "Failed to decompress kernel file." exit 0 fi mv kernel $final_kernel_path echo listdevices echo echo "Complete!"