#!/usr/bin/env bash export LANG=C export LC_CTYPE=C export LC_ALL=C # This variable is used as a command. Set it to either true or false. It's case-sensitive. debug=false iOS12_usrlib=( "libDHCPServer.dylib" "libMatch.dylib" "libSystem.B_asan.dylib" "libSystem.dylib" "libSystem_asan.dylib" "libarchive.dylib" "libbsm.dylib" "libbz2.1.0.5.dylib" "libbz2.dylib" "libc++.dylib" "libc.dylib" "libcharset.dylib" "libcurses.dylib" "libdbm.dylib" "libdl.dylib" "libeasyperf.dylib" "libedit.2.dylib" "libedit.3.0.dylib" "libedit.dylib" "libexslt.dylib" "libextension.dylib" "libform.dylib" "libiconv.2.4.0.dylib" "libiconv.dylib" "libicucore.dylib" "libinfo.dylib" "libipsec.dylib" "liblzma.dylib" "libm.dylib" "libmecab.dylib" "libncurses.5.dylib" "libncurses.dylib" "libobjc-trampolines.dylib" "libobjc.dylib" "libpcap.dylib" "libpmsample.dylib" "libpoll.dylib" "libproc.dylib" "libpthread.dylib" "libresolv.dylib" "librpcsvc.dylib" "libsandbox.dylib" "libsqlite3.0.dylib" "libstdc++.6.0.9.dylib" "libstdc++.dylib" "libtidy.dylib" "libutil1.0.dylib" "libxml2.dylib" "libxslt.dylib" "libz.1.1.3.dylib" "libz.1.2.11.dylib" "libz.1.2.5.dylib" "libz.1.2.8.dylib" "libz.dylib" "log" "system" "updaters" "xpc" "libz.1.dylib" "libxslt.1.dylib" "libxml2.2.dylib" "libutil.dylib" "libtidy.A.dylib" "libstdc++.6.dylib" "libsqlite3.dylib" "libsandbox.1.dylib" "libresolv.9.dylib" "libpcap.A.dylib" "libobjc.A.dylib" "libncurses.5.4.dylib" "libmecab_em.dylib" "liblzma.5.dylib" "libipsec.A.dylib" "libicucore.A.dylib" "libiconv.2.dylib" "libform.5.4.dylib" "libexslt.0.dylib" "libedit.3.dylib" "libperfcheck.dylib" "libcharset.1.0.0.dylib" "libcharset.1.dylib" "libc++.1.dylib" "libbz2.1.0.dylib" "libbsm.0.dylib" "libarchive.2.dylib" "libSystem.B.dylib" "libMatch.1.dylib" "libDHCPServer.A.dylib" "libCRFSuite.dylib" "FDRSealingMap.plist" "bbmasks" "dyld" "libCRFSuite0.12.dylib" ) dylib_folders=( "/Library/MobileSubstrate/DynamicLibraries" "/usr/lib" ) sed_stdout() { printf "$2" | sed -e "$1" } sed_file() { sed -i "" "$1" "$2" 2&> /dev/null printf "$2" } patch_strings() { [ $# -lt 2 ] && return 1 sed="" result="$2" if [ "$1" == "-r" ]; then sed="sed_stdout" elif [ "$1" == "-f" ]; then sed="sed_file" else return 1; fi result="$(${sed} 's/\/Library\//\/var\/LIB\//g' "${result}")" result="$(${sed} 's/\/System\/var\/LIB\//\/System\/Library\//g' "${result}")" result="$(${sed} 's/%@\/var\/LIB\//%@\/Library\//g' "${result}")" result="$(${sed} 's/mobile\/var\/LIB\//mobile\/Library\//g' "${result}")" # The trick: # 1. Replace every "/usr/lib" with "/var/lib" # 2. Iterate over iOS12_usrlib and revert the system libraries # This way, we only need to hardcode the system libraries which will never change. We won't need to hardcode the libraries that are for jailbroken devices. result="$(${sed} 's/\/usr\/lib\//\/var\/ulb\//g' "${result}")" if [ $? -eq 0 ]; then for usr_lib_system_file in "${iOS12_usrlib[@]}"; do escaped_dot='\.' escaped_file="${usr_lib_system_file//./${escaped_dot}}" expression='s/\/var\/ulb\/'"${escaped_file}"'/\/usr\/lib\/'"${escaped_file}"'/g' result="$(${sed} "${expression}" "${result}")" done fi [ "$1" == "-r" ] && printf "${result}" return 0; } patch_file() { [ ! -z "$1" ] || [ -e "$1" ] || return file="$1" if [ -h "${file}" ]; then link="$(readlink -n "${file}")" [ -z "${link}" ] && return 1 echo "[*] Patching symbolic link: \"${file}\"" echo "[i] Old target: ${link}" link="$(patch_strings -r ${link})" echo "[i] New target: ${link}" rm "${file}" ln -s "${link}" "${file}" elif [ -x "${file}" ]; then # When link identity editor fails, it usually means the file is not a valid binary. ldid -S "${file}" 2> /dev/null || return 1 echo "[*] Patching executable: \"${file}\"" patch_strings -f "${file}" || { echo "[-] Failed to patch executable" return 1 } # Sign the binary again, just in case ldid -S "${file}" elif ${debug}; then echo "[D] Nothing to patch." fi } #### Main script #### if [ $# -lt 2 ]; then cat <<'EOF' Patch a deb: patcher [output deb] Patch files: patcher --patch Set "output deb" to "-" in order to create a deb at the same place as the output folder. EOF exit 127 fi if [ "$1" == "--patch" ]; then for (( i=2; i<=$#; i++ )); do file="${@:$i:1}" ${debug} && echo "${file}" [ ! -z "${file}" ] && [ ! -d "${file}" ] && patch_file "${file}" done exit 0 fi echo "[*] Extracting deb" dpkg-deb -R "$1" "$2" || exit $? [ ! -d "$2" ] && { echo "[-] Could not find the extracted directory" exit 2 } find "$2" -exec "$0" "--patch" "{}" \; <<'NOT_TESTED' for i in $2/Applications/*.app do ldid -e $i > /tmp/_ENTS.plist 2> /dev/null if [ $(cat /tmp/_ENTS.plist) == "" ]; then printf 'platform-applicationcom.apple.private.security.no-containercom.apple.private.security.container-required' > /tmp/_ENTS.plist ldid -S/tmp/_ENTS.plist $2 2> /dev/null elif [[ ! $(cat /tmp/_ENTS.plist) == "*com.apple.private.security.container-required*" ]]; then sed -i ':a;N;$!ba;s/<\/dict>\n<\/plist>/com.apple.private.security.container-required<\/key><\/dict>\n<\/plist>/g' /tmp/_ENTS.plist ldid -S/tmp/_ENTS.plist $2 2> /dev/null fi done NOT_TESTED if [ ! -z "$3" ]; then type -p dpkg-deb 2&> /dev/null || { echo "[-] Not creating a patched deb. Install DPKG from Homebrew and try again." exit 1 } echo "[*] Creating a patched deb..." file="$3" [ "$3" == "-" ] && file="$2.deb" dpkg-deb -Znone -b "$2" "${file}" exit $? fi exit 0