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 get_cnmt_data(path=None,TD=None,filter=None,target=None,file=None): if path==None and file==None: return False if file != None: remote=file type='file' remote.rewind() elif path.startswith('http'): url=path remote=Public.location(url);readable=remote.readable if not readable: return False type='file' else: if path=='pick': account=Private.token_picker() TD=Private.TD_picker(account) return test=path.split(".+") if TD=='pick': TD=Private.TD_picker(path) if len(test)>1 or path.endswith('/') or path.endswith('\\'): type="folder" else: ID,name,type,size,md5,remote=Private.get_Data(path,TD=TD,Print=False) if type!='file': # print('Path is a folder') Private.folderpicker(path,TD=TD,filter=filter,mode='get_cnmt_data') return else: files_list=get_files_from_head(remote,remote.name) # print(files_list) for i in range(len(files_list)): if (files_list[i][0]).endswith('.cnmt.nca'): nca_name=files_list[i][0] off1=files_list[i][1] off2=files_list[i][2] sz=files_list[i][3] if target==None: break # print(nca_name) # print(target) if str(nca_name).lower()==str(target).lower(): break remote.seek(off1,off2) buf=int(sz) try: nca=Nca() nca.open(MemoryFile(remote.read(buf))) nca.rewind() cnmt=io.BytesIO(nca.return_cnmt()) titleid,titleversion,base_ID,keygeneration,rightsId,RSV,RGV,ctype,metasdkversion,exesdkversion,hasHtmlManual,Installedsize,DeltaSize,ncadata=cnmt_data(cnmt,nca,nca_name) d={} d['titleid']=titleid;d['version']=titleversion;d['baseid']=base_ID;d['keygeneration']=keygeneration;d['rightsId']=rightsId; d['rsv']=RSV;d['rgv']=RGV;d['ctype']=ctype;d['metasdkversion']=metasdkversion;d['exesdkversion']=exesdkversion; d['hasHtmlManual']=hasHtmlManual;d['Installedsize']=Installedsize;d['DeltaSize']=DeltaSize;d['ncadata']=ncadata; # print(d) return d,files_list,remote except IOError as e: print(e, file=sys.stderr)
def open(self, path=None, mode='rb', cryptoType=-1, cryptoKey=-1, cryptoCounter=-1): r = super(BaseFs, self).open(path, mode, cryptoType, cryptoKey, cryptoCounter) if self.bktr1Buffer: self.bktrRelocation = Bktr.Bktr1(MemoryFile(self.bktr1Buffer), 'rb', nca=self) if self.bktr2Buffer: self.bktrSubsection = Bktr.Bktr2(MemoryFile(self.bktr2Buffer), 'rb', nca=self)
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 __init__(self, buffer, path=None, mode=None, cryptoType=-1, cryptoKey=-1, cryptoCounter=-1): super(Rom, self).__init__(buffer, path, mode, cryptoType, cryptoKey, cryptoCounter) if buffer: self.ivfc = Ivfc(MemoryFile(buffer[0x8:]), 'rb') self.magic = buffer[0x8:0xC] # Hex.dump(buffer) #self.sectionStart = self.ivfc.levels[5].offset else: self.ivfc = None
def __init__(self, buffer, path=None, mode=None, cryptoType=-1, cryptoKey=-1, cryptoCounter=-1): super(Rom, self).__init__(buffer, path, mode, cryptoType, cryptoKey, cryptoCounter) if buffer: self.ivfc = Ivfc(MemoryFile(buffer[0x8:]), 'rb') self.magic = buffer[0x8:0xC] else: self.ivfc = None
def open(self, path=None, mode='rb', cryptoType=-1, cryptoKey=-1, cryptoCounter=-1): r = super(BaseFs, self).open(path, mode, cryptoType, cryptoKey, cryptoCounter) if self.bktr1Buffer: try: self.bktrRelocation = Bktr.Bktr1(MemoryFile(self.bktr1Buffer), 'rb', nca=self) except BaseException as e: Print.info('bktr reloc exception: ' + str(e)) if self.bktr2Buffer: try: self.bktrSubsection = Bktr.Bktr2(MemoryFile(self.bktr2Buffer), 'rb', nca=self) except BaseException as e: Print.info('bktr subsection exception: ' + str(e))
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 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 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 get_nsx_name(dic=None, filepath=None): if dic == None: NAXKey0, NAXKey1, r_path = get_decryption_keys(filepath) elif dic != None: NAXKey0 = dic['NAXKey0'] NAXKey1 == dic['NAXKey1'] r_path = dic['r_path'] filepath = dic['filepath'] else: return False nca_name = (r_path.split('/'))[-1] = (r_path.split('/'))[-1] with open(filepath, 'rb') as f: f.seek(0x4000) data = f.read() crypto = aes128.AESXTS(NAXKey0 + NAXKey1, sector_size=0x4000) nca = Nca() nca.open(MemoryFile(crypto.decrypt(data))) nca.rewind() nca._path = nca_name result = nca.get_langueblock(roman=False) title_name = result[0] return title_name
def get_cnmt_data(dic=None, filepath=None): if dic == None: NAXKey0, NAXKey1, r_path = get_decryption_keys(filepath) elif dic != None: NAXKey0 = dic['NAXKey0'] NAXKey1 = dic['NAXKey1'] r_path = dic['r_path'] filepath = dic['filepath'] else: return False nca_name = (r_path.split('/'))[-1] = (r_path.split('/'))[-1] with open(filepath, 'rb') as f: f.seek(0x4000) data = f.read() crypto = aes128.AESXTS(NAXKey0 + NAXKey1, sector_size=0x4000) nca = Nca() nca.open(MemoryFile(crypto.decrypt(data))) nca.rewind() nca_name = nca_name.replace('.nca', '.cnmt.nca') nca._path = nca_name cnmt = io.BytesIO(nca.return_cnmt()) cnmt_dict = cnmt_data(cnmt, nca, nca_name) return cnmt_dict
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 gen_xci_parts_spec1(filepath=None,remote=None,target_cnmt=None,cachefolder=None,keypatch=False,files_list=None): if filepath=="": filepath=None if remote=="": remote=None if remote==None: test=filepath.split('|');TD=None if len(test)<2: filepath=test[0] lib,TD,libpath=get_library_from_path(remote_lib_file,filepath) else: filepath=test[0] TD=test[1] if str(TD).upper()=="NONE": TD=None ID,name,type,size,md5,remote=DrivePrivate.get_Data(filepath,TD=TD,Print=False) if keypatch!=False: try: keypatch=int(keypatch) except: keypatch=False if cachefolder==None: cachefolder=os.path.join(ztools_dir, '_mtp_cache_') if not os.path.exists(cachefolder): os.makedirs(cachefolder) else: for f in os.listdir(cachefolder): fp = os.path.join(cachefolder, f) try: shutil.rmtree(fp) except OSError: os.remove(fp) if files_list==None: files_list=DriveTools.get_files_from_head(remote,remote.name) files=list();filesizes=list() fplist=list() for k in range(len(files_list)): entry=files_list[k] fplist.append(entry[0]) if target_cnmt==None: for i in range(len(files_list)): entry=files_list[i] cnmtfile=entry[0] if cnmtfile.endswith('.cnmt.nca'): target_cnmt=cnmtfile break for i in range(len(files_list)): entry=files_list[i] cnmtfile=entry[0] if cnmtfile.endswith('.cnmt.nca') and target_cnmt==cnmtfile: metadict,d1,d2=DriveTools.get_cnmt_data(target=cnmtfile,file=remote) ncadata=metadict['ncadata'] for j in range(len(ncadata)): row=ncadata[j] if row['NCAtype']!='Meta' and row['NCAtype']!='Program': test1=str(row['NcaId'])+'.nca';test2=str(row['NcaId'])+'.ncz' if test1 in fplist: files.append(str(row['NcaId'])+'.nca') filesizes.append(int(row['Size'])) elif test2 in fplist: files.append(str(row['NcaId'])+'.ncz') for k in range(len(files_list)): entry=files_list[k] if entry[0]==test2: filesizes.append(int(entry[3])) break for j in range(len(ncadata)): row=ncadata[j] if row['NCAtype']=='Meta': # print(str(row['NcaId'])+'.cnmt.nca') files.append(str(row['NcaId'])+'.cnmt.nca') filesizes.append(int(row['Size'])) for j in range(len(ncadata)): row=ncadata[j] # print(row) if row['NCAtype']=='Program': test1=str(row['NcaId'])+'.nca';test2=str(row['NcaId'])+'.ncz' if test1 in fplist: files.append(str(row['NcaId'])+'.nca') filesizes.append(int(row['Size'])) elif test2 in fplist: files.append(str(row['NcaId'])+'.ncz') for k in range(len(files_list)): entry=files_list[k] if entry[0]==test2: filesizes.append(int(entry[3])) break break remote.rewind() outheader = sq_tools.gen_nsp_header(files,filesizes) properheadsize=len(outheader) # print(properheadsize) # print(bucketsize) i=0;sum=properheadsize; outfile=os.path.join(cachefolder, "0") outf = open(outfile, 'w+b') outf.write(outheader) written=0 for fi in files: if fi.endswith('nca') or fi.endswith('ncz') : for i in range(len(files_list)): if str(files_list[i][0]).lower() == str(fi).lower(): nca_name=files_list[i][0] off1=files_list[i][1] off2=files_list[i][2] nca_size=files_list[i][3] break data=remote.read_at(off1,nca_size) ncaHeader = NcaHeader() ncaHeader.open(MemoryFile(remote.read_at(off1,0x400), FsType.Crypto.XTS, uhx(Keys.get('header_key')))) 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)) hcrypto = aes128.AESXTS(uhx(Keys.get('header_key'))) gc_flag='00'*0x01 crypto1=ncaHeader.getCryptoType() crypto2=ncaHeader.getCryptoType2() if ncaHeader.getRightsId() != 0: ncaHeader.rewind() if crypto2>crypto1: masterKeyRev=crypto2 if crypto2<=crypto1: masterKeyRev=crypto1 titleKeyDec = Keys.decryptTitleKey(titleKey, Keys.getMasterKeyIndex(int(masterKeyRev))) encKeyBlock = crypto.encrypt(titleKeyDec * 4) if str(keypatch) != "False": t = tqdm(total=False, unit='B', unit_scale=False, leave=False) if keypatch < ncaHeader.getCryptoType2(): encKeyBlock,crypto1,crypto2=get_new_cryptoblock(ncaHeader,keypatch,encKeyBlock,t) t.close() if ncaHeader.getRightsId() == 0: ncaHeader.rewind() encKeyBlock = ncaHeader.getKeyBlock() if str(keypatch) != "False": t = tqdm(total=False, unit='B', unit_scale=False, leave=False) if keypatch < ncaHeader.getCryptoType2(): encKeyBlock,crypto1,crypto2=get_new_cryptoblock(ncaHeader,keypatch,encKeyBlock,t) t.close() ncaHeader.rewind() i=0 newheader=get_newheader(MemoryFile(remote.read_at(off1,0xC00)),encKeyBlock,crypto1,crypto2,hcrypto,gc_flag) outf.write(newheader) written+=len(newheader) break else:pass outf.flush() outf.close() tfile=os.path.join(cachefolder, "remote_files.csv") with open(tfile,'w') as csvfile: csvfile.write("{}|{}|{}|{}|{}|{}|{}\n".format("step","filepath","size","targetsize","off1","off2","token")) csvfile.write("{}|{}|{}|{}|{}|{}|{}\n".format(0,outfile,properheadsize+written,properheadsize,0,properheadsize,"False")) k=0;l=0 for fi in files: for j in files_list: if j[0]==fi: csvfile.write("{}|{}|{}|{}|{}|{}|{}\n".format(k+1,outfile,properheadsize+written,0xC00,(properheadsize+l*0xC00),(properheadsize+(l*0xC00)+0xC00),"False")) off1=j[1]+0xC00 off2=j[2] targetsize=j[3]-0xC00 URL='https://www.googleapis.com/drive/v3/files/'+remote.ID+'?alt=media' token=remote.access_token csvfile.write("{}|{}|{}|{}|{}|{}|{}\n".format(k+2,URL,remote.size,targetsize,off1,off2,token)) break k+=2;l+=1 nspname="test.nsp" try: g=remote.name g0=[pos for pos, char in enumerate(g) if char == '['] g0=(g[0:g0[0]]).strip() titleid=metadict['titleid'] titleversion=metadict['version'] ctype=metadict['ctype'] nspname=f"{g0} [{titleid}] [v{titleversion}] [{ctype}].nsp" except:pass return nspname
def nacp_data(file,ncadata,files_list): ncaname=None;dict={} for entry in ncadata: if str(entry['NCAtype']).lower()=='control': ncaname=entry['NcaId']+'.nca' break if ncaname!=None: for i in range(len(files_list)): if files_list[i][0]==ncaname: nca_name=files_list[i][0] off1=files_list[i][1] off2=files_list[i][2] sz=files_list[i][3] break file.seek(off1,off2) buf=int(sz) nca=Nca() nca.open(MemoryFile(file.read(buf))) nca.rewind() f=io.BytesIO(nca.ret_nacp());f.seek(0) nacp = Nacp() dict['RegionalNames'],dict['RegionalEditors']=nacp.get_NameandPub(f.read(0x300*15)) f.seek(0x3000) dict['ISBN']=nacp.get_Isbn(f.read(0x24)) f.seek(0x3025) dict['StartupUserAccount']=nacp.get_StartupUserAccount(readInt8(f,'little')) dict['UserAccountSwitchLock']=nacp.get_UserAccountSwitchLock(readInt8(f,'little')) dict['AddOnContentRegistrationType']=nacp.get_AddOnContentRegistrationType(readInt8(f,'little')) dict['ctype']=nacp.get_ContentType(readInt8(f,'little')) dict['ParentalControl']=nacp.get_ParentalControl(readInt8(f,'little')) dict['ScreenshotsEnabled']=nacp.get_Screenshot(readInt8(f,'little')) dict['VideocaptureEnabled']=nacp.get_VideoCapture(readInt8(f,'little')) dict['dataLossConfirmation']=nacp.get_dataLossConfirmation(readInt8(f,'little')) dict['PlayLogPolicy']=nacp.get_PlayLogPolicy(readInt8(f,'little')) dict['PresenceGroupId']=nacp.get_PresenceGroupId(readInt64(f,'little')) f.seek(0x3040) dict['AgeRatings']=nacp.get_RatingAge(f.read(0x20)) f.seek(0x3060) try: dict['BuildNumber']=nacp.get_DisplayVersion(f.read(0xF)) f.seek(0x3070) dict['AddOnContentBaseId']=nacp.get_AddOnContentBaseId(readInt64(f,'little')) f.seek(0x3078) dict['SaveDataOwnerId']=nacp.get_SaveDataOwnerId(readInt64(f,'little')) f.seek(0x3080) dict['UserAccountSaveDataSize']=nacp.get_UserAccountSaveDataSize(readInt64(f,'little')) f.seek(0x3088) dict['UserAccountSaveDataJournalSize']=nacp.get_UserAccountSaveDataJournalSize(readInt64(f,'little')) f.seek(0x3090) dict['DeviceSaveDataSize']=nacp.get_DeviceSaveDataSize(readInt64(f,'little')) f.seek(0x3098) dict['DeviceSaveDataJournalSize']=nacp.get_DeviceSaveDataJournalSize(readInt64(f,'little')) f.seek(0x30A0) dict['BcatDeliveryCacheStorageSize']=nacp.get_BcatDeliveryCacheStorageSize(readInt64(f,'little')) f.seek(0x30A8) dict['ApplicationErrorCodeCategory']=nacp.get_ApplicationErrorCodeCategory(f.read(0x07)) f.seek(0x30B0) dict['LocalCommunicationId']=nacp.get_LocalCommunicationId(readInt64(f,'little')) f.seek(0x30F0) dict['LogoType']=nacp.get_LogoType(readInt8(f,'little')) dict['LogoHandling']=nacp.get_LogoHandling(readInt8(f,'little')) dict['RuntimeAddOnContentInstall']=nacp.get_RuntimeAddOnContentInstall(readInt8(f,'little')) dict['CrashReport']=nacp.get_CrashReport(readInt8(f,'little')) dict['Hdcp']=nacp.get_Hdcp(readInt8(f,'little')) dict['SeedForPseudoDeviceId']=nacp.get_SeedForPseudoDeviceId(readInt64(f,'little')) f.seek(0x3100) dict['BcatPassphrase']=nacp.get_BcatPassphrase(f.read(0x40)) f.seek(0x3148) dict['UserAccountSaveDataSizeMax']=nacp.par_UserAccountSaveDataSizeMax(readInt64(f,'little')) f.seek(0x3150) dict['UserAccountSaveDataJournalSizeMax']=nacp.par_UserAccountSaveDataJournalSizeMax(readInt64(f,'little')) f.seek(0x3158) dict['DeviceSaveDataSizeMax']=nacp.get_DeviceSaveDataSizeMax(readInt64(f,'little')) f.seek(0x3160) dict['DeviceSaveDataJournalSizeMax']=nacp.get_DeviceSaveDataJournalSizeMax(readInt64(f,'little')) f.seek(0x3168) dict['TemporaryStorageSize']=nacp.get_TemporaryStorageSize(readInt64(f,'little')) dict['CacheStorageSize']=nacp.get_CacheStorageSize(readInt64(f,'little')) f.seek(0x3178) dict['CacheStorageJournalSize']=nacp.get_CacheStorageJournalSize(readInt64(f,'little')) dict['CacheStorageDataAndJournalSizeMax']=nacp.get_CacheStorageDataAndJournalSizeMax(readInt64(f,'little')) f.seek(0x3188) dict['CacheStorageIndexMax']=nacp.get_CacheStorageIndexMax(readInt64(f,'little')) dict['PlayLogQueryableApplicationId']=nacp.get_PlayLogQueryableApplicationId(readInt64(f,'little')) f.seek(0x3210) dict['PlayLogQueryCapability']=nacp.get_PlayLogQueryCapability(readInt8(f,'little')) dict['Repair']=nacp.get_Repair(readInt8(f,'little')) dict['ProgramIndex']=nacp.get_ProgramIndex(readInt8(f,'little')) dict['RequiredNetworkServiceLicenseOnLaunch']=nacp.get_RequiredNetworkServiceLicenseOnLaunch(readInt8(f,'little')) except:pass return dict
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
def memoryload(filelist,target=False,ender=False): for i in range(len(filelist)): entry=filelist[i] file=entry[0];size=entry[1] initpath=entry[2];off1=entry[3] endpath=entry[4];off2=entry[5] if file.lower()==str(target).lower(): if initpath==endpath: with open(initpath, 'rb') as f: f.seek(off1) inmemoryfile = io.BytesIO(f.read(size)) inmemoryfile.seek(0) nca = Fs.Nca() nca.open(inmemoryfile) nca.read_cnmt() elif target==False and ender!=False: if str(file.lower()).endswith(ender): if initpath==endpath: with open(initpath, 'rb') as f: f.seek(off1) inmemoryfile = io.BytesIO(f.read(size)) inmemoryfile.seek(0) ncaHeader = NcaHeader() f.seek(off1) ncaHeader.open(MemoryFile(f.read(size), Type.Crypto.XTS, uhx(Keys.get('header_key')))) # ncaHeader.seek(0x400) try: nca3=NCA3(inmemoryfile,0,file,ncaHeader.titleKeyDec) for _, sec in enumerate(nca3.sections): if sec.fs_type == 'RomFS': continue for buf in sec.decrypt_raw(): DAT=buf Hex.dump(buf) # print(d) # if file.endswith('.cnmt'): # DAT=sec.fs.open(file) # for test in DAT: # Hex.dump(test) # print(DAT) except Exception as e: print('%s: %s' % (e.__class__.__name__, e)) # for i in range(4): # fs = GetSectionFilesystem(ncaHeader.read(0x200), cryptoKey = ncaHeader.titleKeyDec) # Print.info('fs type = ' + hex(fs.fsType)) # Print.info('fs crypto = ' + hex(fs.cryptoType)) # 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))) # break # pfs0=fs # sectionHeaderBlock = fs.buffer # ncaHeader.seek(fs.offset) # pfs0Offset=fs.offset # pfs0Header = f.read(0x100) # Hex.dump(pfs0Header) # mem = MemoryFile(pfs0Header, Type.Crypto.CTR, ncaHeader.titleKeyDec, pfs0.cryptoCounter, offset = pfs0Offset) # data=mem.read(); # data=ncaHeader.read() # Hex.dump(data) # nca = Fs.Nca() # f.seek(off1) # nca.open(MemoryFile(f.read(size), Type.Crypto.None, uhx(Keys.get('header_key')))) # nca.read_cnmt() break