initial code for dumping imessages in a reasonable format
This commit is contained in:
224
dump-imessages/iphone-dataprotection/python_scripts/kernel_patcher.py
Executable file
224
dump-imessages/iphone-dataprotection/python_scripts/kernel_patcher.py
Executable file
@@ -0,0 +1,224 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import plistlib
|
||||
import zipfile
|
||||
import struct
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
from Crypto.Cipher import AES
|
||||
from util.lzss import decompress_lzss
|
||||
|
||||
devices = {"n82ap": "iPhone1,2",
|
||||
"n88ap": "iPhone2,1",
|
||||
"n90ap": "iPhone3,1",
|
||||
"n90bap": "iPhone3,2",
|
||||
"n92ap": "iPhone3,3",
|
||||
"n18ap": "iPod3,1",
|
||||
"n81ap": "iPod4,1",
|
||||
"k48ap": "iPad1,1",
|
||||
"n72ap": "iPod2,1",
|
||||
}
|
||||
|
||||
h=lambda x:x.replace(" ","").decode("hex")
|
||||
|
||||
#thx to 0x56
|
||||
patchs_ios6 = {
|
||||
"IOAESAccelerator enable UID" : (h("B0 F5 FA 6F 00 F0 92 80"), h("B0 F5 FA 6F 00 20 00 20")),
|
||||
"_PE_i_can_has_debugger" : (h("80 B1 43 F2 BE 01 C0 F2"), h("01 20 70 47 BE 01 C0 F2")),
|
||||
}
|
||||
|
||||
#https://github.com/comex/datautils0/blob/master/make_kernel_patchfile.c
|
||||
patchs_ios5 = {
|
||||
"CSED" : (h("df f8 88 33 1d ee 90 0f a2 6a 1b 68"), h("df f8 88 33 1d ee 90 0f a2 6a 01 23")),
|
||||
"AMFI" : (h("D0 47 01 21 40 B1 13 35"), h("00 20 01 21 40 B1 13 35")),
|
||||
"_PE_i_can_has_debugger" : (h("38 B1 05 49 09 68 00 29"), h("01 20 70 47 09 68 00 29")),
|
||||
"task_for_pid_0" : (h("00 21 02 91 ba f1 00 0f 01 91 06 d1 02 a8"), h("00 21 02 91 ba f1 00 0f 01 91 06 e0 02 a8")),
|
||||
"IOAESAccelerator enable UID" : (h("67 D0 40 F6"), h("00 20 40 F6")),
|
||||
#not stritcly required, useful for testing
|
||||
"getxattr system": ("com.apple.system.\x00", "com.apple.aaaaaa.\x00"),
|
||||
"IOAES gid": (h("40 46 D4 F8 54 43 A0 47"), h("40 46 D4 F8 43 A0 00 20")),
|
||||
#HAX to fit into the 40 char boot-args (redsn0w 0.9.10)
|
||||
"nand-disable-driver": ("nand-disable-driver\x00", "nand-disable\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||
}
|
||||
|
||||
patchs_ios4 = {
|
||||
"NAND_epoch" : ("\x90\x47\x83\x45", "\x90\x47\x00\x20"),
|
||||
"CSED" : ("\x00\x00\x00\x00\x01\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00", "\x01\x00\x00\x00\x01\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00"),
|
||||
"AMFI" : ("\x01\xD1\x01\x30\x04\xE0\x02\xDB", "\x00\x20\x01\x30\x04\xE0\x02\xDB"),
|
||||
"_PE_i_can_has_debugger" : (h("48 B1 06 4A 13 68 13 B9"), h("01 20 70 47 13 68 13 B9")),
|
||||
"IOAESAccelerator enable UID" : ("\x56\xD0\x40\xF6", "\x00\x00\x40\xF6"),
|
||||
"getxattr system": ("com.apple.system.\x00", "com.apple.aaaaaa.\x00"),
|
||||
}
|
||||
|
||||
patchs_armv6 = {
|
||||
"NAND_epoch" : (h("00 00 5B E1 0E 00 00 0A"), h("00 00 5B E1 0E 00 00 EA")),
|
||||
"CSED" : (h("00 00 00 00 01 00 00 00 80 00 00 00 00 00 00 00"), h("01 00 00 00 01 00 00 00 80 00 00 00 00 00 00 00")),
|
||||
"AMFI" : (h("00 00 00 0A 00 40 A0 E3 04 00 A0 E1 90 80 BD E8"), h("00 00 00 0A 00 40 A0 E3 01 00 A0 E3 90 80 BD E8")),
|
||||
"_PE_i_can_has_debugger" : (h("00 28 0B D0 07 4A 13 68 00 2B 02 D1 03 60 10 68"), h("01 20 70 47 07 4A 13 68 00 2B 02 D1 03 60 10 68")),
|
||||
"IOAESAccelerator enable UID" : (h("5D D0 36 4B 9A 42"), h("00 20 36 4B 9A 42")),
|
||||
"IOAES gid": (h("FA 23 9B 00 9A 42 05 D1"), h("00 20 00 20 9A 42 05 D1")),
|
||||
"nand-disable-driver": ("nand-disable-driver\x00", "nand-disable\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
}
|
||||
patchs_ios4_fixnand = {
|
||||
"Please reboot => jump to prepare signature": (h("B0 47 DF F8 E8 04 F3 E1"), h("B0 47 DF F8 E8 04 1D E0")),
|
||||
"prepare signature => jump to write signature": (h("10 43 18 60 DF F8 AC 04"), h("10 43 18 60 05 E1 00 20")),
|
||||
"check write ok => infinite loop" : (h("A3 48 B0 47 01 24"), h("A3 48 B0 47 FE E7"))
|
||||
}
|
||||
|
||||
#grab keys from redsn0w Keys.plist
|
||||
class IPSWkeys(object):
|
||||
def __init__(self, manifest):
|
||||
self.keys = {}
|
||||
buildi = manifest["BuildIdentities"][0]
|
||||
dc = buildi["Info"]["DeviceClass"]
|
||||
build = "%s_%s_%s" % (devices.get(dc,dc), manifest["ProductVersion"], manifest["ProductBuildVersion"])
|
||||
try:
|
||||
rs = plistlib.readPlist("Keys.plist")
|
||||
except:
|
||||
raise Exception("Get Keys.plist from redsn0w and place it in the current directory")
|
||||
for k in rs["Keys"]:
|
||||
if k["Build"] == build:
|
||||
self.keys = k
|
||||
break
|
||||
|
||||
def getKeyIV(self, filename):
|
||||
if not self.keys.has_key(filename):
|
||||
return None, None
|
||||
k = self.keys[filename]
|
||||
return k.get("Key",""), k.get("IV","")
|
||||
|
||||
def decryptImg3(blob, key, iv):
|
||||
assert blob[:4] == "3gmI", "Img3 magic tag"
|
||||
data = ""
|
||||
for i in xrange(20, len(blob)):
|
||||
tag = blob[i:i+4]
|
||||
size, real_size = struct.unpack("<LL", blob[i+4:i+12])
|
||||
if tag[::-1] == "DATA":
|
||||
assert size >= real_size, "Img3 length check"
|
||||
data = blob[i+12:i+size]
|
||||
break
|
||||
i += size
|
||||
return AES.new(key, AES.MODE_CBC, iv).decrypt(data)[:real_size]
|
||||
|
||||
|
||||
def main(ipswname, options):
|
||||
ipsw = zipfile.ZipFile(ipswname)
|
||||
manifest = plistlib.readPlistFromString(ipsw.read("BuildManifest.plist"))
|
||||
kernelname = manifest["BuildIdentities"][0]["Manifest"]["KernelCache"]["Info"]["Path"]
|
||||
devclass = manifest["BuildIdentities"][0]["Info"]["DeviceClass"]
|
||||
kernel = ipsw.read(kernelname)
|
||||
keys = IPSWkeys(manifest)
|
||||
|
||||
key,iv = keys.getKeyIV(kernelname)
|
||||
|
||||
if key == None:
|
||||
print "No keys found for kernel"
|
||||
return
|
||||
|
||||
print "Decrypting %s" % kernelname
|
||||
kernel = decryptImg3(kernel, key.decode("hex"), iv.decode("hex"))
|
||||
assert kernel.startswith("complzss"), "Decrypted kernelcache does not start with \"complzss\" => bad key/iv ?"
|
||||
|
||||
print "Unpacking ..."
|
||||
kernel = decompress_lzss(kernel)
|
||||
assert kernel.startswith("\xCE\xFA\xED\xFE"), "Decompressed kernelcache does not start with 0xFEEDFACE"
|
||||
|
||||
patchs = patchs_ios5
|
||||
if devclass in ["n82ap", "n72ap"]:
|
||||
print "Using ARMv6 kernel patches"
|
||||
patchs = patchs_armv6
|
||||
elif manifest["ProductVersion"].startswith("4."):
|
||||
print "Using iOS 4 kernel patches"
|
||||
patchs = patchs_ios4
|
||||
elif manifest["ProductVersion"].startswith("6."):
|
||||
print "Using iOS 6 kernel patches"
|
||||
patchs = patchs_ios6
|
||||
|
||||
if options.fixnand:
|
||||
if patchs != patchs_ios4:
|
||||
print "FAIL : use --fixnand with iOS 4.x IPSW"
|
||||
return
|
||||
patchs.update(patchs_ios4_fixnand)
|
||||
kernelname = "fix_nand_" + kernelname
|
||||
print "WARNING : only use this kernel to fix NAND epoch brick"
|
||||
|
||||
for p in patchs:
|
||||
print "Doing %s patch" % p
|
||||
s, r = patchs[p]
|
||||
c = kernel.count(s)
|
||||
if c != 1:
|
||||
print "=> FAIL, count=%d, do not boot that kernel it wont work" % c
|
||||
else:
|
||||
kernel = kernel.replace(s,r)
|
||||
|
||||
outkernel = "%s.patched" % kernelname
|
||||
open(outkernel, "wb").write(kernel)
|
||||
print "Patched kernel written to %s" % outkernel
|
||||
|
||||
ramdiskname = manifest["BuildIdentities"][0]["Manifest"]["RestoreRamDisk"]["Info"]["Path"]
|
||||
key,iv = keys.getKeyIV("Ramdisk")
|
||||
ramdisk = ipsw.read(ramdiskname)
|
||||
|
||||
print "Decrypting %s" % ramdiskname
|
||||
ramdisk = decryptImg3(ramdisk, key.decode("hex"), iv.decode("hex"))
|
||||
|
||||
assert ramdisk[0x400:0x402] == "H+", "H+ magic not found in decrypted ramdisk => bad key/iv ?"
|
||||
|
||||
customramdisk = "myramdisk_%s.dmg" % devclass
|
||||
f = open(customramdisk, "wb")
|
||||
f.write(ramdisk)
|
||||
f.close()
|
||||
|
||||
if manifest["ProductVersion"].startswith("6."):
|
||||
print "Run ./build_ramdisk_ios6.sh %s" % customramdisk
|
||||
print "Then redsn0w -i %s -r %s -k %s -a \"-v rd=md0 amfi=0xff cs_enforcement_disable=1\"" % (ipswname, customramdisk, outkernel)
|
||||
return
|
||||
|
||||
build_cmd = "./build_ramdisk.sh %s %s %s %s %s" % (ipswname, ramdiskname, key, iv, customramdisk)
|
||||
rs_cmd = "redsn0w -i %s -r %s -k %s" % (ipswname, customramdisk, outkernel)
|
||||
rdisk_script="""#!/bin/sh
|
||||
|
||||
for VER in 4.2 4.3 5.0 5.1 6.0
|
||||
do
|
||||
if [ -f "/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$VER.sdk/System/Library/Frameworks/IOKit.framework/IOKit" ];
|
||||
then
|
||||
SDKVER=$VER
|
||||
echo "Found iOS SDK $SDKVER"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$SDKVER" == "" ]; then
|
||||
echo "iOS SDK not found"
|
||||
exit
|
||||
fi
|
||||
SDKVER=$SDKVER make -C ramdisk_tools
|
||||
|
||||
%s
|
||||
|
||||
if [ "$?" == "0" ]
|
||||
then
|
||||
echo "You can boot the ramdisk using the following command (fix paths)"
|
||||
echo "%s"
|
||||
echo "Add -a \\"-v rd=md0 nand-disable=1\\" for nand dump/read only access"
|
||||
fi
|
||||
""" % (build_cmd, rs_cmd)
|
||||
|
||||
scriptname="make_ramdisk_%s.sh" % devclass
|
||||
f=open(scriptname, "wb")
|
||||
f.write(rdisk_script)
|
||||
f.close()
|
||||
|
||||
print "Created script %s, you can use it to (re)build the ramdisk"% scriptname
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = OptionParser(usage="%prog [options] IPSW")
|
||||
parser.add_option("-f", "--fixnand",
|
||||
action="store_true", dest="fixnand", default=False,
|
||||
help="Apply NAND epoch fix kernel patches")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
if len(args) < 1:
|
||||
parser.print_help()
|
||||
else:
|
||||
main(args[0], options)
|
||||
Reference in New Issue
Block a user