def createFields(self): # Read chunk header yield Bytes(self, "signature", 3, r"Property signature (\x8E\xAD\xE8)") if self["signature"].value != "\x8E\xAD\xE8": raise ParserError("Invalid property signature") yield UInt8(self, "version", "Signature version") yield NullBytes(self, "reserved", 4, "Reserved") yield UInt32(self, "count", "Count") yield UInt32(self, "size", "Size") # Read item header items = [] for i in range(0, self["count"].value): item = ItemHeader(self, "item[]") yield item items.append(item) # Sort items by their offset items.sort(key=lambda field: field["offset"].value) # Read item content start = self.current_size // 8 for item in items: offset = item["offset"].value diff = offset - (self.current_size // 8 - start) if 0 < diff: yield NullBytes(self, "padding[]", diff) yield ItemContent(self, "content[]", item) size = start + self["size"].value - self.current_size // 8 if 0 < size: yield NullBytes(self, "padding[]", size)
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 String(self, "header_id", 4, "DataBase Header Markup (\"mhbd\")", charset="ISO-8859-1") yield UInt32(self, "header_length", "Header Length") yield UInt32(self, "entry_length", "Entry Length") yield UInt32(self, "unknown[]") yield UInt32(self, "version_number", "Version Number") yield UInt32(self, "child_number", "Number of Children") yield UInt64(self, "id", "ID for this database") yield UInt16(self, "unknown[]") yield UInt32(self, "unknown[]") yield UInt64(self, "unknown[]") yield UInt16(self, "unknown[]") yield UInt16(self, "hashing_scheme[]", "Algorithm used to calculate the database hash") yield NullBytes(self, "unknown[]", 20) yield String(self, "language_id", 2, "Language ID") yield UInt64(self, "persistent_id", "Library Persistent ID") yield UInt32(self, "unknown[]") yield UInt32(self, "unknown[]") yield RawBytes(self, "hash[]", 20) yield Int32(self, "timezone_offset[]", "Timezone offset in seconds") yield UInt16(self, "unknown[]") yield RawBytes(self, "iphone_hash[]", 45) size = self["header_length"].value - self.current_size / 8 if size > 0: yield NullBytes(self, "padding", size) for i in xrange(self["child_number"].value): yield DataSet(self, "dataset[]") padding = self.seekByte(self["entry_length"].value, "entry padding") if padding: yield padding
def parseVideoHeader(parent): yield NullBytes(parent, "padding[]", 2) yield String(parent, "fourcc", 4) yield UInt32(parent, "size") yield textHandler(UInt64(parent, "time_unit", "Frame duration"), formatTimeUnit) yield UInt64(parent, "sample_per_unit") yield UInt32(parent, "default_len") yield UInt32(parent, "buffer_size") yield UInt16(parent, "bits_per_sample") yield NullBytes(parent, "padding[]", 2) yield UInt32(parent, "width") yield UInt32(parent, "height") yield NullBytes(parent, "padding[]", 4)
def createFields(self): yield IFDTag(self, "tag", "Tag") yield Enum(UInt16(self, "type", "Type"), self.TYPE_NAME) self.value_cls = self.ENTRY_FORMAT.get(self['type'].value, Bytes) if issubclass(self.value_cls, Bytes): self.value_size = 8 else: self.value_size = self.value_cls.static_size yield UInt32(self, "count", "Count") count = self['count'].value totalsize = self.value_size * count if count == 0: yield NullBytes(self, "padding", 4) elif totalsize <= 32: name = "value" if issubclass(self.value_cls, Bytes): yield self.value_cls(self, name, count) elif count == 1: yield self.value_cls(self, name) else: yield ValueArray(self, name, self.value_cls, count) if totalsize < 32: yield NullBits(self, "padding", 32 - totalsize) else: yield UInt32(self, "offset", "Value offset")
def parseAviHeader(self): yield UInt32(self, "microsec_per_frame", "Microsecond per frame") yield UInt32(self, "max_byte_per_sec", "Maximum byte per second") yield NullBytes(self, "reserved", 4) # Flags yield NullBits(self, "reserved[]", 4) yield Bit(self, "has_index") yield Bit(self, "must_use_index") yield NullBits(self, "reserved[]", 2) yield Bit(self, "is_interleaved") yield NullBits(self, "reserved[]", 2) yield Bit(self, "trust_cktype") yield NullBits(self, "reserved[]", 4) yield Bit(self, "was_capture_file") yield Bit(self, "is_copyrighted") yield NullBits(self, "reserved[]", 14) yield UInt32(self, "total_frame", "Total number of frames in the video") yield UInt32(self, "init_frame", "Initial frame (used in interleaved video)") yield UInt32(self, "nb_stream", "Number of streams") yield UInt32(self, "sug_buf_size", "Suggested buffer size") yield UInt32(self, "width", "Width in pixel") yield UInt32(self, "height", "Height in pixel") yield UInt32(self, "scale") yield UInt32(self, "rate") yield UInt32(self, "start") yield UInt32(self, "length")
def createFields(self): yield UInt16(self, "left", "Left") yield UInt16(self, "top", "Top") yield UInt16(self, "width", "Width") yield UInt16(self, "height", "Height") yield Bits(self, "size_local_map", 3, "log2(size of local map) minus one") yield NullBits(self, "reserved", 2) yield Bit(self, "sort_flag", "Is the local map sorted by decreasing importance?") yield Bit(self, "interlaced", "Interlaced?") yield Bit(self, "has_local_map", "Use local color map?") if self["has_local_map"].value: nb_color = 1 << (1 + self["size_local_map"].value) yield PaletteRGB(self, "local_map", nb_color, "Local color map") yield UInt8(self, "lzw_min_code_size", "LZW Minimum Code Size") group = None while True: size = UInt8(self, "image_block_size[]") if size.value == 0: break yield size block = CustomFragment(self, "image_block[]", size.value * 8, GifImageBlock, "GIF Image Block", group) if group is None: block.group.args["startbits"] = self["lzw_min_code_size"].value group = block.group yield block yield NullBytes(self, "terminator", 1, "Terminator (0)")
def createFields(self): yield NullBytes(self, "options", 4) yield TimestampUnix32(self, "creation_date") yield UInt16(self, "maj_ver", "Major version") yield UInt16(self, "min_ver", "Minor version") yield UInt16(self, "nb_name", "Number of named entries") yield UInt16(self, "nb_index", "Number of indexed entries")
def createFields(self): yield String(self, "signature", 4, "PSD signature (8BPS)", charset="ASCII") yield UInt16(self, "version") yield NullBytes(self, "reserved[]", 6) yield UInt16(self, "nb_channels") yield UInt32(self, "width") yield UInt32(self, "height") yield UInt16(self, "depth") yield Enum(UInt16(self, "color_mode"), self.COLOR_MODE) # Mode data yield UInt32(self, "mode_data_size") size = self["mode_data_size"].value if size: yield RawBytes(self, "mode_data", size) # Resources yield Config(self, "config") # Reserved yield UInt32(self, "reserved_data_size") size = self["reserved_data_size"].value if size: yield RawBytes(self, "reserved_data", size) yield Enum(UInt16(self, "compression"), self.COMPRESSION_NAME) size = (self.size - self.current_size) // 8 if size: yield RawBytes(self, "end", size)
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 createNullField(parent, nbits, name="padding[]", description=None): if nbits <= 0: raise FieldError("Unable to create null padding of %s bits" % nbits) if (nbits % 8) == 0: return NullBytes(parent, name, nbits // 8, description) else: return NullBits(parent, name, nbits, description)
def createFields(self): yield NullBytes(self, "zero", 1) yield textHandler( String(self, "length", self._size // 8 - 1, "Length in ms", charset="ASCII"), self.computeLength)
def createFields(self): while not self.eof: field = FileEntry(self, "file[]") if field.isEmpty(): yield NullBytes(self, "terminator", 512) break yield field if self.current_size < self._size: yield self.seekBit(self._size, "end")
def createFields(self): yield UInt32(self, "version") yield UInt8(self, "has_realm") yield PascalStringWin32(self, "writer_name", charset="UTF-16-BE") yield PascalStringWin32(self, "reader_name", charset="UTF-16-BE") yield UInt32(self, "file_version") size = (self.size - self.current_size) // 8 if size: yield NullBytes(self, "padding", size)
def createFields(self): yield textHandler( UInt32(self, "signature", "Placeable Metafiles signature (0x9AC6CDD7)"), hexadecimal) yield UInt16(self, "handle") yield RECT16(self, "rect") yield UInt16(self, "inch") yield NullBytes(self, "reserved", 4) yield textHandler(UInt16(self, "checksum"), hexadecimal)
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): yield NullBytes(self, "unused", 6) yield UInt8(self, "offsetIntSize", "Size (in bytes) of offsets in the offset table") yield UInt8(self, "objectRefSize", "Size (in bytes) of object numbers in object references") yield UInt64(self, "numObjects", "Number of objects in this file") yield UInt64(self, "topObject", "Top-level object reference") yield UInt64(self, "offsetTableOffset", "File offset to the offset table")
def parseNames(self): # Read header yield UInt16(self, "format") if self["format"].value != 0: raise ParserError("TTF (names): Invalid format (%u)" % self["format"].value) yield UInt16(self, "count") yield UInt16(self, "offset") if MAX_NAME_COUNT < self["count"].value: raise ParserError("Invalid number of names (%s)" % self["count"].value) # Read name index entries = [] for index in xrange(self["count"].value): entry = NameHeader(self, "header[]") yield entry entries.append(entry) # Sort names by their offset entries.sort(key=lambda field: field["offset"].value) # Read name value last = None for entry in entries: # Skip duplicates values new = (entry["offset"].value, entry["length"].value) if last and last == new: self.warning("Skip duplicate %s %s" % (entry.name, new)) continue last = (entry["offset"].value, entry["length"].value) # Skip negative offset offset = entry["offset"].value + self["offset"].value if offset < self.current_size // 8: self.warning("Skip value %s (negative offset)" % entry.name) continue # Add padding if any padding = self.seekByte(offset, relative=True, null=True) if padding: yield padding # Read value size = entry["length"].value if size: yield String(self, "value[]", size, entry.description, charset=entry.getCharset()) padding = (self.size - self.current_size) // 8 if padding: yield NullBytes(self, "padding_end", padding)
def createFields(self): addr = self.absolute_address while True: # Check empty note byte = self.stream.readBits(addr, 8, self.endian) if not byte: yield NullBytes(self, "terminator", 1) return note = self.NOTE(self, "note[]") yield note addr += note.size
def createFields(self): yield String(self, "type", 4, "Signature (FORM)", charset="ASCII") yield filesizeHandler(UInt32(self, "size")) size = self["size"].value if size: if self._parser: for field in self._parser(self): yield field if size % 2: yield NullBytes(self, "padding", 1) else: yield RawBytes(self, "data", size)
def createFields(self): yield UInt8(self, "tag") yield UInt24(self, "size", "Content size") yield UInt24(self, "timestamp", "Timestamp in millisecond") yield NullBytes(self, "reserved", 4) size = self["size"].value if size: if self.parser: for field in self.parser(self, size): yield field else: yield RawBytes(self, "content", size)
def createFields(self): yield Bytes(self, "signature", 2, "New executable signature (NE)") yield UInt8(self, "link_ver", "Linker version number") yield UInt8(self, "link_rev", "Linker revision number") yield UInt16(self, "entry_table_ofst", "Offset to the entry table") yield UInt16(self, "entry_table_size", "Length (in bytes) of the entry table") yield PaddingBytes(self, "reserved[]", 4) yield Bit(self, "is_dll", "Is a dynamic-link library (DLL)?") yield Bit(self, "is_win_app", "Is a Windows application?") yield PaddingBits(self, "reserved[]", 9) yield Bit(self, "first_seg_code", "First segment contains code that loads the application?") yield NullBits(self, "reserved[]", 1) yield Bit(self, "link_error", "Load even if linker detects errors?") yield NullBits(self, "reserved[]", 1) yield Bit(self, "is_lib", "Is a library module?") yield UInt16(self, "auto_data_seg", "Automatic data segment number") yield filesizeHandler(UInt16(self, "local_heap_size", "Initial size (in bytes) of the local heap")) yield filesizeHandler(UInt16(self, "stack_size", "Initial size (in bytes) of the stack")) yield textHandler(UInt32(self, "cs_ip", "Value of CS:IP"), hexadecimal) yield textHandler(UInt32(self, "ss_sp", "Value of SS:SP"), hexadecimal) yield UInt16(self, "nb_entry_seg_tab", "Number of entries in the segment table") yield UInt16(self, "nb_entry_modref_tab", "Number of entries in the module-reference table") yield filesizeHandler(UInt16(self, "size_nonres_name_tab", "Number of bytes in the nonresident-name table")) yield UInt16(self, "seg_tab_ofs", "Segment table offset") yield UInt16(self, "rsrc_ofs", "Resource offset") yield UInt16(self, "res_name_tab_ofs", "Resident-name table offset") yield UInt16(self, "mod_ref_tab_ofs", "Module-reference table offset") yield UInt16(self, "import_tab_ofs", "Imported-name table offset") yield UInt32(self, "non_res_name_tab_ofs", "Nonresident-name table offset") yield UInt16(self, "nb_mov_ent_pt", "Number of movable entry points") yield UInt16(self, "log2_sector_size", "Log2 of the segment sector size") yield UInt16(self, "nb_rsrc_seg", "Number of resource segments") yield Bit(self, "unknown_os_format", "Operating system format is unknown") yield PaddingBits(self, "reserved[]", 1) yield Bit(self, "os_windows", "Operating system is Microsoft Windows") yield NullBits(self, "reserved[]", 6) yield Bit(self, "is_win20_prot", "Is Windows 2.x application running in version 3.x protected mode") yield Bit(self, "is_win20_font", "Is Windows 2.x application supporting proportional fonts") yield Bit(self, "fast_load", "Contains a fast-load area?") yield NullBits(self, "reserved[]", 4) yield UInt16(self, "fastload_ofs", "Fast-load area offset (in sector)") yield UInt16(self, "fastload_size", "Fast-load area length (in sector)") yield NullBytes(self, "reserved[]", 2) yield textHandler(UInt16(self, "win_version", "Expected Windows version number"), hexadecimal)
def createFields(self): yield UInt32(self, "num_spaces", "Total number of entries, including blank entries") nobj = self['/num_objects'].value nspace = self['num_spaces'].value for i in xrange(nobj + 1): yield BomTrailerEntry(self, "entry[]") yield NullBytes(self, "blank_entries", (nspace - nobj - 1) * (BomTrailerEntry.static_size / 8)) yield UInt32(self, "num_trail") ntrail = self['num_trail'].value for i in xrange(ntrail): yield BomTrailerEntry(self, "trail[]")
def parseGraphicControl(parent): yield UInt8(parent, "size", "Block size (4)") yield Bit(parent, "has_transp", "Has transparency") yield Bit(parent, "user_input", "User input") yield Enum(Bits(parent, "disposal_method", 3), DISPOSAL_METHOD) yield NullBits(parent, "reserved[]", 3) if parent["size"].value != 4: raise ParserError("Invalid graphic control size") yield displayHandler(UInt16(parent, "delay", "Delay time in millisecond"), humanDuration) yield UInt8(parent, "transp", "Transparent color index") yield NullBytes(parent, "terminator", 1, "Terminator (0)")
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, "signature", "PE optional header signature (0x010b)") # TODO: Support PE32+ (signature=0x020b) if self["signature"].value != 0x010b: raise ParserError("Invalid PE optional header signature") yield UInt8(self, "maj_lnk_ver", "Major linker version") yield UInt8(self, "min_lnk_ver", "Minor linker version") yield filesizeHandler(UInt32(self, "size_code", "Size of code")) yield filesizeHandler( UInt32(self, "size_init_data", "Size of initialized data")) yield filesizeHandler( UInt32(self, "size_uninit_data", "Size of uninitialized data")) yield textHandler( UInt32(self, "entry_point", "Address (RVA) of the code entry point"), hexadecimal) yield textHandler(UInt32(self, "base_code", "Base (RVA) of code"), hexadecimal) yield textHandler(UInt32(self, "base_data", "Base (RVA) of data"), hexadecimal) yield textHandler(UInt32(self, "image_base", "Image base (RVA)"), hexadecimal) yield filesizeHandler(UInt32(self, "sect_align", "Section alignment")) yield filesizeHandler(UInt32(self, "file_align", "File alignment")) yield UInt16(self, "maj_os_ver", "Major OS version") yield UInt16(self, "min_os_ver", "Minor OS version") yield UInt16(self, "maj_img_ver", "Major image version") yield UInt16(self, "min_img_ver", "Minor image version") yield UInt16(self, "maj_subsys_ver", "Major subsystem version") yield UInt16(self, "min_subsys_ver", "Minor subsystem version") yield NullBytes(self, "reserved", 4) yield filesizeHandler(UInt32(self, "size_img", "Size of image")) yield filesizeHandler(UInt32(self, "size_hdr", "Size of headers")) yield textHandler(UInt32(self, "checksum"), hexadecimal) yield Enum(UInt16(self, "subsystem"), self.SUBSYSTEM_NAME) yield UInt16(self, "dll_flags") yield filesizeHandler(UInt32(self, "size_stack_reserve")) yield filesizeHandler(UInt32(self, "size_stack_commit")) yield filesizeHandler(UInt32(self, "size_heap_reserve")) yield filesizeHandler(UInt32(self, "size_heap_commit")) yield UInt32(self, "loader_flags") yield UInt32(self, "nb_directory", "Number of RVA and sizes") for index in xrange(self["nb_directory"].value): try: name = self.DIRECTORY_NAME[index] except KeyError: name = "data_dir[%u]" % index yield DataDirectory(self, name)
def parseApplicationExtension(parent): yield PascalString8(parent, "app_name", "Application name") while True: size = UInt8(parent, "size[]") if size.value == 0: break yield size if parent["app_name"].value == "NETSCAPE2.0" and size.value == 3: yield Enum(UInt8(parent, "netscape_code"), NETSCAPE_CODE) if parent["netscape_code"].value == 1: yield UInt16(parent, "loop_count") else: yield RawBytes(parent, "raw[]", 2) else: yield RawBytes(parent, "raw[]", size.value) yield NullBytes(parent, "terminator", 1, "Terminator (0)")
def createFields(self): yield Bit(self, "last_metadata_block", "True if this is the last metadata block") yield Enum(Bits(self, "block_type", 7, "Metadata block header type"), self.BLOCK_TYPE_DESC) yield UInt24(self, "metadata_length", "Length of following metadata in bytes (doesn't include this header)") block_type = self["block_type"].value size = self["metadata_length"].value if not size: return try: handler = self.BLOCK_TYPES[block_type][2] except KeyError: handler = None if handler: yield handler(self, "content", size=size * 8) elif self["block_type"].value == 1: yield NullBytes(self, "padding", size) else: yield RawBytes(self, "rawdata", size)
def createFields(self): yield PropertiesFormat(self, "format") yield UInt32(self, "count") offsets = [] for index in xrange(self["count"].value): offset = UInt32(self, "offset[]") yield offset offsets.append(offset.value) yield UInt32(self, "total_str_length") offsets.sort() offset0 = self.current_size // 8 for offset in offsets: padding = self.seekByte(offset0 + offset) if padding: yield padding yield CString(self, "name[]") padding = (self.size - self.current_size) // 8 if padding: yield NullBytes(self, "end_padding", padding)
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)