def getSizeOfTrailingDataEntry(data): num = 0 for v in data[-4:]: if bord(v) & 0x80: num = 0 num = (num << 7) | (bord(v) & 0x7f) return num
def describe(data): txtans = '' hexans = hexlify(data) for i in data: if bord(i) < 32 or bord(i) > 127: txtans += '?' else: txtans += bchar(i).decode('latin-1') return '"' + txtans + '"' + ' 0x' + hexans
def Idpf_mangle_fonts(encryption_key, data): if isinstance(data, text_type): print('Error: font data must be a byte string') crypt = data[:1040] key = cycle(iter(map(bord, encryption_key))) encrypt = b''.join([bchr(bord(x) ^ next(key)) for x in crypt]) return encrypt + data[1040:]
def Idpf_mangle_fonts(encryption_key, data): if isinstance(data, text_type): print('Error: font data must be a byte string') crypt = data[:1040] key = cycle(iter(map(bord, encryption_key))) encrypt = b''.join([bchr(bord(x)^next(key)) for x in crypt]) return encrypt + data[1040:]
def getIndexData(self, idx, label="Unknown"): sect = self.sect outtbl = [] ctoc_text = {} if idx != 0xffffffff: sect.setsectiondescription(idx, "{0} Main INDX section".format(label)) data = sect.loadSection(idx) idxhdr, hordt1, hordt2 = self.parseINDXHeader(data) IndexCount = idxhdr['count'] # handle the case of multiple sections used for CTOC rec_off = 0 off = idx + IndexCount + 1 for j in range(idxhdr['nctoc']): cdata = sect.loadSection(off + j) sect.setsectiondescription(off + j, label + ' CTOC Data ' + str(j)) ctocdict = self.readCTOC(cdata) for k in ctocdict: ctoc_text[k + rec_off] = ctocdict[k] rec_off += 0x10000 tagSectionStart = idxhdr['len'] controlByteCount, tagTable = readTagSection(tagSectionStart, data) if self.DEBUG: print("ControlByteCount is", controlByteCount) print("IndexCount is", IndexCount) print("TagTable: %s" % tagTable) for i in range(idx + 1, idx + 1 + IndexCount): sect.setsectiondescription( i, "{0} Extra {1:d} INDX section".format(label, i - idx)) data = sect.loadSection(i) hdrinfo, ordt1, ordt2 = self.parseINDXHeader(data) idxtPos = hdrinfo['start'] entryCount = hdrinfo['count'] if self.DEBUG: print(idxtPos, entryCount) # loop through to build up the IDXT position starts idxPositions = [] for j in range(entryCount): pos, = struct.unpack_from(b'>H', data, idxtPos + 4 + (2 * j)) idxPositions.append(pos) # The last entry ends before the IDXT tag (but there might be zero fill bytes we need to ignore!) idxPositions.append(idxtPos) # for each entry in the IDXT build up the tagMap and any associated text for j in range(entryCount): startPos = idxPositions[j] endPos = idxPositions[j + 1] textLength = ord(data[startPos:startPos + 1]) text = data[startPos + 1:startPos + 1 + textLength] if hordt2 is not None: text = b''.join(bchr(hordt2[bord(x)]) for x in text) tagMap = getTagMap(controlByteCount, tagTable, data, startPos + 1 + textLength, endPos) outtbl.append([text, tagMap]) if self.DEBUG: print(tagMap) print(text) return outtbl, ctoc_text
def mangle_fonts(encryption_key, data): if isinstance(encryption_key, text_type): encryption_key = encryption_key.encode('latin-1') crypt = data[:1024] key = cycle(iter(map(bord, encryption_key))) # encrypt = ''.join([chr(ord(x)^key.next()) for x in crypt]) encrypt = b''.join([bchr(bord(x) ^ next(key)) for x in crypt]) return encrypt + data[1024:]
def getTagMap(controlByteCount, tagTable, entryData, startPos, endPos): ''' Create a map of tags and values from the given byte section. @param controlByteCount: The number of control bytes. @param tagTable: The tag table. @param entryData: The data to process. @param startPos: The starting position in entryData. @param endPos: The end position in entryData or None if it is unknown. @return: Hashmap of tag and list of values. ''' tags = [] tagHashMap = {} controlByteIndex = 0 dataStart = startPos + controlByteCount for tag, valuesPerEntry, mask, endFlag in tagTable: if endFlag == 0x01: controlByteIndex += 1 continue cbyte = ord(entryData[startPos + controlByteIndex:startPos + controlByteIndex + 1]) if 0: print("Control Byte Index %0x , Control Byte Value %0x" % (controlByteIndex, cbyte)) value = ord(entryData[startPos + controlByteIndex:startPos + controlByteIndex + 1]) & mask if value != 0: if value == mask: if countSetBits(mask) > 1: # If all bits of masked value are set and the mask has more than one bit, a variable width value # will follow after the control bytes which defines the length of bytes (NOT the value count!) # which will contain the corresponding variable width values. consumed, value = getVariableWidthValue( entryData, dataStart) dataStart += consumed tags.append((tag, None, value, valuesPerEntry)) else: tags.append((tag, 1, None, valuesPerEntry)) else: # Shift bits to get the masked value. while mask & 0x01 == 0: mask = mask >> 1 value = value >> 1 tags.append((tag, value, None, valuesPerEntry)) for tag, valueCount, valueBytes, valuesPerEntry in tags: values = [] if valueCount is not None: # Read valueCount * valuesPerEntry variable width values. for _ in range(valueCount): for _ in range(valuesPerEntry): consumed, data = getVariableWidthValue( entryData, dataStart) dataStart += consumed values.append(data) else: # Convert valueBytes to variable width values. totalConsumed = 0 while totalConsumed < valueBytes: # Does this work for valuesPerEntry != 1? consumed, data = getVariableWidthValue(entryData, dataStart) dataStart += consumed totalConsumed += consumed values.append(data) if totalConsumed != valueBytes: print("Error: Should consume %s bytes, but consumed %s" % (valueBytes, totalConsumed)) tagHashMap[tag] = values # Test that all bytes have been processed if endPos is given. if endPos is not None and dataStart != endPos: # The last entry might have some zero padding bytes, so complain only if non zero bytes are left. for char in entryData[dataStart:endPos]: if bord(char) != 0: print("Warning: There are unprocessed index bytes left: %s" % toHex(entryData[dataStart:endPos])) if 0: print("controlByteCount: %s" % controlByteCount) print("tagTable: %s" % tagTable) print("data: %s" % toHex(entryData[startPos:endPos])) print("tagHashMap: %s" % tagHashMap) break return tagHashMap