Skip to content

Instantly share code, notes, and snippets.

@helvenk
Last active April 10, 2023 09:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save helvenk/bb4ac4c790c887a76228a36adb75b33d to your computer and use it in GitHub Desktop.
Save helvenk/bb4ac4c790c887a76228a36adb75b33d to your computer and use it in GitHub Desktop.
#!/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=$(cd $iosSdkPlatformPath/../../.. && pwd)/Developer/Library/Xcode/Plug-ins/XCBSpecifications.ideplugin/Contents/Resources/Embedded-Device.xcspec
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)/Developer/Library/Xcode/Plug-ins/XCBSpecifications.ideplugin/Contents/Resources"
# echo $macosxSDKSpecificationsPath
packageTypesForMacOSXPath="$macosxSDKSpecificationsPath/MacOSX Package Types.xcspec"
productTypesForMacOSXPath="$macosxSDKSpecificationsPath/MacOSX Product Types.xcspec"
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
@helvenk
Copy link
Author

helvenk commented Apr 10, 2023

xcode 14.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment