コード例 #1
0
    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
コード例 #2
0
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
コード例 #3
0
    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
コード例 #4
0
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
コード例 #5
0
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
コード例 #6
0
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						
コード例 #7
0
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
コード例 #8
0
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