破解从 AppStore 下载的 IPA 主要包括如下步骤:
1、去除可执行文件中的加密数据。
2、重新签名打包。
可以参考:http://tungchingkai.blogspot.com/2009/02/how-to-decrypt-iphone-ipa-file.html
如上的文章中附了一个 shell 脚本文件可以方便破解。
这个脚本文件的使用方法是:
1、通过 scp 或者其他工具,将 DCrypt.sh 拷贝到越狱设备上。
2、给文件增加可执行权限:chmod +x ./DCrypt.sh
3、执行破解:./DCrypt.sh UCBrowserHD
但是文章中附的 DCrypt.sh 比较老,
在最新的越狱系统下执行会出错,出错点:
1、plutil 的参数发生了变化。
2、gdb 断点位置需要改变,在 *0x2000 出断点会导出 gdb 出错,无法完成内存 dump。
针对如上问题,对这个工具进行了修改(https://gist.github.com/Proteas/4720822),亲测可用:
#!/bin/sh # # DeCrypt - v1.2 (2013-02-05) # - v1.1 (2008-10-21) # - v1.2 (2013-02-05) # FloydianSlip, Proteas # # Heavily based on xcrack # # Many thanks to: # puy0, SaladFork, Flox, Flawless # echo "DeCrypt 1.2 (2013-02-05)" echo "FloydianSlip, Proteas" echo if [ ! -e /usr/bin/plutil ]; then echo "Cannot find plutil (apt-get install com.ericasadun.utilities)" exit 1 fi if [ ! -e /usr/bin/gdb ]; then echo "Cannot find gdb (apt-get install gdb)" exit 1 fi if [ ! -e /usr/bin/otool ]; then echo "Cannot find otool (apt-get install odcctools)" exit 1 fi if [ ! -e /usr/bin/ldid ]; then echo "Cannot find otool (apt-get install ldid)" exit 1 fi if [ ! -e /usr/bin/awk ]; then echo "Cannot find awk (apt-get install gawk)" exit 1 fi if [ ! -e /usr/bin/zip ]; then echo "Cannot find zip (apt-get install zip)" exit 1 fi if [ $# -ne 1 ]; then echo "Usage: $(basename $0) <ApplicationName>" echo exit 1 fi AppInput=$1 if [ -d "$AppInput" ]; then tempLoc=$AppInput else echo "Locating $AppInput" tempLoc=$(find /var/mobile/Applications -iname "$AppInput.app") if [ -z "$tempLoc" ]; then echo "Unable to locate $AppInput" exit 1 fi AppCount=$(find /var/mobile/Applications -iname "$AppInput.app" | wc -l) if [ $AppCount -gt 1 ]; then echo "Found two installation directories:" find /var/mobile/Applications -iname "$AppInput.app" exit 1 fi fi AppPath=$(dirname "$tempLoc") AppName=$(basename "$tempLoc") AppExec=$(plutil -key CFBundleExecutable "$tempLoc/Info.plist") AppVer=$(plutil -key CFBundleVersion "$tempLoc/Info.plist") AppDisplayName=$(plutil -key CFBundleDisplayName "$tempLoc/Info.plist") if [ ! -d "$AppPath" ]; then echo "Unable to locate original installation directory" exit 1 fi if [ ! -d "$AppPath/$AppName" ]; then echo "Unable to locate .app directory" exit 1 fi if [ ! -e "$AppPath/$AppName/$AppExec" ]; then echo "Unable to locate executable" exit 1 fi echo "Found $AppName" echo "Creating directories" WorkDir="/tmp/DecryptApp-$(date +%Y%m%d-%H%M%S)" NewAppDir="$HOME/Documents/Decrypted" if [ -e "$WorkDir" ]; then rm -rf "$WorkDir" fi mkdir -p "$WorkDir" if [ ! -e "$NewAppDir" ]; then mkdir -p "$NewAppDir" fi if [ ! -d "$WorkDir" -o ! -d "$NewAppDir" ]; then echo "Unable to create Directories" exit 1 fi echo "Copying application files" cp -a "$AppPath/$AppName/" "$WorkDir/" if [ ! -e "$WorkDir/$AppName/$AppExec" ]; then echo "Unable to copy application files" rm -fr "$WorkDir" exit 1 fi echo "Analyzing application" CryptID=$(otool -l "$WorkDir/$AppName/$AppExec" | grep cryptid | awk '{print $2}') if [ $CryptID -ne "1" ]; then echo "Application is not encrypted" rm -fr "$WorkDir" exit 1 fi CryptSize=$(otool -l "$WorkDir/$AppName/$AppExec" | grep cryptsize | awk '{print $2}') if [ ! $CryptSize ]; then echo "Unable to find CryptSize" rm -fr "$WorkDir" exit 1 fi CryptOff=$(otool -l "$WorkDir/$AppName/$AppExec" | grep cryptoff | awk '{print $2}') if [ ! $CryptOff ]; then echo "Unable to find CryptOff" rm -fr "$WorkDir" exit 1 fi echo "Locating and patching CryptID" # "/System/Library/Frameworks" in hex PathAsHex="2f53797374656d2f4c6962726172792f4672616d65776f726b73" # - Convert to hex on 1 long line, only take stuff before the path string, # - Convert to 1 byte set per line, find 0x01 (line number is offset in the real file), # - Strip newlines, reverse the order oneLocations=($(od -A n -t x1 -v "$WorkDir/$AppName/$AppExec" | \ tr -d ' ','\n' | \ sed "s/$PathAsHex.*\$//" | \ sed "s/../&\n/g" | \ grep -n -s 01 | \ cut -d : -f 1 | \ sort -nr | \ tr "\n" " ")) for TryOffset in "${oneLocations[@]}"; do cp -a "$WorkDir/$AppName/$AppExec" "$WorkDir/$AppName/$AppExec.trying" foo=$(echo -ne "\x00" | dd bs=1 seek=$((TryOffset - 1)) conv=notrunc status=noxfer of="$WorkDir/$AppName/$AppExec.trying" 2>&1> /dev/null) cid=$(otool -l "$WorkDir/$AppName/$AppExec.trying" | grep cryptid | awk '{print $2}') if [ $cid -eq 0 ]; then break fi rm "$WorkDir/$AppName/$AppExec.trying" done if [ ! -e "$WorkDir/$AppName/$AppExec.trying" ]; then echo "Unable to find CryptID" rm -fr "$WorkDir" exit 1 fi mv "$WorkDir/$AppName/$AppExec.trying" "$WorkDir/$AppName/$AppExec" echo "Dumping unencrypted data from application" echo -e "set breakpoint pending on\r\n break \"UIApplicationMain\"\r\n commands 1\r\n\ dump memory $WorkDir/dump.bin 0x2000 $(($CryptSize + 0x2000))\r\n\ kill\r\n\ quit\r\n\ end\r\n\ start" > $WorkDir/batch.gdb foo=$(gdb -q -e "$AppPath/$AppName/$AppExec" -x $WorkDir/batch.gdb -batch 2>&1> /dev/null) rm $WorkDir/batch.gdb echo "Verifiying data dump" DumpSize=$(stat -c%s "$WorkDir/dump.bin") if [ "$DumpSize" != "$CryptSize" ]; then echo "Memory dump is not the right size or does not exist" rm -fr "$WorkDir" exit 1 fi echo "Replacing encrypted data with data dump" foo=$(dd seek=4096 bs=1 conv=notrunc if="$WorkDir/dump.bin" of="$WorkDir/$AppName/$AppExec" 2>&1> /dev/null) rm "$WorkDir/dump.bin" echo "Signing the application" foo=$(ldid -s "$WorkDir/$AppName/$AppExec" 2>&1> /dev/null) plutil -key 'SignerIdentity' -value 'Apple iPhone OS Application Signing' "$WorkDir/$AppName/Info.plist" 2>&1> /dev/null if [ -e "$WorkDir/$AppName/SC_Info" ]; then echo "Removing SC_Info" rm -fr "$WorkDir/$AppName/SC_Info" fi if [ -e "$WorkDir/$AppName/_CodeSignature" ]; then echo "Removing _CodeSignature" rm -fr "$WorkDir/$AppName/_CodeSignature" fi if [ -h "$WorkDir/$AppName/CodeResources" ]; then echo "Removing CodeResources" rm -fr "$WorkDir/$AppName/CodeResources" fi if [ -e "$WorkDir/$AppName/ResourceRules.plist" ]; then echo "Removing ResourceRules.plist" rm -fr "$WorkDir/$AppName/ResourceRules.plist" fi echo "Building .ipa" mkdir -p "$WorkDir/Payload" if [ ! -e "$WorkDir/Payload" ]; then echo "Failed to create Payload directory" rm -fr "$WorkDir" exit 1 fi mv "$WorkDir/$AppName" "$WorkDir/Payload/" echo "Copying iTunesArtwork" if [ -e "$AppPath/iTunesArtwork" ]; then cp -a "$AppPath/iTunesArtwork" "$WorkDir/" else echo "Unable to find iTunesArtwork" fi echo "Compressing the .ipa" IPAName=$NewAppDir/$(echo $AppName | sed -e "s: :_:g")-v$AppVer.ipa cd "$WorkDir" zip -m -r "$IPAName" * 2>&1> /dev/null cd - 2>&1> /dev/null if [ ! -e "$IPAName" ]; then echo "Failed to compress the .ipa" rm -fr "$WorkDir" exit 1 fi echo "Removing temporary files" rm -rf "$WorkDir" echo "Done" echo "Created decrypted .ipa at $IPAName"