Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # modified by stoker25 for the reset glitch loader
- # modified by GliGli and Tiros for the reset glitch hack
- # you might need to fill in this
- secret_1BL = "\xDD\x88\xAD\x0C\x9E\xD6\x69\xE7\xB5\x67\x94\xFB\x68\x56\x3E\xFA"
- # >>>VERY<<< important, FILL THIS IN! \x before each 2 bytes
- cpukey = "\x5A\xB7\xC0\xBB\x13\x42\xEE\x98\xA8\x31\x93\x9F\x9B\xDC\x2A\x83"
- # modified by stoker25 for the reset glitch loader
- # modified by GliGli and Tiros for the reset glitch hack
- # so we can do updates properly
- SCRIPT_VERSION = 0x03
- RGL_BUILD = 0x05
- OrigHeader = None
- Keyvault = None
- SMC = None
- CB_A = None
- CB_A_crypted = None
- CB_B = None
- CB_B_crypted = None
- CD = None
- CD_plain = None
- CE = None
- CE_plain = None
- CF = None
- CF1 = None
- CG = None
- CG1 = None
- RGLP = None
- # Import Psyco if available
- try:
- import psyco
- psyco.full()
- except ImportError:
- pass
- # first, unpack base input image. We are ignoring any updates here
- import hmac, sha, struct, sys, binascii
- try:
- import Crypto.Cipher.ARC4 as RC4
- except ImportError:
- print "Error importing Crypto.Cipher.ARC4 - please install python-crypto!"
- print "You can get it from http://www.dlitz.net/software/pycrypto/"
- sys.exit(-1)
- def unpack_base_image(image):
- global OrigHeader, SMC, CB_A, CB_B, CD, CE, CF, CF1, CG, CG1, Keyvault
- OrigHeader = image[:0x200]
- if image[0x205] == "\xFF" or image[0x415] == "\xFF" or image[0x200] == "\xFF":
- print "EDC'ed - will unedc."
- res = ""
- for s in range(0, len(image), 528):
- res += image[s:s+512]
- image = res
- unpackstring = "!HHLLL64s5LLLLLLLL"
- (id1, build, flags, bloffset, size0, copyright, z0, z1, z2, z3, r7, size1, r3, r4, z5, z6, smc_len, smc_start) = struct.unpack(unpackstring, image[:struct.calcsize(unpackstring)])
- #assert not (z0 or z1 or z2 or z3 or z5 or z6), "zeros are not zero."
- block_offset = bloffset
- SMC = image[smc_start:smc_start+smc_len]
- Keyvault = image[0x4000:0x8000]
- assert smc_len == 0x3000, "never saw an SMC != 0x3000 bytes"
- semi = 0
- for block in range(30):
- (block_id, block_build, block_flags, block_entry_point, block_size) = struct.unpack("!2sHLLL", image[block_offset:block_offset+16])
- block_size += 0xF
- block_size &= ~0xF
- id = ord(block_id[1]) & 0xF
- print "Found %dBL (build %d) at %08x" % (id, block_build, block_offset)
- data = image[block_offset:block_offset+block_size]
- if id == 2:
- if semi == 0:
- CB_A = data
- semi = 1
- elif semi ==1:
- CB_B = data
- semi = 0
- elif id == 4:
- CD = data
- elif id == 5:
- CE = data
- block_offset += block_size
- if id == 5:
- break
- assert CB_A and CD and CE
- base_size = 0x8000 + len(CB_A) + len(CD) + len(CE)
- if CB_B:
- base_size += len(CB_B)
- base_size += 16383
- base_size &=~ 16383
- patch_size = 0x10000
- if image[0x71] == "\x02":
- patch_size = 0x20000
- base_size += 0x10000
- patch_offset = base_size
- CF = image[patch_offset:patch_offset + 0x4450]
- CF1 = image[patch_offset + patch_size:patch_offset + 0x4450 + patch_size]
- CG = image[patch_offset + 0x4450:patch_offset + patch_size]
- CG1 = image[patch_offset + 0x4450 + patch_size:patch_offset + (patch_size * 2)]
- #build = 0
- #if not CF[:2] == "\x43\x46" or not CG[:2] == "\x43\x47":
- # CF = None
- # CG = None
- #else:
- # build = build(CF)
- # print "Found 5BL-0 (build %d) at %08x" % (build, patch_offset)
- #if not CF1[:2] == "\x43\x46" or not CG1[:2] == "\x43\x47":
- # CF1 = None
- # CG1 = None
- #else:
- # build = build(CF1)
- # print "Found 5BL-1 (build %d) at %08x" % (build, patch_offset + patch_size)
- def unpack_update(image):
- global CF, CG
- block_offset = 0
- for block in range(30):
- (block_id, block_build, block_flags, block_entry_point, block_size) = struct.unpack("!2sHLLL", image[block_offset:block_offset+16])
- block_size += 0xF
- block_size &= ~0xF
- id = ord(block_id[1]) & 0xF
- print "Found %dBL (build %d) at %08x" % (id, block_build, block_offset)
- data = image[block_offset:block_offset+block_size]
- if id == 6:
- CF = data
- elif id == 7:
- CG = data
- block_offset += block_size
- if id == 7:
- break
- def build(data):
- return struct.unpack(">H", data[2:4])[0]
- def decrypt_CB(CB):
- secret = secret_1BL
- key = hmac.new(secret, CB[0x10:0x20], sha).digest()[0:0x10]
- CB = CB[0:0x10] + key + RC4.new(key).decrypt(CB[0x20:])
- open("output/Cb_dec_key.bin", "wb").write(key)
- return CB
- def decrypt_CB_Cpu(CB):
- assert cpukey
- secret = secret_1BL
- h = hmac.new(secret,None, sha);
- h.update(CB[0x10:0x20]);
- h.update(cpukey);
- key = h.digest()[0:0x10]
- CB = CB[0:0x10] +key+ RC4.new(key).decrypt(CB[0x20:])
- return CB
- def decrypt_CB_B(CB_B, CB_A):
- assert cpukey or build(CB_B) < 1920
- secret = CB_A[0x10:0x20]
- if build(CB_B) >= 1920:
- key = hmac.new(secret, CB_B[0x10:0x20] + cpukey, sha).digest()[0:0x10]
- CB_B = CB_B[0:0x10] + key + RC4.new(key).decrypt(CB_B[0x20:])
- return CB_B
- def decrypt_CD(CD, CB):
- # enable this code if you want to extract CD from a flash image and you know the cup key.
- # disable this when this is a zero-paired image.
- assert cpukey or build(CD) < 1920 or build(CD) >= 9450
- secret = CB[0x10:0x20]
- key = hmac.new(secret, CD[0x10:0x20], sha).digest()[0:0x10]
- if build(CD) >= 1920:
- if build(CD) < 9450:
- key = hmac.new(cpukey, key, sha).digest()[0:0x10]
- CD = CD[0:0x10] + key + RC4.new(key).decrypt(CD[0x20:])
- return CD
- def decrypt_CE(CE, CD):
- secret = CD[0x10:0x20]
- key = hmac.new(secret, CE[0x10:0x20], sha).digest()[0:0x10]
- CE = CE[0:0x20] + RC4.new(key).decrypt(CE[0x20:])
- return CE
- def decrypt_CF(CF):
- secret = secret_1BL
- key = hmac.new(secret, CF[0x20:0x30], sha).digest()[0:0x10]
- CF = CF[0:0x20] + key + RC4.new(key).decrypt(CF[0x30:])
- return CF
- def decrypt_CG(CG, CF):
- secret = CF[0x330:0x330+0x10]
- key = hmac.new(secret, CG[0x10:0x20], sha).digest()[0:0x10]
- CG = CG[:0x10] + key + RC4.new(key).decrypt(CG[0x20:])
- return CG
- def decrypt_SMC(SMC):
- key = [0x42, 0x75, 0x4e, 0x79]
- res = ""
- for i in range(len(SMC)):
- j = ord(SMC[i])
- mod = j * 0xFB
- res += chr(j ^ (key[i&3] & 0xFF))
- key[(i+1)&3] += mod
- key[(i+2)&3] += mod >> 8
- return res
- def decrypt_CB(CB):
- secret = secret_1BL
- key = hmac.new(secret, CB[0x10:0x20], sha).digest()[0:0x10]
- CB = CB[0:0x10] + key + RC4.new(key).decrypt(CB[0x20:])
- open("output/Cb_dec_key.bin", "wb").write(key)
- return CB
- def encrypt_CB(CB):
- secret = secret_1BL
- key = hmac.new(secret, CB[0x10:0x20], sha).digest()[0:0x10]
- CB = CB[0:0x20] + RC4.new(key).encrypt(CB[0x20:])
- return CB, CB[0x10:0x20], key
- def decrypt_CB_B(CB_B, CB_A):
- assert cpukey or build(CB_B) < 1920
- secret = CB_A[0x10:0x20]
- key = hmac.new(secret, CB_B[0x10:0x20] + cpukey, sha).digest()[0:0x10]
- CB_B = CB_B[0:0x10] + key + RC4.new(key).decrypt(CB_B[0x20:])
- return CB_B
- def encrypt_CB_Cpu(CB_B, CB_A_key):
- assert cpukey
- secret = CB_A_key
- open("output/Cb_enc_secret.bin", "wb").write(secret)
- h = hmac.new(secret,None, sha);
- h.update(CB_B[0x10:0x20]);
- h.update(cpukey);
- key = h.digest()[0:0x10]
- CB_B = CB_B[0:0x20] + RC4.new(key).encrypt(CB_B[0x20:])
- return CB_B, key
- def encrypt_CB_B(CB_B, CB_A_key):
- secret = CB_A_key
- open("output/Cb_enc_secret.bin", "wb").write(secret)
- key = hmac.new(secret, CB_B[0x10:0x20] + cpukey, sha).digest()[0:0x10]
- CB_B = CB_B[0:0x20] + RC4.new(key).encrypt(CB_B[0x20:])
- return CB_B, key
- def encrypt_CD(CD, CB_key):
- secret = CB_key
- key = hmac.new(secret, CD[0x10:0x20], sha).digest()[0:0x10]
- CD = CD[0:0x20] + RC4.new(key).encrypt(CD[0x20:])
- return CD, key
- def encrypt_CE(CE, CD_key):
- secret = CD_key
- key = hmac.new(secret, CE[0x10:0x20], sha).digest()[0:0x10]
- CE = CE[0:0x20] + RC4.new(key).encrypt(CE[0x20:])
- return CE
- def encrypt_CF(CF):
- secret = secret_1BL
- key = hmac.new(secret, CF[0x20:0x30], sha).digest()[0:0x10]
- CF_key = CF[0x330:0x330+0x10]
- CF = CF[0:0x30] + RC4.new(key).encrypt(CF[0x30:])
- return CF, CF_key
- def encrypt_CG(CG, CF_key):
- secret = CF_key
- key = hmac.new(secret, CG[0x10:0x20], sha).digest()[0:0x10]
- CG = CG[0:0x20]+ RC4.new(key).encrypt(CG[0x20:])
- return CG
- def encrypt_SMC(SMC):
- key = [0x42, 0x75, 0x4e, 0x79]
- res = ""
- for i in range(len(SMC)):
- j = ord(SMC[i]) ^ (key[i&3] & 0xFF)
- mod = j * 0xFB
- res += chr(j)
- key[(i+1)&3] += mod
- key[(i+2)&3] += mod >> 8
- return res
- # CB_patches is an array of patchsets, a patchset is a version number followed by an array of patches, a patch is 3 ints: [offset,plaintext,patch]
- CB_patches = [[9188,[[0x5678,0x60,0x00,0x00,0x00]]]]
- def int_to_str(i):
- return [chr((i>>24) & 0xff),chr((i>>16) & 0xff),chr((i>>8) & 0xff),chr(i & 0xff)]
- def patch_CB_old(CB):
- found = False
- for versions in CB_patches:
- if build(CB) == versions[0]:
- print "patchset for %d found, %d patch(es)" % (versions[0],len(versions[1]))
- found = True
- for patches in versions[1]:
- plain = int_to_str(patches[1])
- patch = int_to_str(patches[2])
- patched = ""
- for i in range(4):
- CB = CB[:patches[0]+i] + chr(patches[i+1]) + CB[patches[0]+i+1:]
- #patched = patched + chr(ord(patch[i]))
- #keystream = ord(plain[i]) ^ ord(CB[i+patches[0]])
- #patched = patched + patch[i] #chr(keystream ^ ord(patch[i]))
- #CB = CB[:patches[0]] + patched + CB[patches[0]+4:]
- assert found,"can't patch that CB"
- return CB
- def patch_CB_B(CB):
- found = False
- for versions in CB_patches:
- if build(CB) == versions[0]:
- print "patchset for %d found, %d patch(es)" % (versions[0],len(versions[1]))
- found = True
- for patches in versions[1]:
- for i in range(len(patches)-1):
- CB = CB[:patches[0]+i] + chr(patches[i+1]) + CB[patches[0]+i+1:]
- if not found:
- print" ! Warning: can't patch that CB, here are the current supported versions:"
- for versions in CB_patches:
- print " - %s" % versions[0]
- return CB
- # SMC_patches is an array of patchsets, a patchset is a crc32 of the image minus first 4 bytes, human readable version info and an array of patches, a patch is: [offset,byte0,byte1,...]
- SMC_patches = [[0xf9c96639,"Trinity, version 3.1",[[0x13b3,0x00,0x00]]],
- [0x5b3aed00,"Jasper, version 2.3",[[0x12ba,0x00,0x00]]],
- [0x9ad5b7ee,"Zephyr, version 1.10",[[0x1257,0x00,0x00]]],
- [0x7e5bc217,"Zephyr, version 1.13",[[0x12a3,0x00,0x00]]],
- [0x1d0c613e,"Falcon, version 1.6",[[0x12a3,0x00,0x00]]]]
- def patch_SMC(SMC):
- found = False
- smc_crc = binascii.crc32(SMC[4:]) & 0xffffffff
- print "CRC32: %x" % (smc_crc)
- for versions in SMC_patches:
- if smc_crc == versions[0]:
- print "patchset \"%s\" matches, %d patch(es)" % (versions[1],len(versions[2]))
- found = True
- for patches in versions[2]:
- for i in range(len(patches)-1):
- SMC = SMC[:patches[0]+i] + chr(patches[i+1]) + SMC[patches[0]+i+1:]
- if not found:
- print" ! Warning: can't patch that SMC, here are the current supported versions:"
- for versions in SMC_patches:
- print " - %s" % versions[1]
- return SMC
- def allzero(string):
- for x in string:
- if ord(x):
- return False
- return True
- def allFF(string):
- for x in string:
- if ord(x) != 0xFF:
- return False
- return True
- def calcedc(data):
- assert len(data) == 0x210
- val = 0
- for i in range(0x1066):
- if not i & 31:
- v = ~struct.unpack("<L", data[i/8:i/8+4])[0]
- val ^= v & 1
- v >>= 1
- if val & 1:
- val ^= 0x6954559
- val >>= 1
- val = ~val
- return data[:-4] + struct.pack("<L", (val << 6) & 0xFFFFFFFF)
- def addedc(data, block = 0, off_8 = "\x00" * 4):
- res = ""
- while len(data):
- d = (data[:0x200] + "\x00" * 0x200)[:0x200]
- data = data[0x200:]
- d += struct.pack("<L4B4s4s", block / 32, 0, 0xFF, 0, 0, off_8, "\0\0\0\0")
- d = calcedc(d)
- block += 1
- res += d
- return res
- import sys
- for i in sys.argv[1:]:
- image = open(i, "rb").read()[:1*1024*1024]
- if image[:2] == "\xFF\x4F":
- print " * found flash image, unpacking..."
- unpack_base_image(image)
- CB_A_crypted = CB_A
- CB_B_crypted = CB_B
- SMC = decrypt_SMC(SMC)
- elif image[:2] == "CB":
- print " * found (hopefully) decrypted CB"
- CB_A_crypted = None
- CB_A = image
- elif image[:4] == "RGLP" or image[:4] == "RLPF":
- print " * found RGLoader patch file"
- RGLP = image[4:]
- elif image[:2] == "CD" and allzero(image[0x20:0x230]):
- print " * found decrypted CD"
- CD_plain = image
- elif len(image) == 0x3000 and image.find("<Copyright 2001-") >= 0:
- print " * found decrypted SMC"
- SMC = image
- elif len(image) == 0x3000:
- print " * found encrypted SMC (i hope so)"
- SMC = decrypt_SMC(image)
- else:
- raise " * unknown image found in file %s!" % i
- print " * we found the following parts:"
- print "SMC: %d.%d" %(ord(SMC[0x101]),ord(SMC[0x102]))
- print "CB_A:", CB_A and build(CB_A) or "missing"
- print "CB_B:", CB_B and build(CB_B) or "missing"
- print "CD (image):", CD and build(CD) or "missing"
- print "CD (decrypted):", CD_plain and build(CD_plain) or "missing"
- print "CE (image): ", CE and build(CE) or "missing"
- print "CF0: ", CF and build(CF) or "missing"
- print "CF1: ", CF1 and build(CF1) or "missing"
- print " * checking for proper 1BL key...",
- sum = 0
- for v in secret_1BL:
- sum = sum + ord(v)
- assert sum == 0x983, "you need to fill in secret_1BL properly!"
- print "ok"
- print " * decrypting..."
- CB_A = decrypt_CB(CB_A_crypted)
- if not CB_B:
- CD = decrypt_CD(CD, CB_A)
- CE = decrypt_CE(CE, CD)
- else:
- CB_B = decrypt_CB_B(CB_B, CB_A)
- if not allzero(CD[0x40:0x140]):
- CD = decrypt_CD(CD, CB_B)
- CE = decrypt_CE(CE, CD)
- CF = decrypt_CF(CF)
- CF1 = decrypt_CF(CF1)
- open("output/SMC_orig.bin", "wb").write(SMC)
- open("output/CB_A_orig.bin", "wb").write(CB_A)
- if CB_B:
- open("output/CB_B_orig.bin", "wb").write(CB_B)
- open("output/CD_orig.bin", "wb").write(CD)
- open("output/CE_orig.bin", "wb").write(CE)
- open("output/CF_orig.bin", "wb").write(CF)
- open("output/CF1_dec.bin", "wb").write(CF1)
- print " * checking if all files decrypted properly...",
- assert allzero(SMC[-4:])
- assert allzero(CB_A[0x263:0x273])
- assert allzero(CD[0x40:0x140])
- assert allzero(CE[0x20:0x28])
- print "ok"
- print " * checking required versions...",
- assert CD_plain, "you need a decrypted CD"
- print "ok"
- zephyr_builds = [4578]
- falcon_builds = [5771]
- jasper_builds = [6750]
- trinity_builds = [9188]
- print " * this image will be valid *only* for:",
- if build(CB_A) in zephyr_builds: print "zephyr",
- if build(CB_A) in falcon_builds: print "falcon",
- if build(CB_A) in jasper_builds: print "jasper",
- if build(CB_A) in trinity_builds: print "trinity (slim)",
- print
- Final = ""
- print " * patching SMC..."
- SMC = patch_SMC(SMC)
- CD = CD_plain
- if CB_B:
- print " * patching CB_B..."
- CB_B = patch_CB_B(CB_B)
- print " * zero-pairing..."
- if CB_B:
- CB_B = CB_B[0:0x20] + "\0" * 0x20 + CB_B[0x40:]
- else:
- CB_A = CB_A[0:0x20] + "\0" * 0x20 + CB_A[0x40:]
- CF = CF[0:0x21c] + "\0" * 4 + CF[0x220:]
- CF1 = CF1[0:0x21c] + "\0" * 4 + CF1[0x220:]
- c = "zeropair image"
- open("output/CB_A_patched.bin", "wb").write(CB_A)
- if CB_B:
- open("output/CB_B_patched.bin", "wb").write(CB_B)
- open("output/SMC_patched.bin", "wb").write(SMC)
- print " * constructing new image..."
- base_size = 0x8000 + len(CB_A) + len(CD) + len(CE)
- if CB_B:
- base_size += len(CB_B)
- base_size += 16383
- base_size &=~ 16383
- patch_size = 0x10000
- if OrigHeader[0x71] == "\x02":
- patch_size = 0x20000
- base_size += 0x10000
- patch_offset = base_size
- print " * base size: %x" % base_size
- random = "\0" * 16
- SMC = encrypt_SMC(SMC)
- if not CB_B:
- CB_A, CB_A_key, CB_A_key2 = encrypt_CB(CB_A)
- CD, CD_key = encrypt_CD(CD, CB_A_key2)
- CE = encrypt_CE(CE, CD_key)
- else:
- CB_A, CB_A_key, CB_A_key2 = encrypt_CB(CB_A)
- CB_B, CB_B_key = encrypt_CB_B(CB_B, CB_A_key2)
- CD, CD_key = encrypt_CD(CD, CB_B_key)
- CE = encrypt_CE(CE, CD_key)
- CF, CF_key = encrypt_CF(CF)
- CF1, CF1_key = encrypt_CF(CF1)
- if CB_B:
- open("output/CB_B_enc.bin", "wb").write(CB_B)
- print " * Flash Layout:"
- def add_to_flash(d, w, offset = 0):
- global Final
- print "0x%08x..0x%08x (0x%08x bytes) %s" % (offset + len(Final), offset + len(Final) + len(d) - 1, len(d), w)
- Final += d
- def pad_to(loc):
- global Final
- pad = "\0" * (loc - len(Final))
- add_to_flash(pad, "Padding")
- add_to_flash(OrigHeader[:0x200], "Header")
- if RGLP:
- add_to_flash(RGLP, "RGLoader Patch")
- pad_to(0x1000)
- add_to_flash(SMC, "SMC")
- add_to_flash(Keyvault, "Keyvault")
- if CB_B:
- add_to_flash(CB_A, "CB_A %d" % build(CB_A))
- add_to_flash(CB_B, "CB_B %d" % build(CB_B))
- else:
- add_to_flash(CB_A, "CB_A %d" % build(CB_A))
- add_to_flash(CD, "CD %d" % build(CD))
- add_to_flash(CE, "CE %d" % build(CE))
- pad_to(patch_offset)
- add_to_flash(CF, "CF %d" % build(CF))
- add_to_flash(CG, "CG %d" % build(CG))
- add_to_flash(CF1, "CF1 %d" % build(CF1))
- add_to_flash(CG1, "CG1 %d" % build(CG1))
- print " * Encoding EDC..."
- Final = addedc(Final)
- open("output/image_00000000.edc", "wb").write(Final)
- print "------------- Written into output/image_00000000.edc"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement