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 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