Xcode16.3配置越狱开发环境

首先先在https://developer.apple.com/xcode/resources/ 这里面登陆Apple账号,然后访问url下载 https://download.developer.apple.com/Developer_Tools/Xcode_16.3/Xcode_16.3.xip

1、安装theos

https://theos.dev/docs/installation-macos

会安装到默认位置~/theos

或者直接运行

复制代码
 bash -c "$(curl -fsSL https://raw.githubusercontent.com/theos/theos/master/bin/install-theos)"

软链接放到默认位置

复制代码
sudo ln -s /Users/kk/theos /opt/theos

2、安装MonkeyDev

参考这个issue解决,不过这个issue原始的脚本还需要进一步修改才可以用于16.3

https://github.com/AloneMonkey/MonkeyDev/issues/365#issuecomment-2726745723

这里放出来最终可用的安装脚本:

bash 复制代码
#!/bin/bash

#set -e表示一旦脚本中有命令的返回值为非0,则脚本立即退出,后续命令不再执行;
#set -o pipefail表示在管道连接的命令序列中,只要有任何一个命令返回非0值,则整个管道返回非0值,即使最后一个命令返回0.
export setCmd="set -eo pipefail"
$setCmd

#导出环境变量
export PATH=/opt/MonkeyDev/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin:$PATH

#脚本名称和版本
export scriptName="${0##*/}"
export scriptVer="2.0"

#本地存储文件的目录
export MonkeyDevPath="/opt/MonkeyDev"
export backupFileExt=".MonkeyDev"

#获取用户名、用户组、用户目录、和profile文件
export userName="${SUDO_USER-$USER}"
export userGroup=`id -g $userName`
export userHome=`eval echo ~$userName`

#用户可能存在的profile文件
export bashProfileFiles=("$userHome/.zshrc" "$userHome/.bash_profile" "$userHome/.bashrc" "$userHome/.bash_login" "$userHome/.profile")

#获取临时文件名
export tempDirsFile="`mktemp -d -t $scriptName`/tempdirs"
touch "$tempDirsFile"

#把LANG变量从当前环境中删除
unset LANG

#出错退出
function cleanup()
{
	local exitCode=$?
	set +e
	trap - $signals
	removeTempData
	exit $exitCode
}

function panic()
{
	local exitCode=$1
	set +e
	shift
	[[ "$@" == "" ]] || echo "$@" >&2
	exit $exitCode
}

export signals="0 1 2 3 15"
#当shell接收到signals指定的信号时,执行cleanup命令
trap cleanup $signals

function removeTempData()
{
	local tempDirs
	if [[ -f "$tempDirsFile" ]]; then
		tempDirs=(`cat "$tempDirsFile"`)
		for td in "${tempDirs[@]}"; do
			rm -rf "$td" || true
		done
		rm -rf "`dirname $tempDirsFile`" || true
	fi
}
function getTempDir()
{
	$setCmd
	local tempDir
	tempDir=`mktemp -d -t $scriptName` || \
		panic $? "Failed to create temporary directory"
	echo "$tempDir" >> "$tempDirsFile" || \
		panic $? "Failed to echo into $tempDirsFile"
	echo "$tempDir"
}

function copyFile()
{
	cp -f "$1" "$2" || \
		panic $? "Failed to copy file $1 to $2"
}

#备份原文件
function requireBackup()
{
	[[ ! -f "$1" || -f "${1}${backupFileExt}" ]] || \
		copyFile "$1" "${1}${backupFileExt}"
}

#获取SDK信息
function getSdkProperty()
{
	$setCmd

	local sdk="$1"
	local propertyName="$2"

	propertyValue=`xcodebuild -version -sdk $sdk $propertyName` || \
		panic $? "Failed to get $sdk SDK property $propertyName"

	[[ $propertyValue != "" ]] || \
		panic 1 "Value of $sdk SDK property $propertyName cannot be empty"

	# return #
	echo "$propertyValue"
}

#下载文件
function downloadFile() # args: sourceUrl, targetPath
{
	local sourceUrl="$1"
	local targetPath="$2"
	local curlPath

	mkdir -p "${targetPath%/*}" || \
		panic $? "Failed to make directory: ${targetPath%/*}"

	curlPath=`which curl` || \
		panic $? "Failed to get curl path"

	"$curlPath" --output "$targetPath" "$sourceUrl" || \
		panic $? "Failed to download $sourceUrl to $targetPath"
}

#解压文件
function extractTar() # args: tarPath, outputPath
{
	local tarPath="$1"
	local outputPath="$2"
	
	tar -C "$outputPath" -zxf "$tarPath" || \
		panic $? "Failed to extract $tarPath to $outputPath"
}

#下载github文件
function downloadGithubTarball() # args: url, outputDir, title
{
	$setcmd

	local url="$1"
	local outputDir="$2"
	local title="$3"
	local tempDirForTar
	local tempDirForFiles
	local untardDir
	local tarFile="file.tar.gz"

	echo "Downloading $title from Github..."

	tempDirForTar=`getTempDir`
	tempDirForFiles=`getTempDir`
	
	downloadFile "$url" "$tempDirForTar/$tarFile"
	
	extractTar "$tempDirForTar/$tarFile" "$tempDirForFiles"

	untardDir=`find "$tempDirForFiles/"* -type d -depth 0` || \
		panic $? "Failed to get untar'ed directory name of $tempDirForTar/$tarFile"

	mkdir -p "$outputDir" || \
		panic $? "Failed to make directory: $outputDir"

	cp -fR "$untardDir/"* "$outputDir/"
}

#修改文件权限
function changeMode()
{
	local mode="$1"
	local target="$2"
	local recursive="$3"
	local options

	[[ $recursive != "true" ]] || \
		options="-R"

	if [[ -e "$target" ]]; then
		chmod $options "$mode" "$target" || \
			panic $? "Failed to change mode to $mode on $target"
	fi
}

#获取用户profile文件
function determineUserBashProfileFile()
{
	$setCmd

	local f
	local filePath
	
	for f in "${bashProfileFiles[@]}"; do
		if [[ -f "$f" ]]; then
			filePath="$f"
			echo "" >> "$f" || \
				panic $? "Failed to echo into $f"
			break
		fi
	done
	
	if [[ $filePath == "" ]]; then
		filePath="$bashProfileFiles"

		touch "$filePath" || \
			panic $? "Failed to touch $filePath"
			
		chown "$userName:$userGroup" "$filePath" || \
			panic $? "Failed to change owner-group of $filePath"
		
		changeMode 0600 "$filePath"
	fi
	
	# return #
	echo "$filePath"
}

#验证是否存在文件
function requireFile() # args: filePath [, touchFileIfNotFound]
{
	local filePath="$1"
	local touchFileIfNotFound="$2"
	
	if [[ ! -f "$filePath" ]]; then
		if [[ $touchFileIfNotFound == "true" ]]; then

			touch "$filePath" || \
				panic $? "Failed to touch $filePath"
				
		else
			panic 1 "File $filePath not found"
		fi
	fi
}

#增加内容到文件
function addToFileIfMissing() # args: filePath, pattern, value
{
	local filePath="$1"
	local pattern="$2"
	local value="$3"
	local doesContain

	doesContain=`doesFileContain "$filePath" "$pattern"`
	
	[[ $doesContain == "true" ]] || \
		echo "$value" >> "$filePath" || \
			panic $? "Failed to echo into $filePath"	
}

#判断文件是否包含内容
function doesFileContain() # args: filePath, pattern
{
	$setCmd
	
	local filePath="$1"
	local pattern="$2"
	local perlValue
	local funcReturn
	
	perlValue=`perl -ne 'if (/'"$pattern"'/) { print "true"; exit; }' "$filePath"` || \
		panic $? "Failed to perl"

	if [[ $perlValue == "true" ]]; then
		funcReturn="true"
	else
		funcReturn="false"
	fi
	
	# return #
	echo $funcReturn
}

#从spec读取内容
function readXcodeSpecificationById(){ #args: filePath, id
	local filePath="$1"
	local id="$2"
	content=`/usr/libexec/PlistBuddy -x -c Print "$filePath"` || \
		panic $? "Failed to get $filePath content"
	for (( i=0; i<=1; i++)); do
		dict=`/usr/libexec/PlistBuddy -x -c "Print $i" "$filePath"`
		if echo $dict | grep -qE "<string>$id</string>"; then
			echo "$dict"
		fi
	done
}

#往spec文件写入内容
function writeDictToSpecification(){ #args: filePath, content
	# echo $1,$2
	local filePath="$1"
	local content="$2"
	tempfile=`getTempDir`/dictfile
	# echo $content
	echo "$content" >> $tempfile
	# /usr/libexec/PlistBuddy -x -c 'add 0 dict' "$filePath" > /dev/null
	# cat $1
	/usr/libexec/PlistBuddy -x -c "merge $tempfile 0" "$filePath" > /dev/null
	# cat $1
}

# start it
# 创建/opt/MonkeyDev
mkdir -p "$MonkeyDevPath" || \
	panic $? "Failed to make directory: $MonkeyDevPath"

branch="master"

if [[ "$1" ]]; then
	branch="$1"
fi

#下载一些基础文件和模板文件
downloadGithubTarball "https://codeload.github.com/AloneMonkey/MonkeyDev/tar.gz/$branch" "$MonkeyDevPath" "MonkeyDev base"
downloadGithubTarball "https://codeload.github.com/AloneMonkey/MonkeyDev-Xcode-Templates/tar.gz/$branch" "$MonkeyDevPath/templates" "Xcode templates"

#下载frida-ios-dump
echo "Moving frida-ios-dump from Resources..."
downloadFile "https://raw.githubusercontent.com/shadow-boy/MonkeyDev/master/Resource/dump.py" "$MonkeyDevPath/bin/dump.py"
downloadFile "https://raw.githubusercontent.com/shadow-boy/MonkeyDev/master/Resource/dump.js" "$MonkeyDevPath/bin/dump.js"
# cp Resource/dump.js $MonkeyDevPath/bin/dump.js
# cp Resource/dump.py $MonkeyDevPath/bin/dump.py
chmod +x "$MonkeyDevPath/bin/dump.py"

#创建符号链接
echo "Creating symlink to Xcode templates..."

#$userHome/Library/Developer/Xcode/Templates/MonkeyDev linkto $MonkeyDevPath/templates
userDevDir="$userHome/Library/Developer"
userTemplatesDir="$userDevDir/Xcode/Templates"

if [[ ! -d "$userTemplatesDir" ]]; then
	mkdir -p "$userTemplatesDir" || \
		panic $? "Failed to make directory: $userTemplatesDir"
		
	chown -R "$userName:$userGroup" "$userDevDir" || \
		panic $? "Failed to change ownership-group of $userDevDir"
fi

ln -fhs "$MonkeyDevPath/templates" "$userTemplatesDir/MonkeyDev"

#修改用户profile文件
echo "Modifying Bash personal initialization file..."

userBashProfileFile=`determineUserBashProfileFile`

addToFileIfMissing "$userBashProfileFile" "^(export)? *MonkeyDevPath=.*" "export MonkeyDevPath=$MonkeyDevPath"
addToFileIfMissing "$userBashProfileFile" "^(export)? *MonkeyDevDeviceIP=.*" "export MonkeyDevDeviceIP="
addToFileIfMissing "$userBashProfileFile" "^(export)? *PATH=.*(\\\$MonkeyDevPath\\/bin|${MonkeyDevPath//\//\\/}\\/bin).*" "export PATH=$MonkeyDevPath/bin:\$PATH"

#支持iphoneos command line tools
iosSdkPlatformPath=`getSdkProperty iphoneos PlatformPath`
macosSdkPlatformPath=`getSdkProperty macosx PlatformPath`

# specificationFile="/Applications/Xcode.app/Contents/Developer/Library/Xcode/Plug-ins/XCBSpecifications.ideplugin/Contents/Resources/Embedded-Device.xcspec"

# for xcode16
specificationFile=$(find /Applications/Xcode.app -name "Embedded-Device.xcspec" | head -n 1)




requireFile "$specificationFile" false

# backup
requireBackup "$specificationFile"

hasPackageTypeForCommandLineTool=`doesFileContain "$specificationFile" 'com.apple.package-type.mach-o-executable'`
hasProductTypeForCommandLineTool=`doesFileContain "$specificationFile" 'com.apple.product-type.tool'`

macosxSDKSpecificationsPath="$(cd $macosSdkPlatformPath/../../.. && pwd)/PlugIns/XCBSpecifications.ideplugin/Contents/Resources"
# echo $macosxSDKSpecificationsPath
packageTypesForMacOSXPath=$(find /Applications/Xcode.app -name "MacOSX Package Types.xcspec" | head -n 1)
productTypesForMacOSXPath=$(find /Applications/Xcode.app -name "MacOSX Product Types.xcspec" | head -n 1)



requireFile "$packageTypesForMacOSXPath" false
requireFile "$productTypesForMacOSXPath" false

if [[ $hasPackageTypeForCommandLineTool != "true" ]]; then
	machoDict=`readXcodeSpecificationById "$packageTypesForMacOSXPath" "com.apple.package-type.mach-o-executable"`
	writeDictToSpecification "$specificationFile" "$machoDict"
fi

if [[ $hasProductTypeForCommandLineTool != "true" ]]; then
	toolDict=`readXcodeSpecificationById "$productTypesForMacOSXPath" "com.apple.product-type.tool"`
	writeDictToSpecification "$specificationFile" "$toolDict"
fi

exit 0

3、An empty code signing identity is not valid when signing a binary for the 'Dynamic Library' product type.

点击这里的+号

添加 CODE_SIGNING_ALLOWED=NO 选项

这是因为已经编译生成过文件了,删除这个文件之后重新编译即可。

5、with ldid... /opt/MonkeyDev/bin/md: line 326: ldid: command not found 错误解决

这里执行了这个脚本/opt/MonkeyDev/bin/md。往这里面添加brew install 安装文件的目录即可

复制代码
sudo vim /opt/MonkeyDev/bin/md
相关推荐
liuyao_xianhui1 小时前
四数之和_优选算法(C++)双指针法总结
java·开发语言·c++·算法·leetcode·职场和发展
墨染点香2 小时前
LeetCode 刷题【93. 复原 IP 地址】
算法·leetcode·职场和发展
Asmalin5 小时前
【代码随想录day 29】 力扣 860.柠檬水找零
算法·leetcode·职场和发展
程序员小白条7 小时前
度小满运维开发一面
java·运维·python·职场和发展·运维开发
Asmalin14 小时前
【代码随想录day 29】 力扣 135.分发糖果
算法·leetcode·职场和发展
微笑尅乐14 小时前
多解法详解与边界处理——力扣7.整数反转
算法·leetcode·职场和发展
덕화17 小时前
模拟面试 - 第6轮
面试·职场和发展
元亓亓亓19 小时前
LeetCode热题--207. 课程表--中等
算法·leetcode·职场和发展
麻雀20252 天前
一键面试prompt
面试·职场和发展·prompt