Please take note that you don't need this method to decrypt the IPA file, if you already have the decrypted one downloaded from the net. This method applies to the app that you have directly purchased from App Store and want to decrypt it in order to be useful for others.
One of the decrypt methods is to use a jailbreak iPhone and run the script (source from pr0x.org Forum) below in iPhone to create the decrypted ipa.
To use this method you must have installed the app from App Store in jailbreak iPhone plus the following packages from Cydia
com.ericasadun.utilities gdb gawk zip ldid odcctools
Use the following commands in iPhone to install, if you don't like to use Cydia.
apt-get install com.ericasadun.utilities gdb gawk zip ldid odcctools
To find out the app names that your iPhone have installed, run this command in iPhone
find /var/mobile/Applications/ -iname *.app
and use this command to generated the decrypted ipa e.g.
./DCrypt.sh "Monkey Ball"
- DCrypt.sh Select all
#!/bin/sh
#
# DeCrypt - v1.1 (2008-10-21)
# - v1.1 (2008-10-21)
# FloydianSlip
#
# Heavily based on xcrack
#
# Many thanks to:
# puy0, SaladFork, Flox, Flawless
#
echo "DeCrypt 1.1 (2008-10-21)"
echo "FloydianSlip"
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 -v CFBundleExecutable "$tempLoc/Info.plist" 2>&1 | awk -F "] " '{ print $2 }')
AppVer=$(plutil -v CFBundleVersion "$tempLoc/Info.plist" 2>&1 | awk -F "] " '{ print $2 }')
AppDisplayName=$(plutil -v CFBundleDisplayName "$tempLoc/Info.plist" 2>&1 | awk -F "] " '{ print $2 }')
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 sharedlibrary load-rules \".*\" \".*\" none\r\n\
set inferior-auto-start-dyld off\r\n\
set sharedlibrary preload-libraries off\r\n\
set sharedlibrary load-dyld-symbols off\r\n\
handle all nostop\r\n\
break *0x2000\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 -s 'SignerIdentity' -v '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 $AppDisplayName | 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"
If you only want to manually get the decrypted binary for reverse engineering. Suppose the Application Executable is called AppExec and installed in /var/mobile/Applications. This is the script and using the gdb to dump the decrypted binary
Let's use a free app AdHoc Helper (by Erica Sadun) as example
otool -l `find /var/mobile/Applications -iname AdHoc` | grep cryptsize
output-> cryptsize 8192
# get the cryptsize say 8192
gdb `find /var/mobile/Applications -iname AdHoc`
(gdb) b *0x2000
Breakpoint 1 at 0x2000
(gdb) r
(gdb) x/20i 0x2000
(gdb) dump binary memory /var/root/dump.bin 0x2000 (0x2000+8192)
(gdb) kill
Kill the program being debugged? (y or n) y
(gdb) quit
cd /var/root/
cp `find /var/mobile/Applications -iname AdHoc` .
dd seek=4096 bs=1 conv=notrunc if=dump.bin of=AdHoc