Guest User

fatbuild.py

a guest
Sep 9th, 2011
1,170
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # modified by GliGli and Tiros for the reset glitch hack
  2.  
  3. # you might need to fill in this
  4. secret_1BL = "\xDD\x88\xAD\x0C\x9E\xD6\x69\xE7\xB5\x67\x94\xFB\x68\x56\x3E\xFA"
  5. cpukey = ""
  6.  
  7. XELL_BASE_FLASH = 0xc0000
  8. CODE_BASE = 0x1c000000
  9.  
  10. # don't change anything from here.
  11.  
  12. # so we can do updates properly
  13. SCRIPT_VERSION = 0x01
  14.  
  15. Keyvault = None
  16. SMC = None
  17. CB_A = None
  18. CB_B = None
  19. CD = None
  20. CD_plain = None
  21. CE = None
  22. CF = None
  23. CG = None
  24. Xell = ""
  25. Exploit = None
  26.  
  27. #if secret_1BL is None:
  28. #   secret_1BL = open("key_1BL.bin", "rb").read()
  29.  
  30.  # Import Psyco if available
  31. try:
  32.     import psyco
  33.     psyco.full()
  34. except ImportError:
  35.     pass
  36.  
  37. # first, unpack base input image. We are ignoring any updates here
  38. import hmac, sha, struct, sys, binascii
  39. try:
  40.     import Crypto.Cipher.ARC4 as RC4
  41. except ImportError:
  42.     print "Error importing Crypto.Cipher.ARC4 - please install python-crypto!"
  43.     print "You can get it from http://www.dlitz.net/software/pycrypto/"
  44.     sys.exit(-1)
  45.  
  46. def unpack_base_image(image):
  47.     global SMC, CB_A, CB_B, CD, CE, Keyvault
  48.  
  49.     if image[0x205] == "\xFF" or image[0x415] == "\xFF" or image[0x200] == "\xFF":
  50.         print "ECC'ed - will unecc."
  51.         res = ""
  52.         for s in range(0, len(image), 528):
  53.             res += image[s:s+512]
  54.         image = res
  55.  
  56.     unpackstring = "!HHLLL64s5LLLLLLLL"
  57.     (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)])
  58.     #assert not (z0 or z1 or z2 or z3 or z5 or z6), "zeros are not zero."
  59.  
  60.     block_offset = bloffset
  61.  
  62.     SMC = image[smc_start:smc_start+smc_len]
  63.     Keyvault = image[0x4000:0x8000]
  64.  
  65.     assert smc_len == 0x3000, "never saw an SMC != 0x3000 bytes"
  66.     semi = 0
  67.     for block in range(30):
  68.         (block_id, block_build, block_flags, block_entry_point, block_size) = struct.unpack("!2sHLLL", image[block_offset:block_offset+16])
  69.         block_size += 0xF
  70.         block_size &= ~0xF
  71.         id = ord(block_id[1]) & 0xF
  72.  
  73.         print "Found %dBL (build %d) at %08x" % (id, block_build, block_offset)
  74.         data = image[block_offset:block_offset+block_size]
  75.        
  76.         if id == 2:
  77.             if semi == 0:
  78.                 CB_A = data
  79.                 semi = 1
  80.             elif semi ==1:
  81.                 CB_B = data
  82.                 semi = 0
  83.  
  84.         elif id == 4:
  85.             CD = data
  86.         elif id == 5:
  87.             CE = data
  88.        
  89.         block_offset += block_size
  90.  
  91.         if id == 5:
  92.             break
  93.  
  94.     assert CB_A and CD
  95.  
  96. def unpack_update(image):
  97.     global CF, CG
  98.    
  99.     block_offset = 0
  100.     for block in range(30):
  101.         (block_id, block_build, block_flags, block_entry_point, block_size) = struct.unpack("!2sHLLL", image[block_offset:block_offset+16])
  102.         block_size += 0xF
  103.         block_size &= ~0xF
  104.         id = ord(block_id[1]) & 0xF
  105.  
  106.         print "Found %dBL (build %d) at %08x" % (id, block_build, block_offset)
  107.         data = image[block_offset:block_offset+block_size]
  108.        
  109.         if id == 6:
  110.             CF = data
  111.         elif id == 7:
  112.             CG = data
  113.  
  114.         block_offset += block_size
  115.  
  116.         if id == 7:
  117.             break
  118.  
  119. def build(data):
  120.     return struct.unpack(">H", data[2:4])[0]
  121.  
  122. def decrypt_CB(CB):
  123.     secret = secret_1BL
  124.     key = hmac.new(secret, CB[0x10:0x20], sha).digest()[0:0x10]
  125.     CB = CB[0:0x10] + key + RC4.new(key).decrypt(CB[0x20:])
  126.     return CB
  127.  
  128. def decrypt_CB_Cpu(CB):
  129.     assert cpukey
  130.     secret = CB_A[0x10:0x20]
  131.     h = hmac.new(secret,None, sha);
  132.     h.update(CB[0x10:0x20]);
  133.     h.update(cpukey);
  134.     key = h.digest()[0:0x10]
  135.     CB = CB[0:0x10] +key+ RC4.new(key).decrypt(CB[0x20:])
  136.     return CB
  137.  
  138. def decrypt_CD(CD, CB):
  139. # enable this code if you want to extract CD from a flash image and you know the cup key.
  140. # disable this when this is a zero-paired image.
  141. #   assert cpukey or build(CD) < 1920
  142.     secret = CB[0x10:0x20]
  143.     key = hmac.new(secret, CD[0x10:0x20], sha).digest()[0:0x10]
  144. #   if build(CD) >= 1920:
  145. #       key = hmac.new(cpukey, key, sha).digest()[0:0x10]
  146.     CD = CD[0:0x10] + key + RC4.new(key).decrypt(CD[0x20:])
  147.     return CD
  148.  
  149. def decrypt_CE(CE, CD):
  150.     secret = CD[0x10:0x20]
  151.     key = hmac.new(secret, CE[0x10:0x20], sha).digest()[0:0x10]
  152.     CE = CE[0:0x10] + key + RC4.new(key).decrypt(CE[0x20:])
  153.     return CE
  154.  
  155. def decrypt_CF(CF):
  156.     secret = secret_1BL
  157.     key = hmac.new(secret, CF[0x20:0x30], sha).digest()[0:0x10]
  158.     CF = CF[0:0x20] + key + RC4.new(key).decrypt(CF[0x30:])
  159.     return CF
  160.  
  161. def decrypt_CG(CG, CF):
  162.     secret = CF[0x330:0x330+0x10]
  163.     key = hmac.new(secret, CG[0x10:0x20], sha).digest()[0:0x10]
  164.     CG = CG[:0x10] + key + RC4.new(key).decrypt(CG[0x20:])
  165.     return CG
  166.  
  167. def decrypt_SMC(SMC):
  168.     key = [0x42, 0x75, 0x4e, 0x79]
  169.     res = ""
  170.     for i in range(len(SMC)):
  171.         j = ord(SMC[i])
  172.         mod = j * 0xFB
  173.         res += chr(j ^ (key[i&3] & 0xFF))
  174.         key[(i+1)&3] += mod
  175.         key[(i+2)&3] += mod >> 8
  176.     return res
  177.  
  178. def encrypt_CB(CB, random):
  179.     secret = secret_1BL
  180.     key = hmac.new(secret, random, sha).digest()[0:0x10]
  181.     CB = CB[0:0x10] + random + RC4.new(key).encrypt(CB[0x20:])
  182.     return CB, key
  183.  
  184. def encrypt_CB_Cpu(CB):
  185.     assert cpukey
  186.     secret = CB_A[0x10:0x20]
  187.     h = hmac.new(secret,None, sha);
  188.     h.update(CB[0x10:0x20]);
  189.     h.update(cpukey);
  190.     key = h.digest()[0:0x10]
  191.     CB = CB[0:0x20] + RC4.new(key).encrypt(CB[0x20:])
  192.     return CB, key
  193.  
  194. def encrypt_CD(CD, CB_key, random):
  195.     secret = CB_key
  196.     key = hmac.new(secret, random, sha).digest()[0:0x10]
  197.     CD = CD[0:0x10] + random + RC4.new(key).encrypt(CD[0x20:])
  198.     return CD, key
  199.  
  200. def encrypt_CE(CE, CD_key, random):
  201.     secret = CD_key
  202.     key = hmac.new(secret, random, sha).digest()[0:0x10]
  203.     CE = CE[0:0x10] + random + RC4.new(key).encrypt(CE[0x20:])
  204.     return CE
  205.  
  206. def encrypt_CF(CF, random):
  207.     secret = secret_1BL
  208.     key = hmac.new(secret, random, sha).digest()[0:0x10]
  209.     CF_key = CF[0x330:0x330+0x10]
  210.     CF = CF[0:0x20] + random + RC4.new(key).encrypt(CF[0x30:])
  211.     return CF, CF_key
  212.  
  213. def encrypt_CG(CG, CF_key, random):
  214.     secret = CF_key
  215.     key = hmac.new(secret, random, sha).digest()[0:0x10]
  216.     CG = CG[:0x10] + random + RC4.new(key).encrypt(CG[0x20:])
  217.     return CG
  218.  
  219. def encrypt_SMC(SMC):
  220.     key = [0x42, 0x75, 0x4e, 0x79]
  221.     res = ""
  222.     for i in range(len(SMC)):
  223.         j = ord(SMC[i]) ^ (key[i&3] & 0xFF)
  224.         mod = j * 0xFB
  225.         res += chr(j)
  226.         key[(i+1)&3] += mod
  227.         key[(i+2)&3] += mod >> 8
  228.     return res
  229.  
  230. # 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]
  231.  
  232. CB_patches = [[9188,[[0x4f08,0x409a0010,0x60000000],[0x5618,0x480018e1,0x60000000],[0x5678,0x480000b9,0x60000000]]]]
  233.  
  234. def int_to_str(i):
  235.     return [chr((i>>24) & 0xff),chr((i>>16) & 0xff),chr((i>>8) & 0xff),chr(i & 0xff)]
  236.  
  237. def patch_CB(CB):
  238.     found = False
  239.  
  240.     for versions in CB_patches:
  241.         if build(CB) == versions[0]:
  242.             print "patchset for %d found, %d patch(es)" % (versions[0],len(versions[1]))
  243.             found  = True
  244.             for patches in versions[1]:
  245.                 plain = int_to_str(patches[1])
  246.                 patch = int_to_str(patches[2])
  247.  
  248.                 patched = ""
  249.  
  250.                 for i in range(4):
  251.                     keystream = ord(plain[i]) ^ ord(CB[i+patches[0]])
  252.                     patched = patched + chr(keystream ^ ord(patch[i]))
  253.  
  254.                 CB = CB[:patches[0]] + patched + CB[patches[0]+4:]
  255.  
  256.     assert found,"can't patch that CB"
  257.  
  258.     return CB
  259.  
  260. # 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,...]
  261.  
  262. SMC_patches = [[0xf9c96639,"Trinity (for slims), version 3.1",[[0x13b3,0x00,0x00]]],
  263. [0x5b3aed00,"Jasper, version 2.3",[[0x12ba,0x00,0x00]]],
  264. [0x9ad5b7ee,"Zephyr, version 1.10",[[0x1257,0x00,0x00]]],
  265. [0x1d0c613e,"Falcon, version 1.6",[[0x12a3,0x00,0x00]]]]
  266.  
  267.  
  268. def patch_SMC(SMC):
  269.     found = False
  270.  
  271.     for versions in SMC_patches:
  272.         if binascii.crc32(SMC[4:]) & 0xffffffff == versions[0]:
  273.             print "patchset \"%s\" matches, %d patch(es)" % (versions[1],len(versions[2]))
  274.             found  = True
  275.             for patches in versions[2]:
  276.                 for i in range(len(patches)-1):
  277.                     SMC = SMC[:patches[0]+i] + chr(patches[i+1]) + SMC[patches[0]+i+1:]
  278.  
  279.     if not found:
  280.         print" ! Warning: can't patch that SMC, here are the current supported versions:"
  281.         for versions in SMC_patches:
  282.             print "  - %s" % versions[1]
  283.  
  284.     return SMC
  285.  
  286.  
  287. def allzero(string):
  288.     for x in string:
  289.         if ord(x):
  290.             return False
  291.     return True
  292.  
  293. def allFF(string):
  294.     for x in string:
  295.         if ord(x) != 0xFF:
  296.             return False
  297.     return True
  298.  
  299. def calcecc(data):
  300.     assert len(data) == 0x210
  301.     val = 0
  302.     for i in range(0x1066):
  303.         if not i & 31:
  304.             v = ~struct.unpack("<L", data[i/8:i/8+4])[0]
  305.         val ^= v & 1
  306.         v >>= 1
  307.         if val & 1:
  308.             val ^= 0x6954559
  309.         val >>= 1
  310.  
  311.     val = ~val
  312.     return data[:-4] + struct.pack("<L", (val << 6) & 0xFFFFFFFF)
  313.  
  314. def addecc(data, block = 0, off_8 = "\x00" * 4):
  315.     res = ""
  316.     while len(data):
  317.         d = (data[:0x200] + "\x00" * 0x200)[:0x200]
  318.         data = data[0x200:]
  319.        
  320.         d += struct.pack("<L4B4s4s", block / 32, 0, 0xFF, 0, 0, off_8, "\0\0\0\0")
  321.         d = calcecc(d)
  322.         block += 1
  323.         res += d
  324.     return res
  325.  
  326. import sys
  327.  
  328. for i in sys.argv[1:]:
  329.     image = open(i, "rb").read()[:1*1024*1024]
  330.     if image[:2] == "\xFF\x4F":
  331.         print " * found flash image, unpacking..."
  332.         unpack_base_image(image)
  333.         CB_A_crypted = CB_A
  334.         SMC = decrypt_SMC(SMC)
  335.     elif image[:2] == "CD" and allzero(image[0x20:0x230]):
  336.         print " * found decrypted CD"
  337.         CD_plain = image
  338.     elif len(image) == 0x3000 and image.find("<Copyright 2001-") >= 0:
  339.         print " * found decrypted SMC"
  340.         SMC = image
  341.     elif len(image) == 0x3000:
  342.         print " * found encrypted SMC (i hope so)"
  343.         SMC = decrypt_SMC(image)
  344.     elif image[-0x10:] == "x" * 16:
  345.         print " * found XeLL binary, must be linked to %08x" % CODE_BASE
  346.  
  347.         assert len(image) <= 256*1024
  348.         image = (image + "\0" * 256*1024)[:256*1024]
  349.         Xell += image
  350.     else:
  351.         raise " * unknown image found in file %s!" % i
  352.  
  353. print " * we found the following parts:"
  354. print "SMC: %d.%d" %(ord(SMC[0x101]),ord(SMC[0x102]))
  355. print "CB_A:", CB_A and build(CB_A) or "missing"
  356. print "CB_B:", CB_B and build(CB_B) or "missing"
  357. print "CD (image):", CD and build(CD) or "missing"
  358. print "CD (decrypted):", CD_plain and build(CD_plain) or "missing"
  359.  
  360. print " * decrypting..."
  361.  
  362. CB_A = decrypt_CB(CB_A)
  363. print " * checking if all files decrypted properly...",
  364. assert allzero(SMC[-4:])
  365. print "ok"
  366.  
  367. print " * checking required versions...",
  368. assert CD_plain, "you need a decrypted CD"
  369. print "ok"
  370.  
  371. xenon_builds = []
  372. zephyr_builds = [4558, 4571, 4572, 4578, 4579, 4580]
  373. falcon_builds = [5761, 5766, 5770, 5771]
  374. jasper_builds = [6712, 6723, 6750, 6752]
  375. trinity_builds = [9188]
  376.  
  377. print " * this image will be valid *only* for:",
  378. if build(CB_A) in xenon_builds: print "xenon",
  379. if build(CB_A) in zephyr_builds: print "zephyr",
  380. if build(CB_A) in falcon_builds: print "falcon",
  381. if build(CB_A) in jasper_builds: print "jasper",
  382. if build(CB_A) in trinity_builds: print "trinity (slim)",
  383. print
  384.  
  385. Final = ""
  386.  
  387. print " * patching SMC..."
  388. SMC=patch_SMC(SMC)
  389.  
  390. CD = CD_plain
  391.  
  392. if CB_B:
  393.     print " * patching CB_B..."
  394.  
  395.     CB_B = patch_CB(CB_B)
  396.  
  397.     c = "patched CB img"
  398. else:
  399.     print " * zero-pairing..."
  400.  
  401.     CB_A = CB_A[0:0x20] + "\0" * 0x20 + CB_A[0x40:]
  402.  
  403.     c = "zeropair image"
  404.  
  405. open("output/CB_A.bin", "wb").write(CB_A)
  406. if CB_B:
  407.     open("output/CB_B.bin", "wb").write(CB_B)
  408. open("output/SMC.bin", "wb").write(SMC)
  409.  
  410. print " * constructing new image..."
  411.  
  412. base_size = 0x8000 + len(CB_A) + len(CD) + len(CE)
  413. if CB_B:
  414.     base_size += len(CB_B)
  415. base_size += 16383
  416. base_size &=~16383
  417.  
  418. patch_offset = base_size
  419.  
  420. print " * base size: %x" % base_size
  421.  
  422. c += ", version=%02x, CB=%d" % (SCRIPT_VERSION, build(CB_A))
  423. Header = struct.pack(">HHLLL64s5LLLLLLLL", 0xFF4F, 1888, 0, 0x8000, base_size, c, 0, 0, 0, 0, 0x4000, patch_offset, 0x20712, 0x4000, 0, 0, 0x3000, 0x1000)
  424.  
  425. Header = (Header + "\0" * 0x1000)[:0x1000]
  426. random = "\0" * 16
  427.  
  428. SMC = encrypt_SMC(SMC)
  429.  
  430. if not CB_B:
  431.     CB_A, CB_A_key = encrypt_CB(CB_A, random)
  432.     CD, CD_key = encrypt_CD(CD, CB_A_key, random)
  433.  
  434. assert len(Final) < XELL_BASE_FLASH, "Please move XELL_BASE_FLASH"
  435.  
  436. if len(Xell) <= 256*1024:
  437.     print " * No separate recovery Xell available!"
  438.     Xell *= 2
  439.  
  440. print " * Flash Layout:"
  441.  
  442. def add_to_flash(d, w, offset = 0):
  443.     global Final
  444.     print "0x%08x..0x%08x (0x%08x bytes) %s" % (offset + len(Final), offset + len(Final) + len(d) - 1, len(d), w)
  445.     Final += d
  446.  
  447. def pad_to(loc):
  448.     global Final
  449.     pad = "\xFF" * (loc - len(Final))
  450.     add_to_flash(pad, "Padding")
  451.  
  452. add_to_flash(Header[:0x200], "Header")
  453. pad_to(0x1000)
  454. add_to_flash(SMC, "SMC")
  455. add_to_flash(Keyvault, "Keyvault")
  456.  
  457. if CB_B:
  458.     add_to_flash(CB_A_crypted, "CB_A %d" % build(CB_A))
  459.     add_to_flash(CB_B, "CB_B %d" % build(CB_B))
  460. else:
  461.     add_to_flash(CB_A, "CB_A %d" % build(CB_A))
  462.  
  463. add_to_flash(CD, "CD %d" % build(CD))
  464. pad_to(XELL_BASE_FLASH)
  465. add_to_flash(Xell[0:256*1024], "Xell (backup)")
  466. add_to_flash(Xell[256*1024:], "Xell (main)")
  467.  
  468. print " * Encoding ECC..."
  469.  
  470. Final = addecc(Final)
  471.  
  472. open("output/image_00000000.ecc", "wb").write(Final)
  473.  
  474. print "------------- Written into output/image_00000000.ecc"
RAW Paste Data