Created
September 9, 2022 20:39
-
-
Save NikolaRusakov/73a21f7391b6a309232ea40772ede269 to your computer and use it in GitHub Desktop.
Revisions
-
NikolaRusakov created this gist
Sep 9, 2022 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,1391 @@ #!/bin/bash # RUP Review every time when new verison update part. # Latest supported version latestVersion="v71.2" # Support version list. declare -a version_list # RUP Review every time when new verison update part. # Address parameter array and other parameters for each version. # Version 53 declare -a address_param_513 version_list+=("51.3") address_param_513+=("3bc0e7") address_param_513+=("3bab6d") address_param_513+=("3bacbc") exe_hash_513="21aed0fe8e29e9eaf9a1194b316ae6ee0ec342f7" # Version 53 declare -a address_param_530 version_list+=("53") address_param_530+=("4143c2") address_param_530+=("412f2d") address_param_530+=("413079") address_param_530+=("4d2f09") exe_hash_530="f8a7efc0814bbd26c591dcb8b2922cdf17016c04" # Version 58 declare -a address_param_580 version_list+=("58") address_param_580+=("3912bf") address_param_580+=("3912c2") address_param_580+=("38ff2e") address_param_580+=("39007d") exe_hash_580="5669dd6d7452a96ac3523ea8fa1a41d9ce70f50f" # Version 63.1 declare -a address_param_631 version_list+=("63.1") address_param_631+=("4a2a4f") address_param_631+=("4a2a52") address_param_631+=("4a173a") address_param_631+=("4a1879") exe_hash_631="db9b88f3aa6abc484be104660fa911275d9f2515" # Version 64 declare -a address_param_640 version_list+=("64") address_param_640+=("4cde6f") address_param_640+=("4cde72") address_param_640+=("4ccb5a") address_param_640+=("4ccc99") exe_hash_640="a4d16224ebb8caf84c94a6863db183fd306002da" # Version 65.1 declare -a address_param_651 version_list+=("65.1") address_param_651+=("4db4ff") address_param_651+=("4db502") address_param_651+=("4da1ea") address_param_651+=("4da329") exe_hash_651="0e7cad9b81284d127d652b3a8c962315770cd905" # Version 66.1 declare -a address_param_661 version_list+=("66.1") address_param_661+=("4f374f") address_param_661+=("4f3752") address_param_661+=("4f243a") address_param_661+=("4f2579") exe_hash_661="97d6273be93546a9b3caa7c8e1f97fe2246e673b" # Version 67 & 67.1 declare -a address_param_670 version_list+=("67") address_param_670+=("50a6cf") address_param_670+=("50a6d2") address_param_670+=("5093aa") address_param_670+=("5094e9") exe_hash_670="b9866183ded9573aea6be0a004f31c8941059f3f" version_list+=("67.1") exe_hash_671="708e9203a8628c5cee767eb75546c6145b69df57" # Version 67.2 declare -a address_param_672 version_list+=("67.2") address_param_672+=("50a78f") address_param_672+=("50a792") address_param_672+=("50946a") address_param_672+=("5095a9") exe_hash_672="9762906ced4d5589e27b297012ce862665e65a29" # Version 68 declare -a address_param_680 version_list+=("68") address_param_680+=("54d2af") address_param_680+=("54d2b2") address_param_680+=("54bf8a") address_param_680+=("54c0c9") exe_hash_680="ad9ccdce3ac270b2441f0efb8f3233935fb1900a" # Version 68.1 & 68.2 declare -a address_param_681 version_list+=("68.1") address_param_681+=("54d34f") address_param_681+=("54d352") address_param_681+=("54c02a") address_param_681+=("54c169") exe_hash_681="bc22987f7b3a7580aba1ac260c59d66d0a3622e7" version_list+=("68.2") exe_hash_682="651f3263305e004133253c2706fcdf5b16e20558" # Version 69 declare -a address_param_690 version_list+=("69") address_param_690+=("5cf76f") address_param_690+=("5cf772") address_param_690+=("5ce44a") address_param_690+=("5ce589") exe_hash_690="2d4027890e2b72175c4a562f59c5d1adb2655b8c" # Version 69.1 & 69.2 declare -a address_param_691 version_list+=("69.1") address_param_691+=("5d09df") address_param_691+=("5d09e2") address_param_691+=("5cf57e") address_param_691+=("5cf6ae") exe_hash_691="4ce06aa34c40040244c60608a02c152186f23c32" version_list+=("69.2") exe_hash_692="a7ba7ddf8e15e1e03ae88c00ab5070dabecc06b2" # Version 70.2 declare -a address_param_702 version_list+=("70.2") address_param_702+=("5861bf") address_param_702+=("5861c2") address_param_702+=("584e0e") address_param_702+=("584f3e") address_param_702+=("66d03f") address_param_702+=("66d04f") address_param_702+=("dcd72c") address_param_702+=("dcd730") address_param_702+=("dcc3a4") address_param_702+=("dcc4c7") address_param_702+=("ed1031") address_param_702+=("ed1041") exe_hash_702="e3376ad6f58bdf1e24306bf6d94ee67b082a94db" # Version 70.3 declare -a address_param_703 version_list+=("70.3") address_param_703+=("58619f") address_param_703+=("5861a2") address_param_703+=("584dee") address_param_703+=("584f1e") address_param_703+=("66d058") address_param_703+=("66d068") address_param_703+=("dcd574") address_param_703+=("dcd578") address_param_703+=("dcc1ec") address_param_703+=("dcc30f") address_param_703+=("ed0fd7") address_param_703+=("ed0fe7") exe_hash_703="9a0e6b7721c275b75e1fb6b70b55cda7ab99c4a8" # Version 70.4 declare -a address_param_704 version_list+=("70.4") address_param_704+=("58606f") address_param_704+=("586072") address_param_704+=("584cbe") address_param_704+=("584dee") address_param_704+=("66cffb") address_param_704+=("66d00b") address_param_704+=("dcd484") address_param_704+=("dcd488") address_param_704+=("dcc0fc") address_param_704+=("dcc21f") address_param_704+=("ed0fa5") address_param_704+=("ed0fb5") exe_hash_704="6adf7ee4c29bb1a61739b8804c7ce6d94c791f36" # Version 70.5 & 70.6 declare -a address_param_705 version_list+=("70.5") address_param_705+=("585eef") address_param_705+=("585ef2") address_param_705+=("584b3e") address_param_705+=("584c6e") address_param_705+=("66ce63") address_param_705+=("66ce73") address_param_705+=("dcd404") address_param_705+=("dcd408") address_param_705+=("dcc07c") address_param_705+=("dcc19f") address_param_705+=("ed0fbc") address_param_705+=("ed0fcc") exe_hash_705="2f1f2fff46d692f2ffe67cec150da4d5d67218eb" version_list+=("70.6") exe_hash_706="33d438d86cbb81bf945f30d0906395522680a03f" # Version 71.1 declare -a address_param_711 version_list+=("71.1") address_param_711+=("5d904f") address_param_711+=("5d9052") address_param_711+=("5d7c9e") address_param_711+=("5d7dce") address_param_711+=("6cb001") address_param_711+=("6cb011") address_param_711+=("e95d84") address_param_711+=("e95d88") address_param_711+=("e949f4") address_param_711+=("e94b17") address_param_711+=("fa6458") address_param_711+=("fa6468") exe_hash_711="abd3ce2193b113c28d1bf5e28739bb303b52a556" # Version 71.2 declare -a address_param_712 version_list+=("71.2") address_param_712+=("5dccbf") address_param_712+=("5dccc2") address_param_712+=("5db90e") address_param_712+=("5dba3e") address_param_712+=("6cef41") address_param_712+=("6cef51") address_param_712+=("e9992c") address_param_712+=("e99930") address_param_712+=("e9859c") address_param_712+=("e986bf") address_param_712+=("faa308") address_param_712+=("faa318") exe_hash_712="35d64aa153bca44a4325b47211ae19ae2bf16fac" # Value old parameter array. declare -a value_ancient_param value_ancient_param+=("\00") value_ancient_param+=("\00\00") value_ancient_param+=("\165") # Value old parameter array. declare -a value_old_param value_old_param+=("\00") value_old_param+=("\00\00") value_old_param+=("\165") value_old_param+=("\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") # x86_remove_register # Value parameter array. declare -a value_legacy_param value_legacy_param+=("\00") value_legacy_param+=("\00") value_legacy_param+=("\00\00") value_legacy_param+=("\165") declare -a value_param value_param+=("\00") # x86_1 value_param+=("\00") # x86_2 value_param+=("\00\00") # x86_3 value_param+=("\165") # x86_4 value_param+=("\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") # x86_remove_register value_param+=("\40\123\153\145\164\143\150\103\162\141\160\160\40") # x86_modified_day_left value_param+=("\01") # aarch_1 value_param+=("\24") # aarch_2 value_param+=("\165\00") # aarch_3 value_param+=("\64") # aarch_4 value_param+=("\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00") # aarch_remove_register value_param+=("\40\123\153\145\164\143\150\103\162\141\160\160\40") # aarch_modified_day_left declare -a nametag_ancient_ver nametag_ancient_ver+=("51.3") declare -a nametag_old_ver nametag_old_ver+=("53") # OpenSSL configuration. CONFIG=" [ req ] distinguished_name=name [ name ] [ self ] keyUsage = critical,digitalSignature extendedKeyUsage = codeSigning subjectKeyIdentifier = hash basicConstraints = critical,CA:false " downloadURLString="" # Banner block banner() { cat <<"EOF" __ __ __ ___ / /_____ / /_____/ / ___________ ____ ___ ( _-</ '_/ -_) __/ __/ _ \/ __/ __/ _ `/ _ \/ _ \ /___/_/\_\\__/\__/\__/_//_/\__/_/ \_,_/ .__/ .__/ /_/ /_/ Sketch.App Patch Tool (https://github.com/duraki/SketchCrapp) by @duraki & @elijahtsai EOF } # RUP Review every time when new verison update part. # Last function to run before exit. finally() { local status="$1" local pds="2021-10-16 serial 002" printf "[+] SketchCrapp last published date: \e[38;5;14m$pds\e[0m\n" exit $status } # RUP Review every time when new verison update part. # Help messages block. usage() { echo "Usage:" echo "./sketchcrapp [-h] [-a] <applicationPath> [-m] [-g] <version>" echo "Supported versions: v51.3, v53, v58, v63.1, v64.0, v65.1, v66.1, v67" echo "v67.1, v67.2, v68, v68.1, v68.2, v69, v69.1, v69.2, v70.2, v70.3, v70.4" echo "v70.5, v70.6, v71.1, v71.2" finally 0; } # Clean up all related files. clean() { printf "[+] Cleaning up file(s) ... " if [ -f pk.pem ]; then rm -f pk.pem fi if [ -f crt.pem ]; then rm -f crt.pem fi if [ -f pkcs.p12 ]; then rm -f pkcs.p12 fi if [ -f "/tmp/app.zip" ]; then rm -f "/tmp/app.zip" if ! [ "$?" -eq "0" ]; then printf "\e[38;5;9mError\e[0m\n" echo "[-] Fail to remove zip file of latest application. remove by yourself." finally 1 fi fi if [ -f "/tmp/Sketch.app" ]; then rm -f "/tmp/Sketch.app" if ! [ "$?" -eq "0" ]; then printf "\e[38;5;9mError\e[0m\n" echo "[-] Fail to remove application bundle. remove by yourself." finally 1 fi fi if [ -f "/tmp/select.swift" ]; then rm -f "/tmp/select.swift" if ! [ "$?" -eq "0" ]; then printf "\e[38;5;9mError\e[0m\n" echo "[-] Fail to remove swift script file. remove by yourself." finally 1 fi fi if [ -f "/tmp/list.xml" ]; then rm -f "/tmp/list.xml" if ! [ "$?" -eq "0" ]; then printf "\e[38;5;9mError\e[0m\n" echo "[-] Fail to remove list xml file. remove by yourself." finally 1 fi fi printf "\e[38;5;10mCleaned\e[0m\n" } # Generate self-signed certificate for codesign. Required for pass-tru # code-signature detection by Sketch. Built-in via MacOS openssl library. genSelfSignCert() { echo "[+] Generating self-signed certificate ..." openssl req -new -newkey ec:<(openssl ecparam -name secp521r1) \ -config <(echo "$CONFIG") \ -extensions self -days 3650 -nodes -x509 \ -subj "/CN=sketchcrapp"\ -keyform pem -keyout pk.pem \ -outform pem -out crt.pem echo "[+] Creating pkcs package..." openssl pkcs12 -export -out pkcs.p12 -in crt.pem -inkey pk.pem \ -name "sketchcrapp" -nodes -passout pass:1234 } # Import code-signature certificate to keychain. Must be included and trusted # by the OS internals. # - First: The default keychain that under the user profile. importSelfSignCert() { local userDefaultKeychain="$1" echo "[+] Importing private key and self-signed certificate" security import pkcs.p12 -k "$userDefaultKeychain" -f pkcs12 -P 1234 } # Equivalent to code-signature application in Sketch. # Sign Sketch with generated certificate. # - Parameters: # - First: The application bundle path. # - Second: The default keychain that under the user profile. signApplication() { local appPath="$1" local userDefaultKeychain="$2" echo "[+] Signing the patched *.app bundle. This may require root privilege." echo "[+] If asked, enter your login password. Choose \"Always Allow\" to \ not be asked again." codesign --deep --force -s "sketchcrapp" "$appPath" --verbose --keychain "$userDefaultKeychain" if ! [ "$?" -eq "0" ]; then echo "[-] Failed to sign Sketch bundle." echo "[+] Automatic fix process started." echo "[+] Removing certificate ..." security delete-certificate -c "sketchcrapp" "$userDefaultKeychain" if ! [ "$?" -eq "0" ]; then echo "[-] Unable to delete <sketchcrapp> certificate from Keychain" clean finally 1 fi echo "[+] Re-creating signature identity ..." genSelfSignCert echo "[+] Re-importing signature identity ..." importSelfSignCert "$userDefaultKeychain" echo "[+] Resigning application bundle again using signature identity ..." codesign --deep --force -s "sketchcrapp" "$appPath" --verbose --keychain "$userDefaultKeychain" if ! [ "$?" -eq "0" ]; then printf "[\e[38;5;9mERR\e[0m] Failed to sign Sketch bundle. Automatic method failed.\n" printf "[\e[38;5;11mINFO\e[0m] Copy the full log and open a new issue on GitHub \ repository: https://github.com/duraki/SketchCrapp\n" clean finally 1 fi fi } checkVersionSupported() { local versionString="$1" for versionElement in "${version_list[@]}" do if [ "$versionString" = "$versionElement" ]; then return 0 fi done return 1 } generateSelectVersionScript(){ echo "[+] Generating swift script: target Version ..." cat <<'EOF' > /tmp/select.swift import Foundation var testString = "" while let line = readLine() { testString += "\(line)\n" } let pattern = #"v?(?:(\d\.\d\.\d)|(\d\d?\d?\.\d)|(\d\d))"# let regex = try! NSRegularExpression(pattern: pattern) let stringRange = NSRange(location: 0, length: testString.utf16.count) let matches = regex.matches(in: testString, range: stringRange) var versions: String versions="(null)" for match in matches { var groups: String = "" for rangeIndex in 1 ..< match.numberOfRanges { if match.range(at: rangeIndex).location > testString.utf16.count { continue } groups = (testString as NSString).substring(with: match.range(at: rangeIndex)) } versions=groups } print(versions) EOF } generateSelectURLScript(){ echo "[+] Generating swift script: target URL ..." cat <<'EOF' > /tmp/select.swift import Foundation var testString = "" while let line = readLine() { testString += "\(line)\n" } let pattern = #".*<enclosure url[^"]"(.*)" len.*\/>.*"# let regex = try! NSRegularExpression(pattern: pattern) let stringRange = NSRange(location: 0, length: testString.utf16.count) let matches = regex.matches(in: testString, range: stringRange) var urls: [String] = [] for match in matches { var groups: String = "" for rangeIndex in 1 ..< match.numberOfRanges { if match.range(at: rangeIndex).location > testString.utf16.count { continue } groups = (testString as NSString).substring(with: match.range(at: rangeIndex)) } urls.append(groups) } for u in urls { print(u) } EOF } getURLFromVersionString() { local versionString="$1" local testVersionString="" echo "[+] Checking if version $versionString is supported ..." if [ -z "$versionString" ]; then versionString="(null)" else generateSelectVersionScript testVersionString=$(echo $versionString | swift "/tmp/select.swift") checkVersionSupported "$testVersionString" fi if ! [ "$?" -eq "0" ] || [ -z $testVersionString ]; then printf "[\e[38;5;9mERR\e[0m] Version $testVersionString is not supported, \ please carefully review README file again.\n" printf "[\e[38;5;11mINFO\e[0m] Copy the details below and open a new issue on GitHub \ repository: https://github.com/duraki/SketchCrapp\n" echo "+===================================================================" echo "+ Issue details ‹s:sketchcrapp:VersionUserEnter›" echo "+ Passed version : $versionString" echo "+ Normalize version : $testVersionString" echo "+ Error : Version $testVersionString is not supported." echo "+===================================================================" clean finally 1 fi local versionListXMLURL="https://download.sketch.com/sketch-versions.xml" echo "[+] Fetching $versionListXMLURL ... " curl -L "$versionListXMLURL" --output "/tmp/list.xml" if ! [ "$?" -eq "0" ]; then printf "[\e[38;5;9mERR\e[0m] Failed while downloading version list xml file!\n" printf "[\e[38;5;11mINFO\e[0m] Are you connected to the internet? Check your network connection.\n" clean finally 1 fi generateSelectURLScript if ! [ -f "/tmp/select.swift" ]; then echo "[-] Swift script does not exists under the /tmp folder." printf "[\e[38;5;9mERR\e[0m] Couldn't find select.swift at /tmp/select.swift\n" printf "[\e[38;5;11mINFO\e[0m] We don't know what's going on, try to use -m to get latest patch.\n" clean finally 1 fi LANG=en_GB.UTF-8 OIFS=$IFS IFS=$'\n' testURL=$(cat /tmp/list.xml | \ sed -e 's/^[[:space:]]*//g' | \ sed -e 's/[[:space:]]*$//g'| \ tr -d '\n' | \ sed -e $'s/<enclos/\\\n<enclos/g' | \ swift "/tmp/select.swift" | \ grep "\-$testVersionString\-") IFS=$OIFS downloadURLString="$testURL" if [ -z "$downloadURLString" ]; then printf "[\e[38;5;9mERR\e[0m] Version $versionString is not supported, \ please carefully review README file again.\n" printf "[\e[38;5;11mINFO\e[0m] Copy the details below and open a new issue on GitHub \ repository: https://github.com/duraki/SketchCrapp\n" echo "+===================================================================" echo "+ Issue details ‹s:sketchcrapp:UnknowDownloadURLString" echo "+ Passed version : $versionString" echo "+ Normalize version : $testVersionString" echo "+ Error : Version $versionString is not supported." echo "+===================================================================" clean finally 1 fi echo "[+] Download URL set to: $downloadURLString" } # Get binary hash from CFBundleShortVersionString # - Parameters: # - First: The application bundle CFBundleShortVersionString. getHashFromVersionString() { local bundleVersionString="$1" # RUP Review every time when new verison update part. case "$bundleVersionString" in "51.3") echo "$exe_hash_513" ;; "53") echo "$exe_hash_530" ;; "58") echo "$exe_hash_580" ;; "63.1") echo "$exe_hash_631" ;; "64") echo "$exe_hash_640" ;; "65.1") echo "$exe_hash_651" ;; "66.1") echo "$exe_hash_661" ;; "67") echo "$exe_hash_670" ;; "67.1") echo "$exe_hash_671" ;; "67.2") echo "$exe_hash_672" ;; "68") echo "$exe_hash_680" ;; "68.1") echo "$exe_hash_681" ;; "68.2") echo "$exe_hash_682" ;; "69") echo "$exe_hash_690" ;; "69.1") echo "$exe_hash_691" ;; "69.2") echo "$exe_hash_692" ;; "70.2") echo "$exe_hash_702" ;; "70.3") echo "$exe_hash_703" ;; "70.4") echo "$exe_hash_704" ;; "70.5") echo "$exe_hash_705" ;; "70.6") echo "$exe_hash_706" ;; "71.1") echo "$exe_hash_711" ;; "71.2") echo "$exe_hash_712" ;; *) echo "Input version string invaild, cannot lookup correct hash value." esac } # Verify the application by using hash value. # - Parameters: # - First: The application bundle path. analysisApplication() { echo "[+] Analysing application bundle ... Starting" local appPath="$1" printf "[+] Finding executable file ... " # Get the path of application executable. local execPath="$appPath/Contents/MacOS/Sketch" if ! [ -f "$execPath" ]; then printf "\e[38;5;9mError\e[0m\n" echo "[-] Executable file does not exists under the given application folder." printf "[\e[38;5;9mERR\e[0m] Couldn't find executable file at $execPath\n" printf "[\e[38;5;11mINFO\e[0m] Please make sure you pass clean app to script.\n" finally 1 fi printf "\e[38;5;10mOK\e[0m\n" printf "[+] Finding Info.plist ... " # Get the path of application info plist. local infoPath="$appPath/Contents/Info" if ! [ -f "$infoPath.plist" ]; then printf "\e[38;5;9mError\e[0m\n" echo "[-] Info file does not exists under the given application folder." printf "[\e[38;5;9mERR\e[0m] Couldn't find Info.plist at $infoPath.plist\n" printf "[\e[38;5;11mINFO\e[0m] Please make sure you pass clean app to script.\n" finally 1 fi printf "\e[38;5;10mOK\e[0m\n" printf "[+] Checking Info.plist for CFBundleShortVersionString ... " # Get the CFBundleShortVersionString from info plist. local bundleVersionString="$(defaults read $infoPath CFBundleShortVersionString)" if [ -z "$bundleVersionString" ]; then printf "\e[38;5;9mError\e[0m\n" printf "[\e[38;5;9mERR\e[0m] Couldn't find value of CFBundleShortVersionString\n" printf "[\e[38;5;11mINFO\e[0m] Please make sure you pass clean app to script.\n" finally 1 fi printf "\e[38;5;10mOK\e[0m\n" # Get the hash of application executable local appSHA1="$(shasum -a 1 "$execPath" | cut -f 1 -d ' ')" checkVersionSupported "$bundleVersionString" if ! [ "$?" -eq "0" ]; then printf "[\e[38;5;9mERR\e[0m] Version $bundleVersionString is not supported, \ please carefully review README file again.\n" printf "[\e[38;5;11mINFO\e[0m] Copy the details below and open a new issue on GitHub \ repository: https://github.com/duraki/SketchCrapp\n" echo "+===================================================================" echo "+ Issue details ‹s:sketchcrapp›" echo "+ Application Path : $appPath" echo "+ Application Binary: $execPath" echo "+ Passed version : $bundleVersionString" echo "+ Binary SHA1 : $appSHA1" echo "+ Error : Version $bundleVersionString is not supported." echo "+===================================================================" finally 1 fi printf "[+] Validating executable file ... " local testBundleVersionString="" # RUP Review every time when new verison update part. case "$appSHA1" in "$exe_hash_513") testBundleVersionString="51.3" ;; "$exe_hash_530") testBundleVersionString="53" ;; "$exe_hash_580") testBundleVersionString="58" ;; "$exe_hash_631") testBundleVersionString="63.1" ;; "$exe_hash_640") testBundleVersionString="64" ;; "$exe_hash_651") testBundleVersionString="65.1" ;; "$exe_hash_661") testBundleVersionString="66.1" ;; "$exe_hash_670") testBundleVersionString="67" ;; "$exe_hash_671") testBundleVersionString="67.1" ;; "$exe_hash_672") testBundleVersionString="67.2" ;; "$exe_hash_680") testBundleVersionString="68" ;; "$exe_hash_681") testBundleVersionString="68.1" ;; "$exe_hash_682") testBundleVersionString="68.2" ;; "$exe_hash_690") testBundleVersionString="69" ;; "$exe_hash_691") testBundleVersionString="69.1" ;; "$exe_hash_692") testBundleVersionString="69.2" ;; "$exe_hash_702") testBundleVersionString="70.2" ;; "$exe_hash_703") testBundleVersionString="70.3" ;; "$exe_hash_704") testBundleVersionString="70.4" ;; "$exe_hash_705") testBundleVersionString="70.5" ;; "$exe_hash_706") testBundleVersionString="70.6" ;; "$exe_hash_711") testBundleVersionString="71.1" ;; "$exe_hash_712") testBundleVersionString="71.2" ;; *) testBundleVersionString="binaryerr››" printf "\e[38;5;9mError\e[0m\n" printf "[\e[38;5;9mERR\e[0m] Can't find Sketch with that signature. Hash is invalid.\n" printf "[\e[38;5;11mINFO\e[0m] Carefully review README file again\n" printf "[\e[38;5;11mINFO\e[0m] If you still have problem copy the details below and open a new issue\n" printf "[\e[38;5;11mINFO\e[0m] on GitHub repository: https://github.com/duraki/SketchCrapp\n" echo "+===================================================================" echo "+ Application Path : $appPath" echo "+ Application Binary: $execPath" echo "+ Passed version : $bundleVersionString" echo "+ Correct hash : $(getHashFromVersionString "$bundleVersionString")" echo "+ Binary SHA1 : $appSHA1" echo "+ Error : Can't find Sketch with that signature. Hash is invalid." echo "+===================================================================" finally 1 esac if [ "$bundleVersionString" = "$testBundleVersionString" ]; then printf "\e[38;5;10mOK\e[0m\n" engin "$bundleVersionString" "$appPath" "$execPath" else printf "\e[38;5;9mError\e[0m\n" printf "[\e[38;5;9mFATAL\e[0m] Executable SHA1 hash returned version value does not \ equal to the CFBundleShortVersionString\n" printf "[\e[38;5;11mINFO\e[0m] Carefully review README file again, if you still have problem\n" printf "[\e[38;5;11mINFO\e[0m] open a new issue on GitHub repository: https://github.com/duraki/SketchCrapp\n" finally 1 fi } # Patch ancient process. # - Parameters: # - First: An array of address of specific version. # - Second: A path of application executable to patch. patchAncient() { echo "Starting ancient arch patch via bash&seek ..." local addressArray=(${1}) local execPath=${2} for i in {0..2}; do echo "[+] Patching address at offset: 0x${addressArray[$i]} \ with value: ${value_ancient_param[$i]}" printf "${value_ancient_param[$i]}" | dd seek="$((0x${addressArray[$i]}))" conv=notrunc bs=1 of="$execPath" if ! [ "$?" -eq "0" ]; then printf "[\e[38;5;9mFATAL\e[0m] Patch process resulted in failure. That's all we know.\n" printf "[\e[38;5;11mINFO\e[0m] Open a new issue and tell us about this \ on GitHub repository: https://github.com/duraki/SketchCrapp\n" finally 1 fi done } # Patch old process. # - Parameters: # - First: An array of address of specific version. # - Second: A path of application executable to patch. patchOld() { echo "Starting old arch patch via bash&seek ..." local addressArray=(${1}) local execPath=${2} for i in {0..3}; do echo "[+] Patching address at offset: 0x${addressArray[$i]} \ with value: ${value_old_param[$i]}" printf "${value_old_param[$i]}" | dd seek="$((0x${addressArray[$i]}))" conv=notrunc bs=1 of="$execPath" if ! [ "$?" -eq "0" ]; then printf "[\e[38;5;9mFATAL\e[0m] Patch process resulted in failure. That's all we know.\n" printf "[\e[38;5;11mINFO\e[0m] Open a new issue and tell us about this \ on GitHub repository: https://github.com/duraki/SketchCrapp\n" finally 1 fi done } # Patch legacy process. # - Parameters: # - First: An array of address of specific version. # - Second: A path of application executable to patch. patchLegacy() { echo "Starting legacy arch patch via bash&seek ..." local addressArray=(${1}) local execPath=${2} for i in {0..3}; do echo "[+] Patching address at offset: 0x${addressArray[$i]} \ with value: ${value_legacy_param[$i]}" printf "${value_legacy_param[$i]}" | dd seek="$((0x${addressArray[$i]}))" conv=notrunc bs=1 of="$execPath" if ! [ "$?" -eq "0" ]; then printf "[\e[38;5;9mFATAL\e[0m] Patch process resulted in failure. That's all we know.\n" printf "[\e[38;5;11mINFO\e[0m] Open a new issue and tell us about this \ on GitHub repository: https://github.com/duraki/SketchCrapp\n" finally 1 fi done } # Patch process. # - Parameters: # - First: An array of address of specific version. # - Second: A path of application executable to patch. patch() { echo "Starting patch via bash&seek ..." local addressArray=(${1}) local execPath=${2} for i in {0..11}; do echo "[+] Patching address at offset: 0x${addressArray[$i]} \ with value: ${value_param[$i]}" printf "${value_param[$i]}" | dd seek="$((0x${addressArray[$i]}))" conv=notrunc bs=1 of="$execPath" if ! [ "$?" -eq "0" ]; then printf "[\e[38;5;9mFATAL\e[0m] Patch process resulted in failure. That's all we know.\n" printf "[\e[38;5;11mINFO\e[0m] Open a new issue and tell us about this \ on GitHub repository: https://github.com/duraki/SketchCrapp\n" finally 1 fi done } # Install and register cracktag + credits for ancient version nameTagAncient() { local appPath="$1" local LangPath="$appPath/Contents/Resources/" if ! [ -d "$LangPath" ]; then if [ -d "$appPath" ]; then rm -rf "$appPath" clean finally 1 fi fi local LangFilePath="$LangPath/Localizable.strings" if ! [ -f "$LangFilePath" ]; then if [ -d "$appPath" ]; then rm -rf "$appPath" clean finally 1 fi fi local LangFilePathBak="$LangPath/Localizable.strings.bak" mv "$LangFilePath" "$LangFilePathBak" cat "$LangFilePathBak" | iconv -f UTF-16LE -t UTF-8 | sed -e "s/1 Day Left/SketchCrapp/g" -e "s/ - Register Now//g" | iconv -f UTF-8 -t UTF-16LE > "$LangFilePath" rm -f "$LangFilePathBak" } # Install and register cracktag + credits for older version nameTagOld() { local appPath="$1" local LangPath="$appPath/Contents/Resources/en.lproj" if ! [ -d "$LangPath" ]; then if [ -d "$appPath" ]; then rm -rf "$appPath" clean finally 1 fi fi local LangFilePath="$LangPath/Localizable.stringsdict" if ! [ -f "$LangFilePath" ]; then if [ -d "$appPath" ]; then rm -rf "$appPath" clean finally 1 fi fi local LangFilePathBak="$LangPath/Localizable.stringsdict.bak" mv "$LangFilePath" "$LangFilePathBak" cat "$LangFilePathBak" | iconv -f UTF-16LE -t UTF-8 | sed -e "s/1 Day Left/SketchCrapp/g" | iconv -f UTF-8 -t UTF-16LE > "$LangFilePath" rm -f "$LangFilePathBak" } # Install and register cracktag + credits nameTag() { local appPath="$1" local engLangPath="$appPath/Contents/Resources/en.lproj" local zhLangPath="$appPath/Contents/Resources/zh-Hans.lproj" if ! [ -d "$engLangPath" ] || ! [ -d "$zhLangPath" ]; then if [ -d "$appPath" ]; then rm -rf "$appPath" clean finally 1 fi fi echo '"gWf-Nl-VLs.title" = "Sketch Cloud is currently not supported by SketchCrapp. Sorry :("; "h0z-lo-HfZ.ibShadowedIsNilPlaceholder" = "@0xduraki & @elijahtsai"; "h1X-KO-1Ed.title" = "Name"; "Ja3-jS-bo6.title" = "Crack It"; "kCf-Hg-sTQ.ibShadowedIsNilPlaceholder" = "Cracked by @0xduraki & @elijahtsai"; "kUG-6E-w0F.ibShadowedIsNilPlaceholder" = "sketchcrapp@github.com"; "mSb-kZ-v2e.ibShadowedLabels[0]" = "SketchCrapp"; "mSb-kZ-v2e.ibShadowedLabels[1]" = "github.com/duraki/SketchCrapp"; "oEr-Dw-WUj.title" = "Forgot to crack it?"; "pfs-Mp-bgn.title" = "Wh00ps, what did you do :)"; "yfB-jh-Is0.placeholderString" = "Cracked by @0xduraki & @elijahtsai";' > "$engLangPath/MSRegistrationWindow.strings" if ! [ -f "$zhLangPath/MSRegistrationWindow.strings" ]; then if [ -d "$appPath" ]; then rm -rf "$appPath" clean finally 1 fi fi /usr/bin/sed -i -e 's/"gWf-Nl-VLs.title"\ =\ [^;]*/"gWf-Nl-VLs.title" = "SketchCrapp 還沒支援 Sketch Cloud, 再等等吧 :("/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"h0z-lo-HfZ.ibShadowedIsNilPlaceholder"\ =\ [^;]*/"h0z-lo-HfZ.ibShadowedIsNilPlaceholder" = "@0xduraki \& @elijahtsai"/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"h1X-KO-1Ed.title"\ =\ [^;]*/"h1X-KO-1Ed.title" = "名稱"/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"Ja3-jS-bo6.title"\ =\ [^;]*/"Ja3-jS-bo6.title" = "破解"/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"kCf-Hg-sTQ.ibShadowedIsNilPlaceholder"\ =\ [^;]*/"kCf-Hg-sTQ.ibShadowedIsNilPlaceholder" = "由 @0xduraki \& @elijahtsai 破解"/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"kUG-6E-w0F.ibShadowedIsNilPlaceholder"\ =\ [^;]*/"kUG-6E-w0F.ibShadowedIsNilPlaceholder" = "sketchcrapp@github.com"/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"mSb-kZ-v2e.ibShadowedLabels\[0\]"\ =\ [^;]*/"mSb-kZ-v2e.ibShadowedLabels[0]" = "SketchCrapp"/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"mSb-kZ-v2e.ibShadowedLabels\[1\]"\ =\ [^;]*/"mSb-kZ-v2e.ibShadowedLabels[1]" = "github.com\/duraki\/SketchCrapp"/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"oEr-Dw-WUj.title"\ =\ [^;]*/"oEr-Dw-WUj.title" = "忘記破解了嗎?"/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"pfs-Mp-bgn.title"\ =\ [^;]*/"pfs-Mp-bgn.title" = "哇!您做了什麼!"/g' "$zhLangPath/MSRegistrationWindow.strings" /usr/bin/sed -i -e 's/"yfB-jh-Is0.placeholderString"\ =\ [^;]*/"yfB-jh-Is0.placeholderString" = "由 @0xduraki \& @elijahtsai 破解"/g' "$zhLangPath/MSRegistrationWindow.strings" } # All the code and logic flow to patch the Sketch.app binary, do a code-signature # and link-resolve the patched Sketch.app. # - Parameters: # - First: A version of current application bundle. # - Second: An array of address of specific version. # - Third: A path of application executable to patch. engin() { local appVersion="$1" local appPath="$2" local execPath="$3" # Version Selector. echo "[+] Selected Sketch.app version is $appVersion ... SketchCrapp starting ... OK" echo "[+] Patching offsets for $appVersion ... " # RUP Review every time when new verison update part. case "$appVersion" in "51.3") patchAncient "${address_param_513[*]}" "$execPath" ;; "53") patchOld "${address_param_530[*]}" "$execPath" ;; "58") patchLegacy "${address_param_580[*]}" "$execPath" ;; "63.1") patchLegacy "${address_param_631[*]}" "$execPath" ;; "64") patchLegacy "${address_param_640[*]}" "$execPath" ;; "65.1") patchLegacy "${address_param_651[*]}" "$execPath" ;; "66.1") patchLegacy "${address_param_661[*]}" "$execPath" ;; "67"|"67.1") patchLegacy "${address_param_670[*]}" "$execPath" ;; "67.2") patchLegacy "${address_param_672[*]}" "$execPath" ;; "68") patchLegacy "${address_param_680[*]}" "$execPath" ;; "68.1") patchLegacy "${address_param_681[*]}" "$execPath" ;; "68.2") patchLegacy "${address_param_681[*]}" "$execPath" ;; "69") patchLegacy "${address_param_690[*]}" "$execPath" ;; "69.1") patchLegacy "${address_param_691[*]}" "$execPath" ;; "69.2") patchLegacy "${address_param_691[*]}" "$execPath" ;; "70.2") patch "${address_param_702[*]}" "$execPath" ;; "70.3") patch "${address_param_703[*]}" "$execPath" ;; "70.4") patch "${address_param_704[*]}" "$execPath" ;; "70.5") patch "${address_param_705[*]}" "$execPath" ;; "70.6") patch "${address_param_705[*]}" "$execPath" ;; "71.1") patch "${address_param_711[*]}" "$execPath" ;; "71.2") patch "${address_param_712[*]}" "$execPath" ;; *) printf "[\e[38;5;9mERR\e[0m] Something went wrong, this line should never execute.\n" printf "[\e[38;5;11mINFO\e[0m] Copy the details below and open a new issue on GitHub repository: \ https://github.com/duraki/SketchCrapp\n" echo "+===================================================================" echo "+ Issue details ‹s:sketchcrapp›" echo "+ Application Path : $appPath" echo "+ Application Binary: $execPath" echo "+ Passed version : $bundleVersionString" echo "+ Binary SHA1 : $appSHA1" echo "+ Error : patcherr››" echo "+===================================================================" finally 1 esac # Install name tag if [[ "${nametag_ancient_ver[*]}" =~ "$appVersion" ]]; then nameTagAncient "$appPath" elif [[ "${nametag_old_ver[*]}" =~ "$appVersion" ]]; then nameTagOld "$appPath" else nameTag "$appPath" fi # Get the path of user default keychain. userKeyChain="$(security default-keychain -d user | sed -e 's/^[ ]*//g' -e 's/\"//g')" printf "[+] Checking user default keychain ... " if ! [ -f "$userKeyChain" ]; then printf "\e[38;5;9mNot exist\e[0m\n" echo "[-] User default Keychain does not exist: $userKeyChain" clean finally 1 fi printf "\e[38;5;10mExist\e[0m\n" # CodeSigning area. # Check if sketchcrapp certificate already exist. printf "[+] Checking SketchCrapp identity ... " security find-identity -p codesigning | grep sketchcrapp >/dev/null if ! [ "$?" -eq "0" ]; then printf "\e[38;5;11mNot exist\e[0m\n" # Certificate does not exist, generate one. genSelfSignCert # Import the certificate. importSelfSignCert "$userKeyChain" else printf "\e[38;5;10mExist\e[0m\n" echo "[+] Skipping certificate creation" fi # Sign the application. signApplication "$appPath" "$userKeyChain" # Call cleaner to do some housekeeping. clean printf "[+] SketchCrapp process \e[38;5;10mcompleted\e[0m. Sketch.app has been patched :)\n" printf "[+] \e[38;5;11m-- Notice: \e[0m\n" echo "[+] If a dialogue shows up with message: “Sketch 3.app” can’t be opened" echo "[+] please right-click the application and select open, " echo "[+] or go to Settings -› Security and allow opening Sketch.app application." echo "[+] " echo "[+] If you are using an old version and a dialogue shows up asking for password" echo "[+] about \"com.bohemiancoding.sketch3.HockeySDK\"" echo "[+] please enter your login password. Choose \"Always Allow\" to not be asked again." echo "" echo "[+] SketchCrapp (A Sketch.app cracking tool)" echo "[+] https://github.com/duraki/SketchCrapp [by @duraki & @elijahtsai]" } # An auto function to patch latest app. magic() { local testVersionString="$1" if [ -z "$testVersionString" ]; then testVersionString="$latestVersion" fi echo "[+] Hello, The magic show is about to start! Are you ready?" getURLFromVersionString "$testVersionString" # Check if missing cURL if ! command -v curl &> /dev/null; then echo "cURL is not installed on your system." echo "This should not happen, macOS have cURL built-in." printf "[\e[38;5;11mFIX\e[0m] Try: brew install curl\n" printf "[\e[38;5;11mFIX\e[0m] Try: port install curl\n" printf "[\e[38;5;11mFIX\e[0m] Try: install cURL manually\n" finally 1; fi # Check if missing UNZIP if ! command -v unzip &> /dev/null; then echo "UNZIP is not installed on your system." echo "This should not happen, macOS have UNZIP built-in." printf "[\e[38;5;11mFIX\e[0m] Try: brew install unzip\n" printf "[\e[38;5;11mFIX\e[0m] Try: port install unzip\n" printf "[\e[38;5;11mFIX\e[0m] Try: install UNZIP manually\n" finally 1; fi printf "[+] Checking directory tmp existence ... " if ! [ -d /tmp ]; then printf "\e[38;5;9mError\e[0m\n" echo "Directory tmp does not exist." finally 1 fi printf "\e[38;5;10mOK\e[0m\n" echo "[+] Fetching $downloadURLString ... " curl "$downloadURLString" --output "/tmp/app.zip" if ! [ "$?" -eq "0" ]; then echo "[-] Failed while downloading latest application version!" echo "[-] Are you connected to the internet? Check your network connection." clean finally 1 fi echo -n "[+] Checking if Sketch.app exist in /tmp ... " if [ -d "/tmp/Sketch.app" ]; then echo "Exist. Removing." rm -rf "/tmp/Sketch.app" if ! [ "$?" -eq St"0" ]; then echo "[-] Can't remove existing Sketch.app from /tmp directory." clean finally 1 fi else echo "Not exist. Continuous." fi unzip -q "/tmp/app.zip" -d "/tmp" if ! [ "$?" -eq "0" ]; then echo "[-] Can't unzip downloaded archived file of the latest application version." clean finally 1 fi echo -n "[+] Checking if Sketch.app exist in /Applications ... " if [ -d "/Applications/Sketch.app" ]; then echo "Exist. Removing." rm -rf "/Applications/Sketch.app" if ! [ "$?" -eq "0" ]; then echo "Fail to remove exist Sketch.app in /Applications directory." clean finally 1 fi else echo "Not exist. Continuous." fi printf "[+] Moving Sketch.app to /Applications directory ... " reason="$(mv "/tmp/Sketch.app" "/Applications" 2>&1)" if ! [ "$?" -eq "0" ]; then printf "\e[38;5;9mFail\e[0m\n" echo "[-] Failed while moving /tmp/Sketch.app to /Applications directory." printf "[\e[38;5;11mINFO\e[0m] Reason: $reason\n" clean finally 1 fi printf "\e[38;5;10mSuccessfully.\e[0m\n" analysisApplication "/Applications/Sketch.app" } # Command Line Interface initialization. # Script startup point. How about we start from banner shell we? banner # Check if missing UNZIP if ! command -v sed &> /dev/null; then echo "SED is not installed on your system." echo "This should not happen, macOS have sed built-in." printf "[\e[38;5;11mFIX\e[0m] Try: brew install sed\n" printf "[\e[38;5;11mFIX\e[0m] Try: port install sed\n" printf "[\e[38;5;11mFIX\e[0m] Try: install SED manually\n" finally 1; fi # Check if missing OpenSSL library if ! command -v openssl &> /dev/null; then echo "OpenSSL is not installed on your system." echo "This should not happen, macOS have OpenSSL built-in." printf "[\e[38;5;11mFIX\e[0m] Try: brew install openssl\n" printf "[\e[38;5;11mFIX\e[0m] Try: port install openssl\n" printf "[\e[38;5;11mFIX\e[0m] Try: install openssl manually\n" finally 1; fi # If no option was given by default search /Application or ~/Application . if [ $# -eq 0 ]; then echo "SketchCrapp is finding application bundle path ..." if [ -d "/Applications/Sketch.app" ]; then # Sketch is found in /Application . echo "[+] Selected Sketch.app path is </Applications> (auto-detected) ... OK" analysisApplication "/Applications/Sketch.app" elif [ -d "$HOME/Applications/Sketch.app" ]; then # Sketch is found in ~/Application . echo "[+] Selected Sketch.app path is <$HOME/Applications> (auto-detected) ... OK" analysisApplication "$HOME/Applications/Sketch.app" else printf "[\e[38;5;9mERR\e[0m] Application not found in /Applications or ~/Applications\n" echo "Try: ./sketchcrapp -a /Custom/Path/For/Applications/Sketch.app" echo "To get the latest supported version of Sketch" echo "Try: ./sketchcrapp -m" finally 1 fi finally 0 fi # Option filter (Command-Line Interface parser). while getopts "ha:mg:" argv; do case "${argv}" in h) usage ;; a) appPath="${OPTARG}" if [ -d "$appPath" ]; then analysisApplication "$appPath" else printf "[\e[38;5;9mERR\e[0m] Given directory is either invaild or not exist.\n" finally 1 fi ;; m) magic ;; g) version="${OPTARG}" magic "$version" ;; *) echo "Use -h for more information." finally 0 ;; esac done finally 0