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 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 verifyKey(self, userkey): if not self.header.hasTitleRights(): titleKeyDec = Keys.decryptTitleKey( file.getTitleKeyBlock().to_bytes(16, byteorder='big'), Keys.getMasterKeyIndex(self.masterKey())) else: encKey = userkey titleKeyDec = Keys.decryptTitleKey( encKey, Keys.getMasterKeyIndex(self.masterKey())) ''' print('\nTesting {} with:'.format(self)) print('- Keygeneration {}'.format(self.masterKey())) print('- Encrypted key {}'.format(str(hx(encKey))[2:-1])) print('- Decrypted key {}'.format(str(hx(titleKeyDec))[2:-1])) ''' decKey = titleKeyDec f = self if self.header.getRightsId() != 0: for fs in self: # print(fs.fsType) # print(fs.cryptoType) if fs.fsType == Type.Fs.PFS0 and fs.cryptoType == Type.Crypto.CTR: f.seek(0) ncaHeader = NcaHeader() ncaHeader.open( MemoryFile(f.read(0x400), Type.Crypto.XTS, uhx(Keys.get('header_key')))) pfs0 = fs sectionHeaderBlock = fs.buffer #fs.f.setKey(b'\x00' * 16) #print('- Current key {}'.format(str(hx(fs.f.cryptoKey))[2:-1])) fs.seek(0) pfs0Offset = 0 # int.from_bytes(sectionHeaderBlock[0x38:0x40], byteorder='little', signed=False) pfs0Header = fs.read(0x10) # Hex.dump(sectionHeaderBlock) #mem = MemoryFile(pfs0Header, Type.Crypto.CTR, decKey, pfs0.cryptoCounter, offset = pfs0Offset) data = pfs0Header # mem.read(); # Hex.dump(pfs0Header) magic = data[0:4] # print(magic) if magic != b'PFS0': return False else: return True if fs.fsType == Type.Fs.ROMFS and fs.cryptoType == Type.Crypto.CTR: f.seek(0) ncaHeader = NcaHeader() ncaHeader.open( MemoryFile(f.read(0x400), Type.Crypto.XTS, uhx(Keys.get('header_key')))) ncaHeader = f.read(0x400) pfs0 = fs sectionHeaderBlock = fs.buffer levelOffset = int.from_bytes(sectionHeaderBlock[0x18:0x20], byteorder='little', signed=False) levelSize = int.from_bytes(sectionHeaderBlock[0x20:0x28], byteorder='little', signed=False) pfs0Offset = levelOffset f.seek(pfs0Offset + fs.f.offset) pfs0Header = f.read(levelSize) # fs.seek(pfs0Offset) #pfs0Header = fs.read(levelSize) #print(sectionHeaderBlock[8:12] == b'IVFC') if sectionHeaderBlock[8:12] == b'IVFC': # Hex.dump(sectionHeaderBlock) # Print.info(hx(sectionHeaderBlock[0xc8:0xc8+0x20]).decode('utf-8')) mem = MemoryFile(pfs0Header, Type.Crypto.CTR, decKey, pfs0.cryptoCounter, offset=fs.f.offset) data = mem.read() #Hex.dump(data, 48) #print('hash = %s' % str(sha256(data).hexdigest())) if hx(sectionHeaderBlock[0xc8:0xc8 + 0x20]).decode('utf-8') == str( sha256(data).hexdigest()): return True else: return False else: mem = MemoryFile(pfs0Header, Type.Crypto.CTR, decKey, pfs0.cryptoCounter, offset=pfs0Offset) data = mem.read() # Hex.dump(data) magic = mem.read()[0:4] # print(magic) if magic != b'PFS0': pass else: return True if fs.fsType == Type.Fs.ROMFS and fs.cryptoType == Type.Crypto.BKTR and str( f.header.contentType) == 'Content.PROGRAM': f.seek(0) ncaHeader = NcaHeader() ncaHeader.open( MemoryFile(f.read(0x400), Type.Crypto.XTS, uhx(Keys.get('header_key')))) ncaHeader = f.read(0x400) pfs0 = fs sectionHeaderBlock = fs.buffer levelOffset = int.from_bytes(sectionHeaderBlock[0x18:0x20], byteorder='little', signed=False) levelSize = int.from_bytes(sectionHeaderBlock[0x20:0x28], byteorder='little', signed=False) pfs0Offset = fs.offset + levelOffset f.seek(pfs0Offset) pfs0Header = f.read(levelSize) if sectionHeaderBlock[8:12] == b'IVFC': for i in range(10): ini = 0x100 + (i * 0x10) fin = 0x110 + (i * 4) test = sectionHeaderBlock[ini:fin] if test == b'BKTR': return True return False
def read_buildid(path=None, TD=None, filter=None, file=None, cnmtdict=None, files_list=None, dectkey=None): ModuleId = '' BuildID8 = '' BuildID16 = '' iscorrect = False sdkversion = '-' sectionFilesystems = [] if file != None and cnmtdict != None and files_list != None: remote = file else: cnmtdict, files_list, remote = get_cnmt_data(path, TD, filter) ctype = cnmtdict['ctype'] if ctype != 'DLC': ncadata = cnmtdict['ncadata'] for entry in ncadata: if str(entry['NCAtype']).lower() == 'program': ncaname = entry['NcaId'] + '.nca' break for i in range(len(files_list)): if (files_list[i][0]) == ncaname: name = files_list[i][0] off1 = files_list[i][1] off2 = files_list[i][2] sz = files_list[i][3] break remote.seek(off1, off2) ncaHeader = NcaHeader() ncaHeader.open( MemoryFile(remote.read(0xC00), Type.Crypto.XTS, uhx(Keys.get('header_key')))) ncaHeader.rewind() if ncaHeader.getRightsId() == 0: decKey = ncaHeader.titleKeyDec elif dectkey != None: # print(dectkey) decKey = bytes.fromhex(dectkey) try: sdkversion = get_sdkversion_from_head(ncaHeader) except: sdkversion = '-' try: ncaHeader.seek(0x400) for i in range(4): hdr = ncaHeader.read(0x200) section = BaseFs(hdr, cryptoKey=ncaHeader.titleKeyDec) fs = GetSectionFilesystem(hdr, cryptoKey=-1) if fs.fsType: fs.offset = ncaHeader.sectionTables[i].offset sectionFilesystems.append(fs) # Print.info('fs type = ' + hex(fs.fsType)) # Print.info('fs crypto = ' + hex(fs.cryptoType)) # Print.info('fs cryptocounter = ' + str(fs.cryptoCounter)) # Print.info('st end offset = ' + str(ncaHeader.sectionTables[i].endOffset - ncaHeader.sectionTables[i].offset)) # Print.info('fs offset = ' + hex(ncaHeader.sectionTables[i].offset)) # Print.info('fs section start = ' + hex(fs.sectionStart)) # Print.info('titleKey = ' + str(hx(ncaHeader.titleKeyDec))) for fs in sectionFilesystems: if fs.fsType == Type.Fs.PFS0 and fs.cryptoType == Type.Crypto.CTR: # print(fs.fsType) # print(fs.cryptoType) # print(fs.buffer) pfs0 = fs sectionHeaderBlock = fs.buffer pfs0Offset = fs.offset + fs.sectionStart skoff = off1 + pfs0Offset # pfs0Offset=off1+fs.offset+0xC00+ncaHeader.get_htable_offset() remote.seek(skoff, off2) # print(str(fs.cryptoCounter)) pfs0Header = remote.read(0x10 * 30) # print(hex(pfs0Offset)) # print(hex(fs.sectionStart)) # Hex.dump(pfs0Header) off = fs.offset + fs.sectionStart mem = MemoryFile(pfs0Header, Type.Crypto.CTR, decKey, pfs0.cryptoCounter, offset=pfs0Offset) data = mem.read() # Hex.dump(data) head = data[0:4] n_files = (data[4:8]) n_files = int.from_bytes(n_files, byteorder='little') st_size = (data[8:12]) st_size = int.from_bytes(st_size, byteorder='little') junk = (data[12:16]) offset = (0x10 + n_files * 0x18) stringTable = (data[offset:offset + st_size]) stringEndOffset = st_size headerSize = 0x10 + 0x18 * n_files + st_size # print(head) # print(str(n_files)) # print(str(st_size)) # print(str((stringTable))) files_list = list() for i in range(n_files): i = n_files - i - 1 pos = 0x10 + i * 0x18 offset = data[pos:pos + 8] offset = int.from_bytes(offset, byteorder='little') size = data[pos + 8:pos + 16] size = int.from_bytes(size, byteorder='little') nameOffset = data[pos + 16:pos + 20] # just the offset nameOffset = int.from_bytes(nameOffset, byteorder='little') name = stringTable[nameOffset:stringEndOffset].decode( 'utf-8').rstrip(' \t\r\n\0') stringEndOffset = nameOffset # junk2 = data[pos+20:pos+24] # junk data # print(name) # print(offset) # print(size) files_list.append([name, offset, size]) files_list.reverse() # print(files_list) for i in range(len(files_list)): if files_list[i][0] == 'main': foff = files_list[i][1] + pfs0Offset + headerSize skoff2 = files_list[i][1] + skoff + headerSize remote.seek(skoff2, off2) np = remote.read(0x60) mem = MemoryFile(np, Type.Crypto.CTR, decKey, pfs0.cryptoCounter, offset=foff) magic = mem.read(0x4) # print(magic) if magic == b'NSO0': mem.seek(0x40) data = mem.read(0x20) ModuleId = (str(hx(data)).upper())[2:-1] BuildID8 = (str(hx(data[:8])).upper())[2:-1] BuildID16 = (str(hx(data[:16])).upper())[2:-1] iscorrect = True break break except: pass if iscorrect == False: ModuleId = '' BuildID8 = '' BuildID16 = '' # print(ModuleId);print(BuildID8);print(BuildID16) return ModuleId, BuildID8, BuildID16, sdkversion