def readFATB(self, data, ptr): hdr, ptr = self.unpack_from(GARC_FATB_HEADER, data, ptr, getptr=True) if hdr[0] != b'BTAF': error('Invalid FATB magic %s, expected BTAF' % byterepr(hdr[0]), 301) #headerlen = hdr[1] entrycount = hdr[2] self.fatb = [] for i in range(0, entrycount): entry = FATBEntry() flags, ptr = self.uint32(data, ptr) entry.flags = flags for j in range(0, 32): exists = (flags & 1) == 1 flags >>= 1 if exists: subentry = FATBSubEntry() subentry.start, ptr = self.uint32(data, ptr) subentry.end, ptr = self.uint32(data, ptr) subentry.length, ptr = self.uint32(data, ptr) entry.subentries.append(subentry) if len(entry.subentries) > 1: entry.isfolder = True self.fatb.append(entry) return ptr
def readheader(self, data): hdata = self.unpack_from(CBMD_HEADER_STRUCT, data, 0) if hdata[0] != b'CBMD': error('Invalid magic %s, expected CBMD' % byterepr(hdata[0]), 301) self.commonoffset = hdata[2] self.regionoffsets = hdata[3] self.cwavoffset = hdata[5]
def read_table(self, data): tbl = self.unpack_from(BL_TABLE_STRUCT, data, 0) if tbl[0] != b'BL': error('Invalid magic %s, expected BL' % byterepr(tbl[0]), 301) filecount = tbl[1] offsets = [el[0] for el in tbl[2]] return offsets
def readSFAT(self, data, ptr): sfat, ptr = self.unpack_from(SFAT_STRUCT, data, ptr, getptr=True) magic = sfat[0] if magic != b'SFAT': error('Issue with SFAT: invalid magic %s' % byterepr(magic), 301) #headerlen = sfat[1] self.node_count = sfat[2] self.hash_multiplier = sfat[3] self.nodes = [SFATnode(node) for node in sfat[4]] return ptr
def readmeta(self, data): meta, ptr = self.unpack_from(ALYT_META_STRUCT, data, 0, getptr=True) if meta[0] != b'ALYT': error('Invalid magic %s, expected ALYT' % byterepr(meta[0]), 301) self.ltbl = meta[10] self.lmtl = meta[11] self.lfnl = meta[12] self.nametable = [el[0].decode('utf-8') for el in meta[15]] self.symtable = [el[0].decode('utf-8') for el in meta[17]] self.sarc = data[ptr:]
def readFATO(self, data, ptr): fato, ptr = self.unpack_from(GARC_FATO_SECTION, data, ptr, getptr=True) if fato[0] != b'OTAF': error('Invalid FATO magic %s, expected OTAF' % byterepr(fato[0]), 301) #headerlen = fato[1] entrycount = fato[2] self.filenum = entrycount #padding = fato[3] table = fato[4] self.fato = [el[0] for el in table] return ptr
def readheader(self, data): magic, hdrlen, bom = rawutil.unpack_from('>4s2H', data, 0) if magic != b'SARC': error('Invalid magic %s, expected SARC' % byterepr(magic), 301) self.byteorder = ENDIANS[bom] hdr, ptr = self.unpack_from(SARC_HEADER_STRUCT, data, 0, getptr=True) #magic = hdr[0] #headerlen = hdr[1] #bom = hdr[2] #filelen = hdr[3] self.dataoffset = hdr[4] #unknown = hdr[5] return ptr
def readhdr(self, data): magic, endian = rawutil.unpack_from('>4sH', data, 0) if magic != b'darc': error('Invalid magic %s, expected darc' % byterepr(magic), 301) self.byteorder = ENDIANS[endian] hdr, ptr = self.unpack_from(DARC_HEADER_STRUCT, data, 0, getptr=True) #magic=hdr[0] #bom=hdr[1] #headerlen=hdr[2] #unknown = hdr[3] self.version = hdr[4] #filelen=hdr[5] self.tableoffset = hdr[6] self.tablelen = hdr[7] self.dataoffset = hdr[8] return ptr
def readheader(self): header = self.bflyt[:0x14] self.data = self.bflyt[0x14:] if header[0:4] != b'FLYT': error('Invalid magic %s, expected FLYT' % byterepr(header[0:4]), 301) self.byteorder = '<' if header[4:6] == b'\xff\xfe' else '>' self.endianname = 'little' if self.byteorder == '<' else 'big' hdata = self.unpack(FLYT_HEADER, header) #some unused or already read data #magic, endianness, #headerlength = hdata[2] self.version = hdata[3] #padding = hdata[4] #filesize = hdata[5] self.secnum = hdata[6]
def readmeta(self, data): hdata, ptr = self.unpack_from(GFAC_META_STRUCT, data, 0, getptr=True) magic = hdata[0] if magic != b'GFAC': error('Invalid magic %s, expected GFAC' % byterepr(magic), 301) #unknown = hdata[1] self.version = hdata[2] #headerlen = hdata[3] #metalen = hdata[4] self.dataoffset = hdata[5] #datalen = hdata[6] self.filecount = hdata[11] self.fat = hdata[12] self.filenames = hdata[13] self.readinfo() return ptr
def readSFNT(self, data, ptr): hdr, ptr = self.unpack_from(SFNT_HEADER_STRUCT, data, ptr, getptr=True) magic = hdr[0] if magic != b'SFNT': error('Issue with SFNT: invalid magic %s' % byterepr(magic), 301) #headerlen = hdr[1] #unknown = hdr[2] for i, node in enumerate(self.nodes): if node.has_name: filename = self.string(data, node.name_offset + ptr)[0] node.name = filename if self.calc_hash(filename) != node.hash: error( 'File name %s doesn\'t match his hash %08x' % (filename, node.hash), 305) else: node.name = '0x%08x.noname.bin' % node.hash self.nodes[i] = node
def readheader(self, hdr): data = self.unpack(NCCH_HEADER_STRUCT, hdr) self.rsa_signature = data[0] magic = data[1] if magic != b'NCCH': error('Invalid magic %s, expected NCCH' % byterepr(magic), 301) self.content_size = data[2] #In media units self.partition_id = rawutil.hex(data[3], 16) self.maker_code = data[4] self.version = data[5] self.id_hash = data[6] self.tid_high = rawutil.hex(data[7] >> 32, 8) self.tid_low = rawutil.hex(data[7] & 0xffffffff, 8) reserved = data[8] self.logo_hash = data[9] self.product_code = data[10].decode('ascii') self.extheader_hash = data[12] self.extheader_size = data[13] #in bytes reserved = data[14] ncchflags = data[15] self.crypto_keyslot = CRYPTO_KEYSLOTS[ncchflags[3]] self.platform = PLATFORMS[ncchflags[4]] self.content_types = self.extract_contenttypes(ncchflags[5]) self.unitsize = 0x200 << ncchflags[6] flags = ncchflags[7] self.fixed_cryptokey = bool(flags & 0x01) self.has_romfs = not bool(flags & 0x02) self.has_crypto = not bool(flags & 0x04) self.use_new_keyYgen = bool(flags & 0x20) #Everything is in media units self.plain_offset = data[16] self.plain_size = data[17] self.logo_offset = data[18] self.logo_size = data[19] self.exefs_offset = data[20] self.exefs_size = data[21] self.exefs_hashregion_size = data[22] reserved = data[23] self.romfs_offset = data[24] self.romfs_size = data[25] self.romfs_hashregion_size = data[26] reserved = data[27] self.exefs_hash = data[28] self.romfs_hash = data[29]
def read_header(self, data): bom = rawutil.unpack_from('>H', data, 4)[0] self.byteorder = '<' if bom == 0xfffe else '>' hdata = self.unpack_from(BCSTM_HEADER_STRUCT, data) magic = hdata[0] if magic != b'CSTM': error('Invalid magic %s, expected CSTM' % byterepr(magic)) bom = hdata[1] headerlen = hdata[2] self.version = hdata[3] filesize = hdata[4] blockcount = hdata[5] #Should be 3 padding = hdata[6] inforef = SizedRef(hdata[7]) seekref = SizedRef(hdata[8]) dataref = SizedRef(hdata[9]) self.info = inforef.getdata(data) self.seek = seekref.getdata(data) self.data = dataref.getdata(data)
def extract(self): data = self.gfcp magic, version, comp, self.decsize, compsize = self.unpack_from( GFCP_HEADER_STRUCT, data) data = data[20:] if magic != b'GFCP': error('Invalid GFCP magic: %s' % byterepr(magic), 301) if comp in (2, 3): print('\tDecompressing data...') data = self.decompressLZ10(data) print('\tOK!') elif comp == 1: error('Actually unsupported compression') else: error('Invalid compression') for node in self.nodes: outname = self.outdir + node.name filedata = data[node.offset:node.offset + node.length] bwrite(filedata, outname)
def readINFO(self): hdata, ptr = self.unpack_from(INFO_HEADER_STRUCT, self.info, 0, getptr=True) if hdata[0] != b'INFO': error('Invalid INFO magic: %s' % byterepr(hdata[0]), 301) infolen = hdata[1] infooffsets = [None] * 7 i = 2 while i < 16: id, offset = hdata[i:i + 2] i += 2 if id == 0x2100: infooffsets[0] = offset + 8 elif id == 0x2101: infooffsets[1] = offset + 8 elif id == 0x2102: infooffsets[2] = offset + 8 elif id == 0x2103: infooffsets[3] = offset + 8 elif id == 0x2104: infooffsets[4] = offset + 8 elif id == 0x2105: infooffsets[5] = offset + 8 elif id == 0x2106: infooffsets[6] = offset + 8 else: error('Unsupported INFO section %x' % id, 303) #unknown = hdata[16] #unknown = hdata[18] infosecs = [None] * 7 for i in range(0, len(infooffsets)): startoffset = infooffsets[i] try: endoffset = getsup(infooffsets, startoffset) except IndexError: endoffset = infolen infosecs[i] = self.info[startoffset: endoffset] self.readFileTable(infosecs[6]) self.readBankTable(infosecs[1]) self.readAudioTable(infosecs[0]) self.readPlayerTable(infosecs[2]) self.readWARTable(infosecs[3]) self.readSetTable(infosecs[4]) self.readGroupTable(infosecs[5])
def readSTRG(self): hdata, ptr = self.unpack_from(STRG_HEADER_STRUCT, self.strg, 0, getptr=True) if hdata[0] != b'STRG': error('Invalid STRG magic: %s' % byterepr(hdata[0]), 301) #strglen = hdata[1] i = 2 while i < 6: id, offset = hdata[i:i + 2] i += 2 if id == 0x2400: fntoffset = offset + 8 elif id == 0x2401: tbloffset = offset + 8 strcount = self.unpack_from('I', self.strg, fntoffset)[0] strings = [] for i in range(0, strcount): id, nameoffset, namelen = self.unpack_from('3I', self.strg, fntoffset + (i * 12) + 4) name = self.strg[fntoffset + nameoffset:fntoffset + nameoffset + namelen].rstrip(b'\x00').decode('utf-8') strings.append(name) self.strings = strings
def readheader(self, data): hdata = self.unpack_from(CSAR_HEADER_STRUCT, data, 0) if hdata[0] != b'CSAR': error('Invalid magic %s, expected CSAR' % byterepr(hdata[0]), 301) #bom = hdata[1] #headerlen = hdata[2] self.version = hdata[3] #filelen = hdata[4] #seccount = hdata[5] i = 6 while i < 14: id, offset, length = hdata[i:i + 3] i += 3 secdata = data[offset:offset + length] if id == 0x2000: self.strg = secdata elif id == 0x2001: self.info = secdata elif id == 0x2002: self.file = secdata self.fileoffset = offset else: error('Unsupported partition 0x%04x' % id, 303)
def readheader(self, data): magic, self.unco_len, unknown = self.unpack_from( Yaz0_HEADER_STRUCT, data, 0) if magic != b'Yaz0': error('Invalid magic %s, expected Yaz0' % byterepr(magic)) return data[0x10:]