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
相关推荐
爱coding的橙子2 小时前
每日算法刷题Day77:10.22:leetcode 二叉树bfs18道题,用时3h
算法·leetcode·职场和发展
Swift社区2 小时前
LeetCode 404:左叶子之和(Sum of Left Leaves)
算法·leetcode·职场和发展
野蛮人6号4 小时前
力扣热题100道之238除自身以外数组的乘积
算法·leetcode·职场和发展
程序员小远6 小时前
如何编写自动化测试用例?
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
阿啄debugIT9 小时前
HashMap为什么线程不安全? ConcurrentHashMap如何保证线程安全? AQS如何实现锁的获取与释放?用男女关系进行解释,一看就懂
经验分享·职场和发展·系统架构·软件工程·1024程序员节
西阳未落17 小时前
LeetCode——二分(进阶)
算法·leetcode·职场和发展
吃着火锅x唱着歌1 天前
LeetCode 668.乘法表中第k小的数
算法·leetcode·职场和发展
小欣加油1 天前
leetcode 844 比较含退格的字符串
算法·leetcode·职场和发展