Advertisement
TiniVi

NCCHInfo PadGen (Requires KeyXs)

Dec 31st, 2015
992
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.66 KB | None | 0 0
  1. from Crypto.Cipher import AES
  2. from Crypto.Util import Counter
  3. from ctypes import *
  4. import hashlib
  5. import struct
  6.  
  7. # TODO:
  8. #   -Parse NCCH data directly from the ROM
  9. #   -Decrypt NCCH directly
  10. #   -Use command-line based handling
  11.  
  12. #http://www.falatic.com/index.php/108/python-and-bitwise-rotation
  13. rol = lambda val, r_bits, max_bits: \
  14.     (val << r_bits%max_bits) & (2**max_bits-1) | \
  15.     ((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits)))
  16.  
  17. ror = lambda val, r_bits, max_bits: \
  18.     ((val & (2**max_bits-1)) >> r_bits%max_bits) | \
  19.     (val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
  20.  
  21. def to_bytes(num):
  22.     numstr = ''
  23.     tmp = num
  24.     while len(numstr) < 16:
  25.         numstr += chr(tmp & 0xFF)
  26.         tmp >>= 8
  27.     return numstr[::-1]
  28.  
  29. class ncchinfo_hdr(Structure):
  30.     _fields_ = [
  31.         ('FFFFFFFF', c_uint32),
  32.         ('Ver', c_uint32),
  33.         ('Entries', c_uint32),
  34.         ('Reserved', c_uint32)
  35.     ]
  36.  
  37. class ncchinfo_entry(Structure):
  38.     _fields_ = [
  39.         ('Counter', c_uint8 * 0x10),
  40.         ('KeyY', c_uint8 * 0x10),
  41.         ('Size', c_uint32),
  42.         ('Reserved', c_uint32),
  43.         ('Reserved', c_uint32),
  44.         ('CryptoFlag', c_uint32),
  45.         ('TitleID', c_uint32 * 2),
  46.         ('Name', c_char * 112)
  47.     ]
  48.  
  49. #https://github.com/archshift/Decrypt9/blob/master/scripts/ncchinfo_gen.py
  50. def ArrayToString(ctypeArray):
  51.     return ''.join('%02X' % x for x in ctypeArray[::+1])
  52.    
  53. def ReverseArrayToString(ctypeArray):
  54.     return ''.join('%02X' % x for x in ctypeArray[::-1])
  55.    
  56. with open('ncchinfo.bin', 'rb') as f:
  57.     info = ncchinfo_hdr()
  58.     f.readinto(info)
  59.     f.read(16)
  60.     f.seek(16)
  61.    
  62.     for x in xrange(0, info.Entries):
  63.         entry = ncchinfo_entry()
  64.         f.readinto(entry)
  65.         f.seek(168*x+16)
  66.         f.read(168)
  67.        
  68.         KeyX = 0
  69.        
  70.         if (entry.CryptoFlag == 0):
  71.             KeyX = 0x00000000000000000000000000000000 #KeyX 0x2C
  72.             if not hashlib.sha1(to_bytes(KeyX)).hexdigest().upper() == '54701686283A18CA54FF76B6910C49DEC2D6CF13':
  73.                 KeyX = 0
  74.         elif (entry.CryptoFlag == 0x01):
  75.             KeyX = 0x00000000000000000000000000000000 #KeyX 0x25
  76.             if not hashlib.sha1(to_bytes(KeyX)).hexdigest().upper() == '4231F2B435EC7A456C0ACC5FAFCD4CB949F83BC0':
  77.                 KeyX = 0
  78.         elif (entry.CryptoFlag == 0x0A):
  79.             KeyX = 0x00000000000000000000000000000000 #KeyX 0x18
  80.             if not hashlib.sha1(to_bytes(KeyX)).hexdigest().upper() == 'FBEAA933DC7D4997463E8973AD1867C0B245E0BD':
  81.                 KeyX = 0
  82.         elif (entry.CryptoFlag == 0x0B):
  83.             KeyX = 0x00000000000000000000000000000000 #KeyX 0x1B
  84.             if not hashlib.sha1(to_bytes(KeyX)).hexdigest().upper() == '1E96BE527AC64E6F6929B38760B1A4873D051B96':
  85.                 KeyX = 0
  86.        
  87.         ctr = Counter.new(128, initial_value=long(ArrayToString(entry.Counter),16))
  88.         KeyY = long(ArrayToString(entry.KeyY), 16)
  89.         NormalKey = rol((rol(KeyX, 2, 128) ^ KeyY) + 0x1FF9E9AAC5FE0408024591DC5D52768A, 87, 128)
  90.         ctrmode = AES.new(to_bytes(NormalKey), AES.MODE_CTR, counter = ctr)
  91.        
  92.         filename = entry.Name.encode('ascii','ignore')
  93.         print(filename[1:])
  94.         print(ArrayToString(entry.Counter))
  95.         print(ArrayToString(entry.KeyY))
  96.         print '%X' % (NormalKey)
  97.        
  98.         if (KeyX != 0):
  99.             with open(filename[1:], 'w+b') as p:
  100.                 l = 0
  101.                
  102.                 for i in xrange(0, entry.Size*0x10):
  103.                     out = ctrmode.decrypt("00000000000000000000000000000000".decode("hex"))
  104.                     for c in xrange(0, 4095): #0x10000 byte chunks seem to work the fastest
  105.                         out += ctrmode.decrypt("00000000000000000000000000000000".decode("hex"))
  106.                     p.write(out)
  107.                    
  108.                     percent = 100 * float(i)/float(entry.Size*0x10)
  109.                     if (percent >= l):
  110.                         print 'Generating XORpad... %d%%\r' % percent,
  111.                         l = l+1
  112.                 print 'Generating XORpad... 100%'
  113.                
  114.                 print("Done!")
  115.         else:
  116.             print("Invalid KeyX!")
  117.        
  118.         print
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement