def createFields(self): if self.stream.readBits(self.absolute_address, 6, self.endian) == 63: yield Bits(self, "length_ext", 6) yield Bits(self, "code", 10) yield filesizeHandler(UInt32(self, "length")) else: yield filesizeHandler(Bits(self, "length", 6)) yield Bits(self, "code", 10) size = self["length"].value if 0 < size: if self.parser: for field in self.parser(self, size): yield field else: yield RawBytes(self, "data", size)
def createFields(self): yield textHandler(UInt8(self, "header", "Header"), hexadecimal) if self["header"].value != 0xFF: raise ParserError("JPEG: Invalid chunk header!") yield textHandler(UInt8(self, "type", "Type"), hexadecimal) tag = self["type"].value if tag in [self.TAG_SOI, self.TAG_EOI] + range(0xD0, 0xD8): # D0 - D7 inclusive are the restart markers return yield UInt16(self, "size", "Size") size = (self["size"].value - 2) if 0 < size: if self._parser: yield self._parser(self, "content", "Chunk content", size=size*8) else: yield RawBytes(self, "data", size, "Data")
def createFields(self): if self.stream.readBytes(self.absolute_address, 5) != "Adobe": yield RawBytes(self, "raw", self.size // 8, "Raw data") return yield String(self, "adobe", 5, "\"Adobe\" string", charset="ASCII") yield UInt16(self, "version", "DCT encoder version") yield Enum(Bit(self, "flag00"), { False: "Chop down or subsampling", True: "Blend" }) yield NullBits(self, "flags0_reserved", 15) yield NullBytes(self, "flags1", 2) yield Enum( UInt8(self, "color_transform", "Colorspace transformation code"), self.COLORSPACE_TRANSFORMATION)
def createFields(self): if not self.LFN: yield String(self, "name", 8, "DOS file name (padded with spaces)", strip=' ', charset="ASCII") yield String(self, "ext", 3, "DOS file extension (padded with spaces)", strip=' ', charset="ASCII") yield Bit(self, "read_only") yield Bit(self, "hidden") yield Bit(self, "system") yield Bit(self, "volume_label") yield Bit(self, "directory") yield Bit(self, "archive") yield Bit(self, "device") yield Bit(self, "unused") yield RawBytes(self, "reserved", 1, "Something about the case") yield Date(self, "create") yield Date(self, "access") if self.parent.parent.version > 16: yield UInt16(self, "cluster_hi") else: yield UInt16(self, "ea_index") yield Date(self, "modify") yield UInt16(self, "cluster_lo") size = UInt32(self, "size") yield size if self.process: del self.process target_size = size.value if self["directory"].value: if target_size: size.error("(FAT) value must be zero") target_size = 0 elif not target_size: return self.target_size = 8 * target_size yield InodeLink(self, "data") else: yield UInt8(self, "seq_no", "Sequence Number") yield String(self, "name[]", 10, "(5 UTF-16 characters)", charset="UTF-16-LE") yield UInt8(self, "magic", "Magic number (15)") yield NullBytes(self, "reserved", 1, "(always 0)") yield UInt8(self, "checksum", "Checksum of DOS file name") yield String(self, "name[]", 12, "(6 UTF-16 characters)", charset="UTF-16-LE") yield UInt16(self, "first_cluster", "(always 0)") yield String(self, "name[]", 4, "(2 UTF-16 characters)", charset="UTF-16-LE")
def createFields(self): yield Bits(self, "marker[]", 1) yield Bits(self, "rate_bound", 22) yield Bits(self, "marker[]", 1) yield Bits(self, "audio_bound", 6) yield Bit(self, "fixed_bitrate") yield Bit(self, "csps", description="Constrained system parameter stream") yield Bit(self, "audio_lock") yield Bit(self, "video_lock") yield Bits(self, "marker[]", 1) yield Bits(self, "video_bound", 5) length = self['../length'].value - 5 if length: yield RawBytes(self, "raw[]", length)
def parseDefineSound(parent, size): yield UInt16(parent, "sound_id") yield Bit(parent, "is_stereo") yield Bit(parent, "is_16bit") yield textHandler(Bits(parent, "rate", 2), bit2hertz) yield Enum(Bits(parent, "codec", 4), SOUND_CODEC) yield UInt32(parent, "sample_count") if parent["codec"].value == SOUND_CODEC_MP3: yield UInt16(parent, "len") size = (parent.size - parent.current_size) // 8 if size: yield RawBytes(parent, "music_data", size)
def createFields(self): yield TimestampUnix32(self, "ts_epoch", "Timestamp (Epoch)") yield UInt32(self, "ts_nanosec", "Timestamp (nano second)") yield UInt32(self, "caplen", "length of portion present") yield UInt32(self, "len", "length this packet (off wire)") # Read different layers field = self._first_parser(self, self._first_name) while field: yield field field = field.parseNext(self) # Read data if any size = (self.size - self.current_size) // 8 if size: yield RawBytes(self, "data", size)
def createFields(self): yield MasterBootRecord(self, "mbr") bios = self["mbr/bios"] cluster_size = bios["sectors_per_cluster"].value * bios[ "bytes_per_sector"].value offset = self["mbr/mft_cluster"].value * cluster_size padding = self.seekByte(offset, relative=False) if padding: yield padding for index in xrange(1000): yield File(self, "file[]") size = (self.size - self.current_size) // 8 if size: yield RawBytes(self, "end", size)
def createFields(self): # Find synchronisation bytes padding = self.synchronize() if padding: yield padding while self.current_size < self.size: yield Frame(self, "frame[]") # padding = self.synchronize() # if padding: # yield padding # Read raw bytes at the end (if any) size = (self.size - self.current_size) / 8 if size: yield RawBytes(self, "raw", size)
def createFields(self): yield String(self, "signature", 4, "AVI header (RIFF)", charset="ASCII") yield filesizeHandler(UInt32(self, "filesize", "File size")) yield String(self, "type", 4, "Content type (\"AVI \", \"WAVE\", ...)", charset="ASCII") # Choose chunk type depending on file type try: chunk_cls = self.VALID_TYPES[self["type"].value][0] except KeyError: chunk_cls = Chunk # Parse all chunks up to filesize while self.current_size < self["filesize"].value*8+8: yield chunk_cls(self, "chunk[]") if not self.eof: yield RawBytes(self, "padding[]", (self.size-self.current_size)/8)
def createFields(self): uid = self.stream.readBits(self.absolute_address, 8, LITTLE_ENDIAN) if uid == ID_HEADER: yield IDHeader(self, "header", ID_INFO[ID_HEADER]) elif uid == ID_ENCODED_HEADER: yield EncodedHeader(self, "encoded_hdr", ID_INFO[ID_ENCODED_HEADER]) # Game Over: this is usually encoded using LZMA, not copy # See SzReadAndDecodePackedStreams/SzDecode being called with the # data position from "/next_hdr/encoded_hdr/pack_info/pack_pos" # We should process further, yet we can't... else: ParserError("Unexpected ID %u" % uid) size = self._size - self.current_size if size > 0: yield RawBytes(self, "next_hdr_data", size // 8, "Next header's data")
def createFields(self): yield UInt32(self, "size") self._size = (self['size'].value+4)*8 yield UInt16(self, "unknown[]") yield UInt8(self, "video_count", "Number of video stream entries") yield UInt8(self, "audio_count", "Number of video stream entries") yield UInt8(self, "subtitle_count", "Number of presentation graphics/text subtitle entries") yield UInt8(self, "ig_count", "Number of interactive graphics entries") yield RawBytes(self, "unknown[]", 8) for i in xrange(self['video_count'].value): yield AVCHDMPLS_Stream(self, "video[]") for i in xrange(self['audio_count'].value): yield AVCHDMPLS_Stream(self, "audio[]") for i in xrange(self['subtitle_count'].value): yield AVCHDMPLS_Stream(self, "subtitle[]") for i in xrange(self['ig_count'].value): yield AVCHDMPLS_Stream(self, "ig[]")
def createFields(self): yield Enum(UInt8(self, "code", "Code"), self.code_name) code = self["code"].value if code == self.NOP: return yield UInt8(self, "length", "Option size in bytes") if code == self.MAX_SEGMENT: yield UInt16(self, "max_seg", "Maximum segment size") elif code == self.WINDOW_SCALE: yield UInt8(self, "win_scale", "Window scale") elif code == self.TIMESTAMP: yield UInt32(self, "ts_val", "Timestamp value") yield UInt32(self, "ts_ecr", "Timestamp echo reply") else: size = (self.size - self.current_size) // 8 if size: yield RawBytes(self, "data", size)
def parseProperty(self, property_index, property, name_prefix): ole2 = self.ole2 if not property["size"].value: return if property["size"].value >= ole2["header/threshold"].value: return name = "%s[]" % name_prefix first = None previous = None size = 0 start = property["start"].value chain = ole2.getChain(start, True) blocksize = ole2.ss_size desc_format = "Small blocks %s..%s (%s)" fragment_group = None while True: try: block = chain.next() contiguous = False if not first: first = block contiguous = True if previous and block == (previous+1): contiguous = True if contiguous: previous = block size += blocksize continue except StopIteration: block = None self.seekSBlock(first) desc = desc_format % (first, previous, previous-first+1) size = min(size, property["size"].value*8) if name_prefix in ("summary", "doc_summary"): yield SummaryFieldSet(self, name, desc, size=size) elif name_prefix == "word_doc": yield WordDocumentFieldSet(self, name, desc, size=size) elif property_index == 1: yield CompObj(self, "comp_obj", desc, size=size) else: yield RawBytes(self, name, size//8, desc) if block is None: break first = block previous = block size = ole2.sector_size
def createFields(self): yield UInt64(self, "zip64_end_size", "Size of zip64 end of central directory record") yield ZipVersion(self, "version_made_by", "Version made by") yield ZipVersion(self, "version_needed", "Version needed to extract") yield UInt32(self, "number_disk", "Number of this disk") yield UInt32(self, "number_disk2", "Number of the disk with the start of the central directory") yield UInt64(self, "number_entries", "Total number of entries in the central directory on this disk") yield UInt64(self, "number_entries2", "Total number of entries in the central directory") yield UInt64(self, "size", "Size of the central directory") yield UInt64(self, "offset", "Offset of start of central directory") if 0 < self["zip64_end_size"].value: yield RawBytes(self, "data_sector", self["zip64_end_size"].value, "zip64 extensible data sector")
def createFields(self): yield UInt16(self, "version") # CRC of this structure, excluding first 32 bytes: yield Crc16( self, "crc", self.stream.readBytes(self.absolute_address + (32 * 8), (2112 - 32))) yield RawBytes(self, "reserved", 28) yield BannerIcon(self, "icon_data") for i in range(0, 16): yield NdsColor(self, "palette_color[]") yield String(self, "title_jp", 256, charset="UTF-16-LE", truncate="\0") yield String(self, "title_en", 256, charset="UTF-16-LE", truncate="\0") yield String(self, "title_fr", 256, charset="UTF-16-LE", truncate="\0") yield String(self, "title_de", 256, charset="UTF-16-LE", truncate="\0") yield String(self, "title_it", 256, charset="UTF-16-LE", truncate="\0") yield String(self, "title_es", 256, charset="UTF-16-LE", truncate="\0")
def yieldChunks(self, obj): while len(self.chunks) > 0: chunk = self.chunks.pop() current_pos = obj.current_size // 8 # Check if padding needed size = chunk.offset - current_pos if size > 0: obj.info("Padding of %u bytes needed: curr=%u offset=%u" % \ (size, current_pos, chunk.offset)) yield PaddingBytes(obj, "padding[]", size) current_pos = obj.current_size // 8 # Find resynch point if needed count = 0 old_off = chunk.offset while chunk.offset < current_pos: count += 1 chunk = self.chunks.pop() # Unfortunaly, we also pass the underlying chunks if chunk == None: obj.info("Couldn't resynch: %u object skipped to reach %u" % \ (count, current_pos)) return # Resynch size = chunk.offset - current_pos if size > 0: obj.info("Skipped %u objects to resynch to %u; chunk offset: %u->%u" % \ (count, current_pos, old_off, chunk.offset)) yield RawBytes(obj, "resynch[]", size) # Yield obj.info("Yielding element of size %u at offset %u" % \ (chunk.size, chunk.offset)) field = chunk.cls(obj, chunk.name, chunk.size, *chunk.args) # Not tested, probably wrong: #if chunk.size: field.static_size = 8*chunk.size yield field if hasattr(field, "getSubChunks"): for sub_chunk in field.getSubChunks(): obj.info("Adding sub chunk: position=%u size=%u name='%s'" % \ (sub_chunk.offset, sub_chunk.size, sub_chunk.name)) self.addChunk(sub_chunk)
def markerHeader(self): yield String(self, "signature", 7, "Signature") yield UInt8(self, "ver_extract", "Version needed to extract archive") yield UInt8(self, "ver_created", "Version used to create archive") yield Enum(UInt8(self, "host_os", "OS where the files were compressed"), HOST_OS) yield UInt8(self, "vol_num", "Volume number") yield TimeDateMSDOS32(self, "time", "Date and time (MS DOS format)") yield Bits(self, "reserved", 64, "Reserved size for future extensions") flags = self["flags"] if flags["has_av_string"].value: yield PascalString8(self, "av_string", "AV String") if flags["has_comment"].value: size = filesizeHandler(UInt16(self, "comment_size", "Comment size")) yield size if size.value > 0: yield RawBytes(self, "compressed_comment", size.value, \ "Compressed comment")
def createFields(self): yield Enum( textHandler(UInt16(self, "type", "Chunk type"), hexadecimal), Chunk.type_name) yield UInt32(self, "size", "Chunk size (in bytes)") content_size = self["size"].value - 6 if content_size == 0: return type = self["type"].value if type in Chunk.sub_chunks: while self.current_size < self.size: yield Chunk(self, "chunk[]") else: if type in Chunk.handlers: fields = Chunk.handlers[type](self) for field in fields: yield field else: yield RawBytes(self, "data", content_size)
def createFields(self): yield UInt32(self, "offset", "Offset to data (from file start)") yield UInt16(self, "data_blocks", "Number of data blocks which are in this cabinet") yield Enum(Bits(self, "compr_method", 4, "Compression method"), COMPRESSION_NAME) if self["compr_method"].value in [ 2, 3 ]: # Quantum or LZX use compression level yield PaddingBits(self, "padding[]", 4) yield Bits(self, "compr_level", 5, "Compression level") yield PaddingBits(self, "padding[]", 3) else: yield PaddingBits(self, "padding[]", 12) if self["../flags/has_reserved"].value and self[ "../reserved_folder_size"].value: yield RawBytes(self, "reserved_folder", self["../reserved_folder_size"].value, "Per-folder reserved area")
def parseString(parent): yield UInt32(parent, "length", "Length") length = parent["length"].value if parent.name == "lnotab": bytecode_offset = 0 line_number = parent['../firstlineno'].value for i in range(0, length, 2): bc_off_delta = UInt8(parent, 'bytecode_offset_delta[]') yield bc_off_delta bytecode_offset += bc_off_delta.value bc_off_delta._description = 'Bytecode Offset %i' % bytecode_offset line_number_delta = UInt8(parent, 'line_number_delta[]') yield line_number_delta line_number += line_number_delta.value line_number_delta._description = 'Line Number %i' % line_number elif 0 < length: yield RawBytes(parent, "text", length, "Content") if DISASSEMBLE and parent.name == "compiled_code": disassembleBytecode(parent["text"])
def createFields(self): yield PascalString16(self, "name", "Name", charset="UTF-16-LE", strip="\0") yield Enum(UInt16(self, "type"), self.TYPE_NAME) yield UInt16(self, "value_length") type = self["type"].value size = self["value_length"].value name = "value" if type == 0 and (size % 2) == 0: yield String(self, name, size, charset="UTF-16-LE", strip="\0") elif type in (2, 3): yield UInt32(self, name) elif type == 4: yield UInt64(self, name) else: yield RawBytes(self, name, size)
def createFields(self): #TODO: This structure is normally divided in two parts: # _reiserfs_super_block_v1 # _reiserfs_super_block # It will be divided later to easily support older version of the first part yield UInt32(self, "block_count", "Number of blocks") yield UInt32(self, "free_blocks", "Number of free blocks") yield UInt32(self, "root_block", "Root block number") yield Journal_params(self, "Journal parameters") yield UInt16(self, "blocksize", "Size of a block") yield UInt16(self, "oid_maxsize", "Max size of object id array") yield UInt16(self, "oid_cursize", "Current size of object id array") yield Enum(UInt16(self, "umount_state", "Filesystem umounted or not"), self.UMOUNT_STATE) yield String(self, "magic", 10, "Magic string", strip="\0") #TODO: change the type of s_fs_state in Enum to have more details about this fsck state yield UInt16(self, "fs_state", "Rebuilding phase of fsck ") yield Enum( UInt32(self, "hash_function", "Hash function to sort names in a directory"), self.HASH_FUNCTIONS) yield UInt16(self, "tree_height", "Height of disk tree") yield UInt16( self, "bmap_nr", "Amount of bitmap blocks needed to address each block of file system" ) #TODO: find a good description for this field yield UInt16( self, "version", "Field only reliable on filesystem with non-standard journal") yield UInt16(self, "reserved_for_journal", "Size in blocks of journal area on main device") #TODO: same as above yield UInt32(self, "inode_generation", "No description") #TODO: same as above and should be an enum field yield UInt32(self, "flags", "No description") #TODO: Create a special Type to format this id yield RawBytes(self, "uuid", 16, "Filesystem unique identifier") yield String(self, "label", 16, "Filesystem volume label", strip="\0") yield NullBytes(self, "unused", 88) yield NullBytes(self, "Bytes before end of the block", self["blocksize"].value - 204)
def createFields(self): LONG = Int32 yield UInt32(self, "type", "Record type (always 1)") yield UInt32(self, "size", "Size of the header in bytes") yield RECT32(self, "Bounds", "Inclusive bounds") yield RECT32(self, "Frame", "Inclusive picture frame") yield textHandler( UInt32(self, "signature", "Signature ID (always 0x464D4520)"), hexadecimal) yield UInt16(self, "min_ver", "Minor version") yield UInt16(self, "maj_ver", "Major version") yield UInt32(self, "file_size", "Size of the file in bytes") yield UInt32(self, "NumOfRecords", "Number of records in the metafile") yield UInt16(self, "NumOfHandles", "Number of handles in the handle table") yield NullBytes(self, "reserved", 2) yield UInt32(self, "desc_size", "Size of description in 16-bit words") yield UInt32(self, "desc_ofst", "Offset of description string in metafile") yield UInt32(self, "nb_colors", "Number of color palette entries") yield LONG(self, "width_px", "Width of reference device in pixels") yield LONG(self, "height_px", "Height of reference device in pixels") yield LONG(self, "width_mm", "Width of reference device in millimeters") yield LONG(self, "height_mm", "Height of reference device in millimeters") # Read description (if any) offset = self["desc_ofst"].value current = (self.absolute_address + self.current_size) // 8 size = self["desc_size"].value * 2 if offset == current and size: yield String(self, "description", size, charset="UTF-16-LE", strip="\0 ") # Read padding (if any) size = self["size"].value - self.current_size // 8 if size: yield RawBytes(self, "padding", size)
def createFields(self): yield String(self, "magic", 4, "File signature (MAR1)", charset="ASCII") yield UInt32(self, "index_offset", "Offset to index relative to file start") self.seekByte(self["index_offset"].value, False) yield UInt32(self, "index_size", "size of index in bytes") current_index_size = 0 # bytes while current_index_size < self["index_size"].value: # plus 4 compensates for index_size self.seekByte(self["index_offset"].value + current_index_size + 4, False) entry = IndexEntry(self, "index_entry[]") yield entry current_index_size += entry.size // 8 self.seekByte(entry["offset"].value, False) yield RawBytes(self, "file[]", entry["length"].value)
def createFields(self): yield textHandler(UInt8(self, "signature", "IPTC signature (0x1c)"), hexadecimal) if self["signature"].value != 0x1C: raise ParserError("Wrong IPTC signature") yield textHandler(UInt8(self, "dataset_nb", "Dataset number"), hexadecimal) yield UInt8(self, "tag", "Tag") yield IPTC_Size(self, "size", "Content size") size = self["size"].value if 0 < size: if self.dataset_info: cls = self.dataset_info[2] else: cls = None if cls: yield cls(self, "content") else: yield RawBytes(self, "content", size)
def createFields(self): # Parse header and program headers yield PRCHeader(self, "header", "Header") lens = [] firstOne = True poff = 0 for index in xrange(self["header/num_records"].value): r = ResourceHeader(self, "res_header[]") if firstOne: firstOne = False else: lens.append(r["offset"].value - poff) poff = r["offset"].value yield r lens.append(self.size / 8 - poff) yield UInt16(self, "placeholder", "Place holder bytes") for i in range(len(lens)): yield RawBytes( self, "res[]", lens[i], '"' + self["res_header[" + str(i) + "]/name"].value + "\" Resource")
def createFields(self): yield String(self, "jfif", 5, "JFIF string", charset="ASCII") if self["jfif"].value != "JFIF\0": raise ParserError( "Stream doesn't look like JPEG chunk (wrong JFIF signature)") yield UInt8(self, "ver_maj", "Major version") yield UInt8(self, "ver_min", "Minor version") yield Enum(UInt8(self, "units", "Units"), self.UNIT_NAME) if self["units"].value == 0: yield UInt16(self, "aspect_x", "Aspect ratio (X)") yield UInt16(self, "aspect_y", "Aspect ratio (Y)") else: yield UInt16(self, "x_density", "X density") yield UInt16(self, "y_density", "Y density") yield UInt8(self, "thumb_w", "Thumbnail width") yield UInt8(self, "thumb_h", "Thumbnail height") thumb_size = self["thumb_w"].value * self["thumb_h"].value if thumb_size != 0: yield PaletteRGB(self, "thumb_palette", 256) yield RawBytes(self, "thumb_data", thumb_size, "Thumbnail data")
def createFields(self): frame = None scan = None restart_interval = None restart_offset = 0 while not self.eof: chunk = JpegChunk(self, "chunk[]") yield chunk if chunk["type"].value in JpegChunk.START_OF_FRAME: if chunk["type"].value not in [0xC0, 0xC1]: # SOF0 [Baseline], SOF1 [Extended Sequential] self.warning("Only supporting Baseline & Extended Sequential JPEG images so far!") frame = chunk["content"] if chunk["type"].value == JpegChunk.TAG_SOS: if not frame: self.warning("Missing or invalid SOF marker before SOS!") continue scan = chunk["content"] # hack: scan only the fields seen so far (in _fields): don't use the generator if "restart_interval" in self._fields: restart_interval = self["restart_interval/content/interval"].value else: restart_interval = None yield JpegImageData(self, "image_data[]", frame, scan, restart_interval) elif chunk["type"].value in range(0xD0, 0xD8): restart_offset += 1 yield JpegImageData(self, "image_data[]", frame, scan, restart_interval, restart_offset) # TODO: is it possible to handle piped input? if self._size is None: raise NotImplementedError has_end = False size = (self._size - self.current_size) // 8 if size: if 2 < size \ and self.stream.readBytes(self._size - 16, 2) == "\xff\xd9": has_end = True size -= 2 yield RawBytes(self, "data", size, "JPEG data") if has_end: yield JpegChunk(self, "chunk[]")
def createFields(self): for field in ZipStartCommonFields(self): yield field length = self["filename_length"].value if length: filename = String(self, "filename", length, "Filename", charset=zipGetCharset(self)) yield filename self.filename = filename.value if self["extra_length"].value: yield RawBytes(self, "extra", self["extra_length"].value, "Extra") size = self["compressed_size"].value if size > 0: yield self.data(size) elif self["flags/incomplete"].value: for field in self.resync(): yield field if self["flags/has_descriptor"].value: yield ZipDataDescriptor(self, "data_desc", "Data descriptor")
def __init__(self, parent, name): RawBytes.__init__(self, parent, name, PAGE_SIZE)