def verify(self): ncaHeader = NcaHeader() ncaHeader.open( MemoryFile(self.ncaHeader, Type.Crypto.XTS, uhx(Keys.get('header_key')))) id = ncaHeader.rightsId[0:16].decode().upper() if str(self.titleId) != id: raise IndexError('Title IDs do not match! ' + str(self.titleId) + ' != ' + id) decKey = Keys.decryptTitleKey(uhx(self.titleKey), ncaHeader.masterKey) pfs0 = Fs.Pfs0(self.sectionHeaderBlock) ''' print('encKey = ' + str(self.titleKey)) print('decKey = ' + str(hx(decKey))) print('master key = ' + str(ncaHeader.masterKey)) print('ctr = ' + str(hx(pfs0.cryptoCounter))) print('offset = ' + str(self.pfs0Offset)) ''' mem = MemoryFile(self.pfs0Header, Type.Crypto.CTR, decKey, pfs0.cryptoCounter, offset=self.pfs0Offset) magic = mem.read()[0:4] if magic != b'PFS0': raise LookupError('Title Key is incorrect!') return True
def unwrapAesWrappedTitlekey(wrappedKey, keyGeneration): aes_kek_generation_source = uhx(keys['aes_kek_generation_source']) aes_key_generation_source = uhx(keys['aes_key_generation_source']) kek = generateKek(uhx(keys['key_area_key_application_source']), uhx(keys['master_key_0' + str(keyGeneration)]), aes_kek_generation_source, aes_key_generation_source) crypto = aes128.AESECB(kek) return crypto.decrypt(wrappedKey)
def decrypt(keyName, sourceKey): for key in range(len(master_keys)): # Create our AES MasterKey aes_masterKey = AES.new(uhx(master_keys[key]), AES.MODE_ECB) # Use our AES MasterKey to Decrypt our Source Key dec_sourceKey = aes_masterKey.decrypt(uhx(sourceKey)) # Print out the Generated Keys [MasterKey Enumerated] print('%s%d = %s' % (keyName, key, hx(dec_sourceKey).upper()))
def deserialize(self, obj): self.titleId = obj['titleId'] self.titleKey = obj['titleKey'] self.ncaHeader = uhx(obj['ncaHeader']) self.sectionHeaderBlock = uhx(obj['sectionHeaderBlock']) self.pfs0Header = uhx(obj['pfs0Header']) self.pfs0Offset = obj['pfs0Offset'] return self
def decrypt(keyName, isKek, isDsk, sourceKey1, sourceKey2): for key in range(len(master_keys)): # Create the MasterKey Cipher masterKey_cipher = AES.new(uhx(master_keys[key]), AES.MODE_ECB) # Use the MasterKey Cipher to Decrypt the Source Key dec_sourceKey = masterKey_cipher.decrypt(uhx(sourceKey1)) if isKek: # Decrypt the Kek Gen Source dec_kekGenSource = masterKey_cipher.decrypt( uhx(aes_kek_generation_source)) # Create the Kek Cipher kek_cipher = AES.new(uhx(hx(dec_kekGenSource).upper()), AES.MODE_ECB) # Use the Kek Cipher to Decrypt the Source Key dec_keyAreaKey = kek_cipher.decrypt(uhx(sourceKey1)) # Create the Key Cipher key_cipher = AES.new(uhx(hx(dec_keyAreaKey).upper()), AES.MODE_ECB) # Use the Key Cipher to Decrypt the Key Gen Source dec_sourceKey = key_cipher.decrypt(uhx(aes_key_generation_source)) if isDsk: # Create the Dual-Source Key Cipher MSK_cipher = AES.new(uhx(hx(dec_sourceKey).upper()), AES.MODE_ECB) # Use the Dual-Source Key Cipher to Decrypt the Source Key dec_sourceKey2 = MSK_cipher.decrypt(uhx(sourceKey2)) # Print out the Generated Source Key print('%s = %s' % (keyName, hx(dec_sourceKey2).upper())) # Since this only uses Master_Key_00... Stop Processing break # Print out the Generated Source Key [MasterKey Enumerated] print('%s%d = %s' % (keyName, key, hx(dec_sourceKey).upper()))
def activate(self, ctx): # Load Needed NIDs... NEEDED_NIDS = load_nids('plugins', NEEDED) #print('Needed NIDs: %s' % NEEDED_NIDS) # Get the name from IDA... name = idaapi.get_highlighted_identifier() if name is None: print('# Error: Please select a valid string in IDA...') return 1 # Make the NID... symbol = sha1(name.encode() + uhx('518D64A635DED8C1E6B039B1C3E55230')).digest() id = struct.unpack('<Q', symbol[:8])[0] nid = base64enc(uhx('%016x' % id), b'+-').rstrip(b'=') print('%s %s' % (nid, name)) # If the NID is Needed and isn't in our list, add it! if nid in NEEDED_NIDS: print('# Found a missing NID!') # Add the NID and name to our dictionary... NEW_NIDS[nid] = name #print(NEW_NIDS) # Update the Aerolib file... save_nids('loaders', AEROLIB, NEW_NIDS) print('# Successfully updated aerolib.csv!') # Remove the nid from the New list... # Next remove the NID... NEW_NIDS.pop(nid) #print(NEW_NIDS) NEEDED_NIDS.remove(nid) #print(NEEDED_NIDS) # Update the Needed file... save_nids('plugins', NEEDED, NEEDED_NIDS) print('# Successfully updated needed_nids.txt!') print( '---------------------------------------------------------------------------------------------' ) return 1
def encrypt_sector(self, data, tweak): if len(data) % self.block_size: raise ValueError('Data is not aligned to block size!') out = b'' tweak = self.K2.encrypt(uhx('%032X' % tweak)) while data: out += sxor(tweak, self.K1.encrypt(sxor(data[:0x10], tweak))) _t = int(hx(tweak[::-1]), 16) _t <<= 1 if _t & (1 << 128): _t ^= ((1 << 128) | (0x87)) tweak = uhx('%032X' % _t)[::-1] data = data[0x10:] return out
def verify(self): ncaHeader = NcaHeader() ncaHeader.open( MemoryFile(self.ncaHeader, Type.Crypto.XTS, uhx(Keys.get('header_key')))) id = ncaHeader.rightsId[0:16].decode().upper() if str(self.titleId) != id: raise IndexError('Title IDs do not match! ' + str(self.titleId) + ' != ' + id) decKey = Keys.decryptTitleKey(uhx(self.titleKey), ncaHeader.masterKey) pfs0 = Fs.Pfs0(self.sectionHeaderBlock) ''' print('encKey = ' + str(self.titleKey)) print('decKey = ' + str(hx(decKey))) print('master key = ' + str(ncaHeader.masterKey)) print('ctr = ' + str(hx(pfs0.cryptoCounter))) print('offset = ' + str(self.pfs0Offset)) ''' if self.sectionHeaderBlock[8:12] == b'IVFC': #Hex.dump(self.sectionHeaderBlock) #Print.info(hx(self.sectionHeaderBlock[0xc8:0xc8+0x20]).decode('utf-8')) mem = MemoryFile(self.pfs0Header, Type.Crypto.CTR, decKey, pfs0.cryptoCounter, offset=self.pfs0Offset) data = mem.read() #Hex.dump(data) #print('hash = %s' % str(_sha256(data))) if hx(self.sectionHeaderBlock[0xc8:0xc8 + 0x20]).decode('utf-8') == str( _sha256(data)): return True else: return False else: mem = MemoryFile(self.pfs0Header, Type.Crypto.CTR, decKey, pfs0.cryptoCounter, offset=self.pfs0Offset) magic = mem.read()[0:4] if magic != b'PFS0': raise LookupError('Title Key is incorrect!') return True
def get_ssl_privk(cal0): ssl_kek = uhx('B011............................') cal0.seek(0x0AE0) sec_block = cal0.read(0x800) with open('clcert.der', 'wb') as cert: cert.write(sec_block) cal0.seek(0x3AE0) ctr = Counter.new(128, initial_value=int(hx(cal0.read(0x10)), 16)) dec = AES.new(ssl_kek, AES.MODE_CTR, counter=ctr).decrypt(cal0.read(0x120)) privk = hx(dec[:0x100]) with open('privk.bin', 'wb') as out: out.write(uhx(privk)) return None
def ticket(self, rightsId=None, autoGenerate = False): for f in self: if type(f).__name__ == 'Ticket' and (rightsId is None or f._path == rightsId + '.tik'): return f if autoGenerate and rightsId is not None: tikFile = os.path.join(os.path.dirname(self._path), rightsId.lower()) + '.tik' with open('Ticket.tik', 'rb') as intik: data = bytearray(intik.read()) data[0x180:0x190] = b'\x00' * 0x10 data[0x285] = int(rightsId[-2:], 16) + 1 data[0x2A0:0x2B0] = uhx(rightsId) try: with open(tikFile, 'wb') as f: f.write(data) except BaseException as e: Print.error(str(e)) f = Fs.factory(tikFile) f.open(tikFile, 'r+b') return f raise IOError('no ticket in NSP')
def encrypt(in_bytes, public_key, vm_file=None, *, drmkey="c9674744cfce53f3a3ee187a15869795"): pubKey = RSA.importKey(open(public_key).read()) aesKey = randint(0, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).to_bytes(0x10, "big") buf = None inp = b"" if vm_file: with open(vm_file, "rb") as f: tmp = f.read() inp += b"\x13\x37\xB0\x0B" inp += len(tmp).to_bytes(4, "little") inp += tmp if vm_file: inp += doEncrypt(uhx(drmkey[0:32]), in_bytes) else: inp += in_bytes compressed = compress(inp, 9) return ( b"TINFOIL\xFE" + PKCS1_OAEP.new(pubKey, hashAlgo=SHA256, label=b"").encrypt(aesKey) + len(compressed).to_bytes(8, "little") + doEncrypt(aesKey, compressed))
def __init__(self, keys_type): self.keys_type = keys_type is_key = re.compile( r'''\s*([a-zA-Z0-9_]*)\s* # name = \s*([a-fA-F0-9]*)\s* # key''', re.X) try: if my_file.is_file(): f = open(my_file, 'r') if my_file2.is_file(): f = open(my_file2, 'r') except FileNotFoundError: try: f = open( path.join(path.dirname(path.abspath(__file__)), '%s' % self.keys_type), 'r') except FileNotFoundError: raise FileNotFoundError( 'Need key file %s.keys in either %s or %s' % (self.keys_type, path.expanduser('~/.switch'), path.dirname(path.abspath(__file__)))) iterator = (re.search(is_key, l) for l in f) super(Keys, self).__init__( {r[1]: uhx(r[2]) for r in iterator if r is not None}) f.close()
def extract_titlekey(S, kp): E, D, N = kp M = uhx('%0512X' % pow(S, D, N)) M = M[0] + sxor(M[1:0x21], MGF1(M[0x21:], 0x20)) + sxor( M[0x21:], MGF1(sxor(M[1:0x21], MGF1(M[0x21:], 0x20)), 0xDF)) pref, salt, DB = M[0], M[1:0x21], M[0x21:] if pref != '\x00': return None label_hash, DB = DB[:0x20], DB[0x20:] if label_hash != uhx( 'E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855' ): return None for i in xrange(1, len(DB)): if DB.startswith('\x00' * i + '\x01'): return DB[i + 1:] return None
def setHash(self): newHash = uhx(self.calculateHash()) fs = self.header.fs.f fs.seek(0) fs.write(newHash) sbhash = sha256(newHash).hexdigest() self.setHashTableHash(sbhash)
def auth(self): if(self.type == 'CXR' or self.type == 'SW'): auth1r = self.command('AUTH1 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000') if(auth1r[0] == 0 and auth1r[1] != []): auth1r = uhx(auth1r[1][0]) if(auth1r[0:0x10] == self.auth1r_header): data = self.aes_decrypt_cbc(self.sc2tb, self.zero, auth1r[0x10:0x40]) if(data[0x8:0x10] == self.zero[0x0:0x8] and data[0x10:0x20] == self.value and data[0x20:0x30] == self.zero): new_data = data[0x8:0x10] + data[0x0:0x8] + self.zero + self.zero auth2_body = self.aes_encrypt_cbc(self.tb2sc, self.zero, new_data) auth2r = self.command('AUTH2 ' + ''.join('{:02X}'.format(c) for c in bytearray(self.auth2_header + auth2_body))) if(auth2r[0] == 0): return 'Auth successful' else: return 'Auth failed' else: return 'Auth1 response body invalid' else: return 'Auth1 response header invalid' else: return 'Auth1 response invalid' else: scopen = self.command('scopen') if('SC_READY' in scopen[1][0]): auth1r = self.command('10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000') auth1r = auth1r[1][0].split('\r')[1][1:] if(len(auth1r) == 128): auth1r = uhx(auth1r) if(auth1r[0:0x10] == self.auth1r_header): data = self.aes_decrypt_cbc(self.sc2tb, self.zero, auth1r[0x10:0x40]) if(data[0x8:0x10] == self.zero[0x0:0x8] and data[0x10:0x20] == self.value and data[0x20:0x30] == self.zero): new_data = data[0x8:0x10] + data[0x0:0x8] + self.zero + self.zero auth2_body = self.aes_encrypt_cbc(self.tb2sc, self.zero, new_data) auth2r = self.command(''.join('{:02X}'.format(c) for c in bytearray(self.auth2_header + auth2_body))) if('SC_SUCCESS' in auth2r[1][0]): return 'Auth successful' else: return 'Auth failed' else: return 'Auth1 response body invalid' else: return 'Auth1 response header invalid' else: return 'Auth1 response invalid' else: return 'scopen response invalid'
def load(fileName): global keyAreaKeys global titleKeks with open(fileName, encoding="utf8") as f: for line in f.readlines(): r = re.match('\s*([a-z0-9_]+)\s*=\s*([A-F0-9]+)\s*', line, re.I) if r: keys[r.group(1)] = r.group(2) #crypto = aes128.AESCTR(uhx(key), uhx('00000000000000000000000000000010')) aes_kek_generation_source = uhx(keys['aes_kek_generation_source']) aes_key_generation_source = uhx(keys['aes_key_generation_source']) keyAreaKeys = [] for i in range(10): keyAreaKeys.append([None, None, None]) for i in range(10): masterKeyName = 'master_key_0' + str(i) if masterKeyName in keys.keys(): # aes_decrypt(master_ctx, &keyset->titlekeks[i], keyset->titlekek_source, 0x10); masterKey = uhx(keys[masterKeyName]) crypto = aes128.AESECB(masterKey) titleKeks.append(crypto.decrypt(uhx(keys['titlekek_source'])).hex()) keyAreaKeys[i][0] = generateKek(uhx(keys['key_area_key_application_source']), masterKey, aes_kek_generation_source, aes_key_generation_source) keyAreaKeys[i][1] = generateKek(uhx(keys['key_area_key_ocean_source']), masterKey, aes_kek_generation_source, aes_key_generation_source) keyAreaKeys[i][2] = generateKek(uhx(keys['key_area_key_system_source']), masterKey, aes_kek_generation_source, aes_key_generation_source) else: titleKeks.append('0' * 32)
def setHash(self, contentId, hash): contentId = contentId.lower() if '.' in contentId: contentId = contentId.split('.')[0] for entry in self.contentEntries: if entry.ncaId == contentId: entry.setHash(uhx(hash))
def steps2(type): print('\nFIRST STEP - DECRYPT:\n') DKEYS = [ aes_decrypt_cbc(uhx(MASTER), uhx(ZEROS), uhx(type[idx])) for idx, _ in enumerate(type) ] printem(DKEYS) print('\nSECOND STEP - XOR2:\n') XOR1S = [[chr(ord(a) ^ ord(b)) for (a, b) in zip(DKEYS[idx], uhx(XOR2))] for idx, _ in enumerate(type)] printem(XOR1S) print('\nTHIRD STEP - XOR3:\n') XOR2S = [[chr(ord(a) ^ ord(b)) for (a, b) in zip(XOR1S[idx], uhx(XOR3))] for idx, _ in enumerate(type)] printem2(XOR2S)
def file_hash(remote, target, files_list=None): if files_list == None: files_list = get_files_from_head(remote, remote.name) else: files_list = files_list target2 = target[:-1] + 'z' indent = 1 gamecard = False tabs = '\t' * indent sha = False sizef = False for i in range(len(files_list)): if str(files_list[i][0]).lower() == str(target).lower() or str( files_list[i][0]).lower() == str(target2).lower(): nca_name = files_list[i][0] off1 = files_list[i][1] off2 = files_list[i][2] sz = files_list[i][3] break hblock = remote.read_at(off1, 0x200) sha = sha256(hblock).hexdigest() if nca_name.endswith('.ncz') or nca_name.endswith('.nca'): ncaHeader = NcaHeader() ncaHeader.open( MemoryFile(remote.read_at(off1, 0x400), Type.Crypto.XTS, uhx(Keys.get('header_key')))) if nca_name.endswith('.ncz'): sizef = ncaHeader.size else: sizef = sz if nca_name.endswith('.ncz'): if ncaHeader.getgamecard() == 1: gamecard = True else: nca_id = ncaHeader.titleId if nca_id.endswith('000') or nca_id.endswith('800'): if str(ncaHeader.contentType) == 'Content.PROGRAM': docheck = True else: if str(ncaHeader.contentType) == 'Content.DATA': docheck = True if docheck == True: crypto1 = ncaHeader.getCryptoType() crypto2 = ncaHeader.getCryptoType2() if crypto2 > crypto1: masterKeyRev = crypto2 if crypto2 <= crypto1: masterKeyRev = crypto1 crypto = aes128.AESECB( Keys.keyAreaKey(Keys.getMasterKeyIndex(masterKeyRev), ncaHeader.keyIndex)) KB1L = ncaHeader.getKB1L() KB1L = crypto.decrypt(KB1L) if sum(KB1L) == 0: gamecard = True return sha, sizef, gamecard
def open(self, file=None, mode='rb', cryptoType=-1, cryptoKey=-1, cryptoCounter=-1): super(Nca, self).open(file, mode, cryptoType, cryptoKey, cryptoCounter) self.header = NcaHeader() self.partition(0x0, 0xC00, self.header, Fs.Type.Crypto.XTS, uhx(Keys.get('header_key'))) #Print.info('partition complete, seeking') self.header.seek(0x400) # Print.info('reading') # Hex.dump(self.header.read(0x200)) # exit() if self._path is not None and self._path.endswith('.ncz'): return for i in range(4): hdr = self.header.read(0x200) section = BaseFs(hdr, cryptoKey=self.header.titleKeyDec) fs = GetSectionFilesystem(hdr, cryptoKey=-1) #Print.info('fs type = ' + hex(fs.fsType)) #Print.info('fs crypto = ' + hex(fs.cryptoType)) #Print.info('st end offset = ' + str(self.header.sectionTables[i].endOffset - self.header.sectionTables[i].offset)) #Print.info('fs offset = ' + hex(self.header.sectionTables[i].offset)) #Print.info('fs section start = ' + hex(fs.sectionStart)) #Print.info('titleKey = ' + hex(self.header.titleKeyDec)) self.partition(self.header.sectionTables[i].offset, self.header.sectionTables[i].endOffset - self.header.sectionTables[i].offset, section, cryptoKey=self.header.titleKeyDec) try: section.partition(fs.sectionStart, section.size - fs.sectionStart, fs) except BaseException as e: pass # Print.info(e) # raise if fs.fsType: self.sectionFilesystems.append(fs) self.sections.append(section) try: fs.open(None, 'rb') except BaseException as e: Print.error(str(e)) traceback.print_exc(file=sys.stdout) self.titleKeyDec = None
def verify(self): if self.unk1 != 2: raise IOError('invalid HierarchicalSha256 value') hash1 = sha256(uhx(self.getHashTable())).hexdigest() if hash1 != self.hash: Print.error( '\n\n ********** invalid HierarchicalSha256 hash value ********** \n\n' )
def getKey(key): if key not in keys: raise IOError('{0} missing from {1}'.format(key, loadedKeysFile)) foundKey = uhx(keys[key]) foundKeyChecksum = crc32(foundKey) if key in crc32_checksum: if crc32_checksum[key] != foundKeyChecksum: raise IOError('{0} from {1} is invalid (crc32 missmatch)'.format(key, loadedKeysFile)) elif current_process().name == 'MainProcess': Print.info('Unconfirmed: crc32({0}) = {1}'.format(key, foundKeyChecksum)) return foundKey
def load(fileName): global keyAreaKeys global titleKeks global hasDecimalMasterKeys with open(fileName, encoding="utf8") as f: for line in f.readlines(): r = re.match(r'\s*([a-z0-9_]+)\s*=\s*([A-F0-9]+)\s*', line, re.I) if r: keys[r.group(1).lower()] = r.group(2) #crypto = aes128.AESCTR(uhx(key), uhx('00000000000000000000000000000010')) aes_kek_generation_source = uhx(keys['aes_kek_generation_source']) aes_key_generation_source = uhx(keys['aes_key_generation_source']) digits = ['a', 'b', 'c', 'd', 'e', 'f'] for key in keys.keys(): if not key.startswith('master_key_'): continue for c in key.lower().split('_')[-1]: if c in digits: hasDecimalMasterKeys = False break keyAreaKeys = [] for i in range(0x10): keyAreaKeys.append([None, None, None]) for i in range(0x10): masterKeyName = ini_Key(i) if masterKeyName in keys.keys(): # aes_decrypt(master_ctx, &keyset->titlekeks[i], keyset->titlekek_source, 0x10); masterKey = uhx(keys[masterKeyName]) crypto = aes128.AESECB(masterKey) titleKeks.append( crypto.decrypt(uhx(keys['titlekek_source'])).hex()) keyAreaKeys[i][0] = generateKek( uhx(keys['key_area_key_application_source']), masterKey, aes_kek_generation_source, aes_key_generation_source) keyAreaKeys[i][1] = generateKek( uhx(keys['key_area_key_ocean_source']), masterKey, aes_kek_generation_source, aes_key_generation_source) keyAreaKeys[i][2] = generateKek( uhx(keys['key_area_key_system_source']), masterKey, aes_kek_generation_source, aes_key_generation_source) keyGens.append(i) else: titleKeks.append('0' * 32) keyGens.append(keyGens[-1] + 1)
def sign_meme_data(data, key=3): privk = get_private_key(key) if not privk: raise ValueError('Private key not known for key %s!' % str(key)) if len(data) < 0x60: raise ValueError('Memesigned data must be atleast 0x60 bytes!') N, E, D, der = privk aes_key = hashlib.sha1(der + data[:-0x60]).digest()[:0x10] output = data[:-0x8] + hashlib.sha1(data[:-0x8]).digest()[:0x8] meme_enc = meme_aes_encrypt(key, output[-0x60:]) meme_enc = chr(ord(meme_enc[0]) & 0x7F) + meme_enc[1:] rsa_enc = uhx('%0192X' % pow(int(hx(meme_enc), 0x10), D, N)) return output[:-0x60] + rsa
def return_nca_data(file_list): File_DB = {} meta_filename = False meta_filepath = False end = len(file_list) c = 1 for filepath in file_list: try: NAXKey0, NAXKey1, r_path = get_decryption_keys(filepath) filename = (r_path.split('/'))[-1] with open(filepath, 'rb') as f: f.seek(0x4000) data = f.read(0x4000) crypto = aes128.AESXTS(NAXKey0 + NAXKey1, sector_size=0x4000) first_chunk = crypto.decrypt(data) ncaHeader = NcaHeader() ncaHeader.open( MemoryFile(first_chunk, Type.Crypto.XTS, uhx(Keys.get('header_key')))) # print(str(ncaHeader.contentType)) if ncaHeader.magic not in [b'NCA3', b'NCA2']: pass elif str(ncaHeader.contentType) == 'Content.META': if str(ncaHeader.contentType) == 'Content.META': filename = filename.replace('.nca', '.cnmt.nca') # meta_filename=filename # meta_filepath=filepath File_DB[filename] = { 'filepath': filepath, 'NAXKey0': NAXKey0, 'NAXKey1': NAXKey1, 'r_path': r_path, 'content_type': ncaHeader.contentType, 'titleid': ncaHeader.titleId, 'size': ncaHeader.size, 'titlerights': ncaHeader.rightsId, 'crypto1': ncaHeader.getCryptoType(), 'crypto2': ncaHeader.getCryptoType2() } print( f"{filename} - {ncaHeader.titleId} - {str(ncaHeader.contentType)} ({c}/{end})" ) c += 1 ncaHeader.close() except: pass # return meta_filepath,meta_filename,File_DB return File_DB
def getDeviceId(self): if not self.deviceId: raise IOError('device id not set') bytes_ = uhx(self.deviceId) if len(bytes_) < 7: raise IOError('device id too small') if len(bytes_) > 8: raise IOError('device id too large') if int.from_bytes(bytes_, byteorder='big') < 0x100000000000: raise IOError('device id incorrect') return self.deviceId.lower()
def encrypt(self, data, ctr=None): '''Encrypts some data in CTR mode.''' if ctr is None: ctr = self.ctr elif type(ctr) is not int: ctr = int(hx(ctr), 16) out = b'' ln = len(data) while ln: xorpad = self.aes.encrypt_block_ecb(uhx('%032X' % ctr)) l = min(0x10, ln) out += sxor(data[:l], xorpad[:l]) data = data[l:] ln -= l ctr += 1 self.ctr = ctr return out
def decrypt_nax0(input, output=None, ofolder=None, relative_PATH=False): if output == None and ofolder == None: raise Exception("User didn't set output") NAXKey0, NAXKey1, r_path = get_decryption_keys(input, relative_PATH) filename = (r_path.split('/'))[-1] with open(input, 'rb') as f: f.seek(0x4000) data = f.read(0x4000) crypto = aes128.AESXTS(NAXKey0 + NAXKey1, sector_size=0x4000) first_chunk = crypto.decrypt(data) ncaHeader = NcaHeader() ncaHeader.open( MemoryFile(first_chunk, Type.Crypto.XTS, uhx(Keys.get('header_key')))) if ncaHeader.magic not in [b'NCA3', b'NCA2']: raise Exception('Failed to decrypt NCA header: ' + str(self.magic)) else: sz = ncaHeader.size print(f'* {r_path} - Decryption Correct') print( f'* NCA Type is {str(ncaHeader.contentType).replace("Content.","")}' ) print(f'* NCA TitleID is {str(ncaHeader.titleId)}') print(f'* NCA size is {str(sq_tools.getSize(sz))}') if not str(ncaHeader.contentType) == 'Content.META': print(f'* Filename is {filename}') else: filename = filename.replace('.nca', '.cnmt.nca') if output == None: output = os.path.join(ofolder, filename) t = tqdm(total=sz, unit='B', unit_scale=True, leave=False) t.write(f'\n- Decrypting to {output}') buffer = 0x4000 sect = 0 with open(output, 'wb') as o: with open(input, 'rb') as f: f.seek(0x4000) for data in iter(lambda: f.read(0x4000), ""): crypto = aes128.AESXTS(NAXKey0 + NAXKey1, sector=sect, sector_size=0x4000) o.write(crypto.decrypt(data)) o.flush() if not data: t.close() break sect += 1
def open(self, file=None, mode='rb', cryptoType=-1, cryptoKey=-1, cryptoCounter=-1): super(Nca, self).open(file, mode, cryptoType, cryptoKey, cryptoCounter) self.header = NcaHeader() self.partition(0x0, 0xC00, self.header, Fs.Type.Crypto.XTS, uhx(Keys.get('header_key'))) #Print.info('partition complete, seeking') self.header.seek(0x400) #Print.info('reading') #Hex.dump(self.header.read(0x200)) #exit() for i in range(4): fs = GetSectionFilesystem(self.header.read(0x200), cryptoKey=self.header.titleKeyDec) #Print.info('fs type = ' + hex(fs.fsType)) #Print.info('fs crypto = ' + hex(fs.cryptoType)) #Print.info('st end offset = ' + str(self.header.sectionTables[i].endOffset - self.header.sectionTables[i].offset)) #Print.info('fs offset = ' + hex(self.header.sectionTables[i].offset)) #Print.info('fs section start = ' + hex(fs.sectionStart)) #Print.info('titleKey = ' + str(hx(self.header.titleKeyDec))) try: self.partition(self.header.sectionTables[i].offset + fs.sectionStart, self.header.sectionTables[i].endOffset - self.header.sectionTables[i].offset, fs, cryptoKey=self.header.titleKeyDec) except BaseException as e: pass #Print.info(e) #raise if fs.fsType: self.sectionFilesystems.append(fs) self.titleKeyDec = None self.masterKey = None
def get_ssl_privk(cal0): # Save the SSL Cert ssl_cert = read_at(cal0, 0x0AE0, 0x800) with open('clcert.der', 'wb') as cert: cert.write(ssl_cert) # Generate the SSL RSA Kek unwrapped_kek = unwrap(rsa_private_kek_generation_source, master_key_00) unwrapped_kekek = unwrap(ssl_rsa_kek_source_x, unwrapped_kek) ssl_rsa_kek = unwrap(ssl_rsa_kek_source_y, unwrapped_kekek) #print('ssl_rsa_kek = %s' % (hx(ssl_rsa_kek).upper())) # Decrypt the Encrypted SSL Key dec = AES.new(ssl_rsa_kek, AES.MODE_CTR, counter=b2ctr(read_at(cal0, 0x3AE0, 0x10))) \ .decrypt(read_at(cal0, 0x3AF0, 0x120)) privk = hx(dec[:0x100]) with open('privk.bin', 'wb') as key: key.write(uhx(privk)) return
def sha256(data): return uhx(SHA256.new(data).hexdigest())