def createFields(self): # Header yield NullBytes(self, "zero_vector", 16) yield GUID(self, "fs_guid") yield UInt64(self, "volume_len") yield String(self, "signature", 4) yield UInt32(self, "attributes") yield UInt16(self, "header_len") yield UInt16(self, "checksum") yield UInt16(self, "ext_header_offset") yield UInt8(self, "reserved") yield UInt8(self, "revision") while True: bm = BlockMap(self, "block_map[]") yield bm if bm['num_blocks'].value == 0 and bm['len'].value == 0: break # TODO must handle extended header # Content while not self.eof: padding = paddingSize(self.current_size // 8, 8) if padding: yield PaddingBytes(self, "padding[]", padding) yield File(self, "file[]")
def createFields(self): yield UInt16(self, "size", "Node size (in bytes)") yield UInt16(self, "data_size") yield Enum(UInt16(self, "type"), self.TYPE_NAME) yield CString(self, "name", charset="UTF-16-LE") size = paddingSize(self.current_size // 8, 4) if size: yield NullBytes(self, "padding[]", size) size = self["data_size"].value if size: if self["type"].value == self.TYPE_STRING: if self.is_32bit: size *= 2 yield String(self, "value", size, charset="UTF-16-LE", truncate="\0") elif self["name"].value == "VS_VERSION_INFO": yield VersionInfoBinary(self, "value", size=size * 8) if self["value/file_flags_mask"].value == 0: self.is_32bit = False else: yield RawBytes(self, "value", size) while 12 <= (self.size - self.current_size) // 8: yield VersionInfoNode(self, "node[]", self.is_32bit) size = (self.size - self.current_size) // 8 if size: yield NullBytes(self, "padding[]", size)
def createFields(self): yield textHandler(UInt32(self, "crc32"), hexadecimal) yield UInt16(self, "size") yield UInt16( self, "uncompressed_size", "If this is 0, this block is continued in a subsequent cabinet") if self["/flags/has_reserved"].value and self[ "/reserved_data_size"].value: yield RawBytes(self, "reserved_data", self["/reserved_data_size"].value, "Per-datablock reserved area") compr_method = self.parent.folder["compr_method"].value if compr_method == 0: # Uncompressed yield RawBytes(self, "data", self["size"].value, "Folder Data") self.parent.uncompressed_data += self["data"].value elif compr_method == 1: # MSZIP yield String(self, "mszip_signature", 2, "MSZIP Signature (CK)") yield DeflateBlock(self, "deflate_block", self.parent.uncompressed_data) padding = paddingSize(self.current_size, 8) if padding: yield PaddingBits(self, "padding[]", padding) self.parent.uncompressed_data = self["deflate_block"].uncomp_data elif compr_method == 2: # Quantum yield RawBytes(self, "compr_data", self["size"].value, "Compressed Folder Data") elif compr_method == 3: # LZX group = getattr(self.parent.folder, "lzx_group", None) field = CustomFragment(self, "data", self["size"].value * 8, LZXStream, "LZX data fragment", group) if group is None: field.group.args["compr_level"] = self.parent.folder[ "compr_level"].value self.parent.folder.lzx_group = field.group yield field
def createFields(self): dictionary = {} self.nbits = self.startbits CLEAR_CODE = 2**self.nbits END_CODE = CLEAR_CODE + 1 compress_code = CLEAR_CODE + 2 obuf = [] output = [] while True: if compress_code >= 2**self.nbits: self.nbits += 1 code = Bits(self, "code[]", self.nbits) if code.value == CLEAR_CODE: if compress_code == 2**(self.nbits - 1): # this fixes a bizarre edge case where the reset code could # appear just after the bits incremented. Apparently, the # correct behaviour is to express the reset code with the # old number of bits, not the new... code = Bits(self, "code[]", self.nbits - 1) self.nbits = self.startbits + 1 dictionary = {} compress_code = CLEAR_CODE + 2 obuf = [] code._description = "Reset Code (LZW code %i)" % code.value yield code continue elif code.value == END_CODE: code._description = "End of Information Code (LZW code %i)" % code.value yield code break if code.value < CLEAR_CODE: # literal if obuf: chain = obuf + [code.value] dictionary[compress_code] = chain compress_code += 1 obuf = [code.value] output.append(code.value) code._description = "Literal Code %i" % code.value elif code.value >= CLEAR_CODE + 2: if code.value in dictionary: chain = dictionary[code.value] code._description = "Compression Code %i (found in dictionary as %s)" % ( code.value, rle_repr(chain)) else: chain = obuf + [obuf[0]] code._description = "Compression Code %i (not found in dictionary; guessed to be %s)" % ( code.value, rle_repr(chain)) dictionary[compress_code] = obuf + [chain[0]] compress_code += 1 obuf = chain output += chain code._description += "; Current Decoded Length %i" % len(output) yield code padding = paddingSize(self.current_size, 8) if padding: yield NullBits(self, "padding[]", padding)
def createFields(self): yield Bits(self, "nbits", 5) nbits = self["nbits"].value if not nbits: raise ParserError("SWF parser: Invalid RECT field size (0)") yield Bits(self, "xmin", nbits, "X minimum in twips") yield Bits(self, "xmax", nbits, "X maximum in twips") yield Bits(self, "ymin", nbits, "Y minimum in twips") yield Bits(self, "ymax", nbits, "Y maximum in twips") size = paddingSize(self.current_size, 8) if size: yield NullBits(self, "padding", size)
def createFields(self): uncomp_data = "" blk = DeflateBlock(self, "compressed_block[]", uncomp_data) yield blk uncomp_data = blk.uncomp_data while not blk["final"].value: blk = DeflateBlock(self, "compressed_block[]", uncomp_data) yield blk uncomp_data = blk.uncomp_data padding = paddingSize(self.current_size + self.absolute_address, 8) # align on byte boundary if padding: yield PaddingBits(self, "padding[]", padding) self.uncompressed_data = uncomp_data
def createFields(self): self.uncompressed_data = "" self.r0 = 1 self.r1 = 1 self.r2 = 1 yield Bit(self, "filesize_indicator") if self["filesize_indicator"].value: yield UInt32(self, "filesize") while self.current_size < self.size: block = LZXBlock(self, "block[]") yield block if self.size - self.current_size < 16: padding = paddingSize(self.address + self.current_size, 16) if padding: yield PaddingBits(self, "padding[]", padding) break
def createFields(self): yield UInt16(self, "size", "Node size (in bytes)") yield UInt16(self, "data_size") yield CString(self, "name", charset="ISO-8859-1") size = paddingSize(self.current_size // 8, 4) if size: yield NullBytes(self, "padding[]", size) size = self["data_size"].value if size: if self["name"].value == "VS_VERSION_INFO": yield VersionInfoBinary(self, "value", size=size * 8) else: yield String(self, "value", size, charset="ISO-8859-1") while 12 <= (self.size - self.current_size) // 8: yield NE_VersionInfoNode(self, "node[]") size = (self.size - self.current_size) // 8 if size: yield NullBytes(self, "padding[]", size)
def createFields(self): end = False while not end: marker = self.stream.readBits( self.absolute_address + self.current_size, 48, self.endian) if marker == self.START_BLOCK: yield Bzip2Block(self, "block[]") elif marker == self.END_STREAM: yield textHandler( Bits(self, "stream_end", 48, "End-of-stream marker"), hexadecimal) yield textHandler( UInt32(self, "crc32", "CRC32 for entire stream"), hexadecimal) padding = paddingSize(self.current_size, 8) if padding: yield PaddingBits(self, "padding[]", padding) end = True else: raise ParserError("Invalid marker 0x%02X!" % marker)
def createFields(self): yield UInt32(self, "nblocks") yield UInt32(self, "unknown", description="Always 0") for i in xrange(self['nblocks'].value): yield BlockAddress(self, "block[]") padding = paddingSize(self['nblocks'].value, 256) if padding: yield NullBytes( self, "padding", padding * 4, description= "padding to make the number of blocks a multiple of 256") yield UInt32(self, "ndirs") for i in xrange(self['ndirs'].value): yield BudDirectory(self, "dir[]") for i in xrange(32): yield FreeList(self, "freelist[]") if self.current_size < self.size: yield PaddingBytes(self, "slack", (self.size - self.current_size) // 8, description="slack space")
def createFields(self): yield PropertiesFormat(self, "format") yield UInt32(self, "nb_prop") properties = [] for index in xrange(self["nb_prop"].value): property = Property(self, "property[]") yield property properties.append(property) padding = paddingSize(self.current_size // 8, 4) if padding: yield NullBytes(self, "padding", padding) yield UInt32(self, "total_str_length") properties.sort(key=lambda entry: entry["name_offset"].value) offset0 = self.current_size // 8 for property in properties: padding = self.seekByte(offset0 + property["name_offset"].value) if padding: yield padding yield CString(self, "name[]", "Name of %s" % property.name) if property["is_string"].value: yield CString(self, "value[]", "Value of %s" % property.name) padding = (self.size - self.current_size) // 8 if padding: yield NullBytes(self, "end_padding", padding)
def createFields(self): yield UInt16(self, "length", "Length of Item ID Entry") if not self["length"].value: return yield Enum(UInt8(self, "type"), self.ITEM_TYPE) entrytype = self["type"].value if entrytype in (0x1F, 0x70): # GUID yield RawBytes(self, "dummy", 1, "should be 0x50") yield GUID(self, "guid") elif entrytype == 0x2E: # Shell extension yield RawBytes(self, "dummy", 1, "should be 0x50") if self["dummy"].value == '\0': yield UInt16(self, "length_data", "Length of shell extension-specific data") if self["length_data"].value: yield RawBytes(self, "data", self["length_data"].value, "Shell extension-specific data") yield GUID(self, "handler_guid") yield GUID(self, "guid") elif entrytype in (0x23, 0x25, 0x29, 0x2F): # Drive yield String(self, "drive", self["length"].value - 3, strip="\0") elif entrytype in (0x30, 0x31, 0x32, 0x61, 0xb1): yield RawBytes(self, "dummy", 1, "should be 0x00") yield UInt32(self, "size", "size of file; 0 for folders") yield DateTimeMSDOS32(self, "date_time", "File/folder date and time") yield MSDOSFileAttr16(self, "attribs", "File/folder attributes") yield CString(self, "name", "File/folder name") if self.root.hasUnicodeNames(): # Align to 2-bytes n = paddingSize(self.current_size // 8, 2) if n: yield PaddingBytes(self, "pad", n) yield UInt16(self, "length_w", "Length of wide struct member") yield RawBytes(self, "unknown[]", 6) yield DateTimeMSDOS32(self, "creation_date_time", "File/folder creation date and time") yield DateTimeMSDOS32(self, "access_date_time", "File/folder last access date and time") yield RawBytes(self, "unknown[]", 2) yield UInt16( self, "length_next", "Length of next two strings (if zero, ignore this field)") yield CString(self, "unicode_name", "File/folder name", charset="UTF-16-LE") if self["length_next"].value: yield CString(self, "localized_name", "Localized name") yield RawBytes(self, "unknown[]", 2) else: yield CString(self, "name_short", "File/folder short name") elif entrytype in (0x41, 0x42, 0x46): yield RawBytes(self, "unknown[]", 2) yield CString(self, "name") yield CString(self, "protocol") yield RawBytes(self, "unknown[]", 2) elif entrytype == 0x47: # Whole Network yield RawBytes(self, "unknown[]", 2) yield CString(self, "name") elif entrytype == 0xC3: # Network Share yield RawBytes(self, "unknown[]", 2) yield CString(self, "name") yield CString(self, "protocol") yield CString(self, "description") yield RawBytes(self, "unknown[]", 2) elif entrytype == 0x4C: # Web Folder yield RawBytes(self, "unknown[]", 5) yield TimestampWin64(self, "modification_time") yield UInt32(self, "unknown[]") yield UInt32(self, "unknown[]") yield UInt32(self, "unknown[]") yield LnkString(self, "name") yield RawBytes(self, "padding[]", 2) yield LnkString(self, "address") if self["address/length"].value: yield RawBytes(self, "padding[]", 2) else: yield RawBytes(self, "raw", self["length"].value - 3)
def createFields(self): yield Bits(self, "block_type", 3) yield Bits(self, "block_size", 24) self.uncompressed_size = self["block_size"].value self.compression_level = self.root.compr_level self.window_size = self.WINDOW_SIZE[self.compression_level] self.block_type = self["block_type"].value curlen = len(self.parent.uncompressed_data) if self.block_type in (1, 2): # Verbatim or aligned offset block if self.block_type == 2: for i in xrange(8): yield Bits(self, "aligned_len[]", 3) aligned_tree = build_tree( [self['aligned_len[%d]' % i].value for i in xrange(8)]) yield LZXPreTreeEncodedTree(self, "main_tree_start", 256) yield LZXPreTreeEncodedTree(self, "main_tree_rest", self.window_size * 8) main_tree = build_tree(self["main_tree_start"].lengths + self["main_tree_rest"].lengths) yield LZXPreTreeEncodedTree(self, "length_tree", 249) length_tree = build_tree(self["length_tree"].lengths) current_decoded_size = 0 while current_decoded_size < self.uncompressed_size: if (curlen + current_decoded_size) % 32768 == 0 and ( curlen + current_decoded_size) != 0: padding = paddingSize(self.address + self.current_size, 16) if padding: yield PaddingBits(self, "padding[]", padding) field = HuffmanCode(self, "main_code[]", main_tree) if field.realvalue < 256: field._description = "Literal value %r" % chr( field.realvalue) current_decoded_size += 1 self.parent.uncompressed_data += chr(field.realvalue) yield field continue position_header, length_header = divmod( field.realvalue - 256, 8) info = self.POSITION_SLOTS[position_header] if info[2] == 0: if info[0] == 0: position = self.parent.r0 field._description = "Position Slot %i, Position [R0] (%i)" % ( position_header, position) elif info[0] == 1: position = self.parent.r1 self.parent.r1 = self.parent.r0 self.parent.r0 = position field._description = "Position Slot %i, Position [R1] (%i)" % ( position_header, position) elif info[0] == 2: position = self.parent.r2 self.parent.r2 = self.parent.r0 self.parent.r0 = position field._description = "Position Slot %i, Position [R2] (%i)" % ( position_header, position) else: position = info[0] - 2 self.parent.r2 = self.parent.r1 self.parent.r1 = self.parent.r0 self.parent.r0 = position field._description = "Position Slot %i, Position %i" % ( position_header, position) else: field._description = "Position Slot %i, Positions %i to %i" % ( position_header, info[0] - 2, info[1] - 2) if length_header == 7: field._description += ", Length Values 9 and up" yield field length_field = HuffmanCode(self, "length_code[]", length_tree) length = length_field.realvalue + 9 length_field._description = "Length Code %i, total length %i" % ( length_field.realvalue, length) yield length_field else: field._description += ", Length Value %i (Huffman Code %i)" % ( length_header + 2, field.value) yield field length = length_header + 2 if info[2]: if self.block_type == 1 or info[2] < 3: # verbatim extrafield = Bits( self, "position_extra[%s" % field.name.split('[')[1], info[2]) position = extrafield.value + info[0] - 2 extrafield._description = "Position Extra Bits (%i), total position %i" % ( extrafield.value, position) yield extrafield else: # aligned offset position = info[0] - 2 if info[2] > 3: extrafield = Bits( self, "position_verbatim[%s" % field.name.split('[')[1], info[2] - 3) position += extrafield.value * 8 extrafield._description = "Position Verbatim Bits (%i), added position %i" % ( extrafield.value, extrafield.value * 8) yield extrafield if info[2] >= 3: extrafield = HuffmanCode( self, "position_aligned[%s" % field.name.split('[')[1], aligned_tree) position += extrafield.realvalue extrafield._description = "Position Aligned Bits (%i), total position %i" % ( extrafield.realvalue, position) yield extrafield self.parent.r2 = self.parent.r1 self.parent.r1 = self.parent.r0 self.parent.r0 = position self.parent.uncompressed_data = extend_data( self.parent.uncompressed_data, length, position) current_decoded_size += length elif self.block_type == 3: # Uncompressed block padding = paddingSize(self.address + self.current_size, 16) if padding: yield PaddingBits(self, "padding[]", padding) else: yield PaddingBits(self, "padding[]", 16) self.endian = LITTLE_ENDIAN yield UInt32(self, "r[]", "New value of R0") yield UInt32(self, "r[]", "New value of R1") yield UInt32(self, "r[]", "New value of R2") self.parent.r0 = self["r[0]"].value self.parent.r1 = self["r[1]"].value self.parent.r2 = self["r[2]"].value yield RawBytes(self, "data", self.uncompressed_size) self.parent.uncompressed_data += self["data"].value if self["block_size"].value % 2: yield PaddingBits(self, "padding", 8) else: raise ParserError("Unknown block type %d!" % self.block_type)
def createFields(self): yield String(self, "name", 100, "Name", strip="\0", charset="ISO-8859-1") yield String(self, "mode", 8, "Mode", strip=" \0", charset="ASCII") yield String(self, "uid", 8, "User ID", strip=" \0", charset="ASCII") yield String(self, "gid", 8, "Group ID", strip=" \0", charset="ASCII") yield String(self, "size", 12, "Size", strip=" \0", charset="ASCII") yield String(self, "mtime", 12, "Modification time", strip=" \0", charset="ASCII") yield String(self, "check_sum", 8, "Check sum", strip=" \0", charset="ASCII") yield Enum(UInt8(self, "type", "Type"), self.type_name) yield String(self, "lname", 100, "Link name", strip=" \0", charset="ISO-8859-1") yield String(self, "magic", 8, "Magic", strip=" \0", charset="ASCII") yield String(self, "uname", 32, "User name", strip=" \0", charset="ISO-8859-1") yield String(self, "gname", 32, "Group name", strip=" \0", charset="ISO-8859-1") yield String(self, "devmajor", 8, "Dev major", strip=" \0", charset="ASCII") yield String(self, "devminor", 8, "Dev minor", strip=" \0", charset="ASCII") yield String(self, "prefix", 155, "Prefix for filename", strip="\0", charset="ASCII") yield NullBytes(self, "padding", 12, "Padding (zero)") filesize = self.getOctal("size") if filesize: yield SubFile(self, "content", filesize, filename=self["name"].value) size = paddingSize(self.current_size // 8, 512) if size: yield NullBytes(self, "padding_end", size, "Padding (512 align)")
def createFields(self): yield Bit(self, "final", "Is this the final block?") # BFINAL yield Enum( Bits(self, "compression_type", 2), # BTYPE { 0: "None", 1: "Fixed Huffman", 2: "Dynamic Huffman", 3: "Reserved" }) if self["compression_type"].value == 0: # no compression padding = paddingSize(self.current_size + self.absolute_address, 8) # align on byte boundary if padding: yield PaddingBits(self, "padding[]", padding) yield Int16(self, "len") yield Int16(self, "nlen", "One's complement of len") if self["len"].value != ~self["nlen"].value: raise ParserError( "len must be equal to the one's complement of nlen!") if self["len"].value: # null stored blocks produced by some encoders (e.g. PIL) yield RawBytes(self, "data", self["len"].value, "Uncompressed data") return elif self["compression_type"].value == 1: # Fixed Huffman length_tree = {} # (size, huffman code): value distance_tree = {} for i in xrange(144): length_tree[(8, i + 48)] = i for i in xrange(144, 256): length_tree[(9, i + 256)] = i for i in xrange(256, 280): length_tree[(7, i - 256)] = i for i in xrange(280, 288): length_tree[(8, i - 88)] = i for i in xrange(32): distance_tree[(5, i)] = i elif self["compression_type"].value == 2: # Dynamic Huffman yield Bits(self, "huff_num_length_codes", 5, "Number of Literal/Length Codes, minus 257") yield Bits(self, "huff_num_distance_codes", 5, "Number of Distance Codes, minus 1") yield Bits(self, "huff_num_code_length_codes", 4, "Number of Code Length Codes, minus 4") code_length_code_lengths = [0] * 19 # confusing variable name... for i in self.CODE_LENGTH_ORDER[:self["huff_num_code_length_codes"] .value + 4]: field = Bits(self, "huff_code_length_code[%i]" % i, 3, "Code lengths for the code length alphabet") yield field code_length_code_lengths[i] = field.value code_length_tree = build_tree(code_length_code_lengths) length_code_lengths = [] distance_code_lengths = [] for numcodes, name, lengths in ( (self["huff_num_length_codes"].value + 257, "length", length_code_lengths), (self["huff_num_distance_codes"].value + 1, "distance", distance_code_lengths)): while len(lengths) < numcodes: field = HuffmanCode(self, "huff_%s_code[]" % name, code_length_tree) value = field.realvalue if value < 16: prev_value = value field._description = "Literal Code Length %i (Huffman Code %i)" % ( value, field.value) yield field lengths.append(value) else: info = { 16: (3, 6, 2), 17: (3, 10, 3), 18: (11, 138, 7) }[value] if value == 16: repvalue = prev_value else: repvalue = 0 field._description = "Repeat Code %i, Repeating value (%i) %i to %i times (Huffman Code %i)" % ( value, repvalue, info[0], info[1], field.value) yield field extrafield = Bits( self, "huff_%s_code_extra[%s" % (name, field.name.split('[')[1]), info[2]) num_repeats = extrafield.value + info[0] extrafield._description = "Repeat Extra Bits (%i), total repeats %i" % ( extrafield.value, num_repeats) yield extrafield lengths += [repvalue] * num_repeats length_tree = build_tree(length_code_lengths) distance_tree = build_tree(distance_code_lengths) else: raise ParserError("Unsupported compression type 3!") while True: field = HuffmanCode(self, "length_code[]", length_tree) value = field.realvalue if value < 256: field._description = "Literal Code %r (Huffman Code %i)" % ( chr(value), field.value) yield field self.uncomp_data += chr(value) if value == 256: field._description = "Block Terminator Code (256) (Huffman Code %i)" % field.value yield field break elif value > 256: info = self.LENGTH_SYMBOLS[value] if info[2] == 0: field._description = "Length Code %i, Value %i (Huffman Code %i)" % ( value, info[0], field.value) length = info[0] yield field else: field._description = "Length Code %i, Values %i to %i (Huffman Code %i)" % ( value, info[0], info[1], field.value) yield field extrafield = Bits( self, "length_extra[%s" % field.name.split('[')[1], info[2]) length = extrafield.value + info[0] extrafield._description = "Length Extra Bits (%i), total length %i" % ( extrafield.value, length) yield extrafield field = HuffmanCode(self, "distance_code[]", distance_tree) value = field.realvalue info = self.DISTANCE_SYMBOLS[value] if info[2] == 0: field._description = "Distance Code %i, Value %i (Huffman Code %i)" % ( value, info[0], field.value) distance = info[0] yield field else: field._description = "Distance Code %i, Values %i to %i (Huffman Code %i)" % ( value, info[0], info[1], field.value) yield field extrafield = Bits( self, "distance_extra[%s" % field.name.split('[')[1], info[2]) distance = extrafield.value + info[0] extrafield._description = "Distance Extra Bits (%i), total length %i" % ( extrafield.value, distance) yield extrafield self.uncomp_data = extend_data(self.uncomp_data, length, distance)