def createFields(self): yield UInt8(self, "id", "PCX identifier (10)") yield Enum(UInt8(self, "version", "PCX version"), self.version_name) yield Enum(UInt8(self, "compression", "Compression method"), self.compression_name) yield UInt8(self, "bpp", "Bits / pixel") yield UInt16(self, "xmin", "Minimum X") yield UInt16(self, "ymin", "Minimum Y") yield UInt16(self, "xmax", "Width minus one") # value + 1 yield UInt16(self, "ymax", "Height minus one") # value + 1 yield UInt16(self, "horiz_dpi", "Horizontal DPI") yield UInt16(self, "vert_dpi", "Vertical DPI") yield PaletteRGB(self, "palette_4bits", 16, "Palette (4 bits)") yield PaddingBytes(self, "reserved[]", 1) yield UInt8(self, "nb_color_plan", "Number of color plans") yield UInt16(self, "bytes_per_line", "Bytes per line") yield UInt16(self, "color_mode", "Color mode") yield PaddingBytes(self, "reserved[]", 58) if self._size is None: # TODO: is it possible to handle piped input? raise NotImplementedError nb_colors = 256 size = (self._size - self.current_size) // 8 has_palette = self["bpp"].value == 8 if has_palette: size -= nb_colors * 3 yield RawBytes(self, "image_data", size, "Image data") if has_palette: yield PaletteRGB(self, "palette_8bits", nb_colors, "Palette (8 bit)")
def createFields(self): yield String(self, "header", 2, "File header (MZ)", charset="ASCII") yield UInt16(self, "size_mod_512", "File size in bytes modulo 512") yield UInt16(self, "size_div_512", "File size in bytes divide by 512") yield UInt16(self, "reloc_entries", "Number of relocation entries") yield UInt16(self, "code_offset", "Offset to the code in the file (divided by 16)") yield UInt16(self, "needed_memory", "Memory needed to run (divided by 16)") yield UInt16(self, "max_memory", "Maximum memory needed to run (divided by 16)") yield textHandler( UInt32(self, "init_ss_sp", "Initial value of SP:SS registers"), hexadecimal) yield UInt16(self, "checksum", "Checksum") yield textHandler( UInt32(self, "init_cs_ip", "Initial value of CS:IP registers"), hexadecimal) yield UInt16(self, "reloc_offset", "Offset in file to relocation table") yield UInt16(self, "overlay_number", "Overlay number") yield PaddingBytes(self, "reserved[]", 8, "Reserved") yield UInt16(self, "oem_id", "OEM id") yield UInt16(self, "oem_info", "OEM info") yield PaddingBytes(self, "reserved[]", 20, "Reserved") yield UInt32(self, "next_offset", "Offset to next header (PE or NE)")
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 String(self, "signature", 2, "Header (\"BM\")", charset="ASCII") yield UInt32(self, "file_size", "File size (bytes)") yield PaddingBytes(self, "reserved", 4, "Reserved") yield UInt32(self, "data_start", "Data start position") yield BmpHeader(self, "header") # Compute number of color header = self["header"] bpp = header["bpp"].value if 0 < bpp <= 8: if "used_colors" in header and header["used_colors"].value: nb_color = header["used_colors"].value else: nb_color = (1 << bpp) else: nb_color = 0 # Color palette (if any) if nb_color: yield PaletteRGBA(self, "palette", nb_color) # Seek to data start field = self.seekByte(self["data_start"].value) if field: yield field # Image pixels size = min(self["file_size"].value - self["data_start"].value, (self.size - self.current_size) // 8) yield parseImageData(self, "pixels", size, header)
def createPaddingField(parent, nbits, name="padding[]", description=None): if nbits <= 0: raise FieldError("Unable to create padding of %s bits" % nbits) if (nbits % 8) == 0: return PaddingBytes(parent, name, nbits // 8, description) else: return PaddingBits(parent, name, nbits, description)
def createFields(self): while self.current_size < self.size: pos = self.stream.searchBytes('\0\0\1', self.current_size, self.current_size + 1024 * 1024 * 8) # seek forward by at most 1MB if pos is not None: padsize = pos - self.current_size if padsize: yield PaddingBytes(self, "pad[]", padsize // 8) yield VideoChunk(self, "chunk[]")
def createFields(self): padding = 0 position = 0 streamlength = self["../length"].value while position < streamlength * 8: next = ord(self.parent.stream.readBytes(self.absolute_address + self.current_size + position, 1)) if next == 0xff: padding += 1 position += 8 elif padding: yield PaddingBytes(self, "pad[]", padding) padding = None position = 0 elif 0x40 <= next <= 0x7f: yield Bits(self, "scale_marker", 2) # 1 yield Bit(self, "scale") scale = self['scale'].value if scale: scaleval = 1024 else: scaleval = 128 yield textHandler(Bits(self, "size", 13), lambda field: str(field.value * scaleval)) elif 0x00 <= next <= 0x3f: yield Bits(self, "ts_marker", 2) # 0 yield Bit(self, "has_pts") yield Bit(self, "has_dts") if self['has_pts'].value: yield Timestamp(self, "pts") if self['has_dts'].value: yield PaddingBits(self, "pad[]", 4) yield Timestamp(self, "dts") if self.current_size % 8 == 4: yield PaddingBits(self, "pad[]", 4) break elif 0x80 <= next <= 0xbf: # MPEG-2 extension yield PacketElement(self, "pkt") break else: # 0xc0 - 0xfe: unknown break length = self["../length"].value - self.current_size // 8 if length: tag = self['../tag'].value group = self.root.streamgroups[tag] parname = self.parent._name if parname.startswith('audio'): frag = CustomFragment(self, "data", length * 8, MpegAudioFile, group=group) elif parname.startswith('video'): frag = CustomFragment(self, "data", length * 8, VideoStream, group=group) else: frag = CustomFragment(self, "data", length * 8, None, group=group) self.root.streamgroups[tag] = frag.group yield frag
def createFields(self): if False: yield UInt32(self, "width0") yield UInt32(self, "height0") yield PaddingBytes(self, "reserved[]", 7) yield UInt32(self, "width") yield UInt32(self, "height") yield PaddingBytes(self, "reserved[]", 2) yield UInt16(self, "depth") yield Enum(String(self, "codec", 4, charset="ASCII"), video_fourcc_name) yield NullBytes(self, "padding", 20) else: yield UInt32(self, "width") yield UInt32(self, "height") yield PaddingBytes(self, "reserved[]", 1) yield UInt16(self, "format_data_size") if self["format_data_size"].value < 40: raise ParserError("Unknown format data size") yield BitmapInfoHeader(self, "bmp_info", use_fourcc=True)
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 synchronize(self): addr = self.absolute_address start = addr + self.current_size end = min(start + self.MAX_PADDING * 8, addr + self.size) padding = findSynchronizeBits(self, start, end) if padding is None: raise ParserError( "MPEG audio: Unable to find synchronization bits") if padding: return PaddingBytes(self, "padding[]", padding, "Padding before synchronization") else: return None
def createFields(self): yield displayHandler(UInt32(self, "res_space", "Reserved space"), humanFilesize) yield displayHandler(UInt32(self, "used_space", "Used space"), humanFilesize) yield Bits(self, "file_flags", 8, "(=4)") yield textHandler(UInt16(self, "magic"), hexadecimal) yield Bits(self, "flags", 16) yield displayHandler(UInt16(self, "page_size", "Page size in bytes"), humanFilesize) yield String(self, "structure", 16, strip="\0", charset="ASCII") yield NullBytes(self, "zero", 2) yield UInt16(self, "nb_page_splits", "Number of page splits B+ tree has suffered") yield UInt16(self, "root_page", "Page number of B+ tree root page") yield PaddingBytes(self, "one", 2, pattern="\xFF") yield UInt16(self, "nb_page", "Number of B+ tree pages") yield UInt16(self, "nb_level", "Number of levels of B+ tree") yield UInt16(self, "nb_entry", "Number of entries in B+ tree") size = (self.size - self.current_size) // 8 if size: yield PaddingBytes(self, "reserved_space", size)
def createFields(self): while self.current_size < self.size: pos = self.stream.searchBytes('\0\0\1', self.current_size, self.current_size + 1024 * 1024 * 8) # seek forward by at most 1MB if pos is not None: padsize = pos - self.current_size if padsize: yield PaddingBytes(self, "pad[]", padsize // 8) chunk = Chunk(self, "chunk[]") try: # force chunk to be processed, so that CustomFragments are complete chunk['content/data'] except Exception: pass yield chunk
def createFields(self): yield UInt32(self, "root_block", "The block number of the root node of the B-tree") yield UInt32( self, "tree_levels", "The number of levels of internal nodes (tree height minus one)") yield UInt32(self, "num_records", "The number of records in the tree") yield UInt32( self, "num_nodes", "The number of nodes in the tree (tree nodes, not including this header block)" ) yield UInt32(self, "unknown", "Always 0x1000, probably the tree node page size") if self.current_size < self.size: yield PaddingBytes(self, "slack", (self.size - self.current_size) // 8, description="slack space")
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 is 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 createFields(self): yield String(self, "name", 8, charset="ASCII", strip="\0 ") yield filesizeHandler(UInt32(self, "mem_size", "Size in memory")) yield textHandler(UInt32(self, "rva", "RVA (location) in memory"), hexadecimal) yield filesizeHandler( UInt32(self, "phys_size", "Physical size (on disk)")) yield filesizeHandler( UInt32(self, "phys_off", "Physical location (on disk)")) yield PaddingBytes(self, "reserved", 12) # 0x0000000# yield NullBits(self, "reserved[]", 4) # 0x000000#0 yield NullBits(self, "reserved[]", 1) yield Bit(self, "has_code", "Contains code") yield Bit(self, "has_init_data", "Contains initialized data") yield Bit(self, "has_uninit_data", "Contains uninitialized data") # 0x00000#00 yield NullBits(self, "reserved[]", 1) yield Bit(self, "has_comment", "Contains comments?") yield NullBits(self, "reserved[]", 1) yield Bit(self, "remove", "Contents will not become part of image") # 0x0000#000 yield Bit(self, "has_comdata", "Contains comdat?") yield NullBits(self, "reserved[]", 1) yield Bit( self, "no_defer_spec_exc", "Reset speculative exceptions handling bits in the TLB entries") yield Bit(self, "gp_rel", "Content can be accessed relative to GP") # 0x000#0000 yield NullBits(self, "reserved[]", 4) # 0x00#00000 yield NullBits(self, "reserved[]", 4) # 0x0#000000 yield Bit(self, "ext_reloc", "Contains extended relocations?") yield Bit(self, "discarded", "Can be discarded?") yield Bit(self, "is_not_cached", "Is not cachable?") yield Bit(self, "is_not_paged", "Is not pageable?") # 0x#0000000 yield Bit(self, "is_shareable", "Is shareable?") yield Bit(self, "is_executable", "Is executable?") yield Bit(self, "is_readable", "Is readable?") yield Bit(self, "is_writable", "Is writable?")
def createFields(self): if self.stream.readBits(self.absolute_address, 2, self.endian) == 1: # MPEG version 2 yield Bits(self, "sync[]", 2) yield SCRExt(self, "scr") yield Bits(self, "mux_rate", 22) yield Bits(self, "sync[]", 2) yield PaddingBits(self, "reserved", 5, pattern=1) yield Bits(self, "stuffing_length", 3) count = self["stuffing_length"].value if count: yield PaddingBytes(self, "stuffing", count, pattern="\xff") else: # MPEG version 1 yield Bits(self, "sync[]", 4) yield Timestamp(self, "scr") yield Bit(self, "sync[]") yield Bits(self, "mux_rate", 22) yield Bit(self, "sync[]")
def getHeaderEndFields(self): instr = self["num_instruments"].value patterns = self["num_patterns"].value # File pointers if instr > 0: yield GenericVector(self, "instr_pptr", instr, UInt16, "offset") if patterns > 0: yield GenericVector(self, "pattern_pptr", patterns, UInt16, "offset") # S3M 3.20 extension if self["creation_version_major"].value >= 3 \ and self["creation_version_minor"].value >= 0x20 \ and self["panning_info"].value == 252: yield GenericVector(self, "channel_panning", 32, ChannelPanning, "channel") # Padding required for 16B alignment size = self._size - self.current_size if size > 0: yield PaddingBytes(self, "padding", size // 8)
def createFields(self): yield UInt32(self, "last_block") yield UInt32(self, "count") if self['last_block'].value != 0: for i in xrange(self['count'].value): block = UInt32(self, "child_block[]") yield block link = Link(self, "child_link[]") link.createValue = self.linkValue(block) yield link yield DSRecord(self, "record[]") link = Link(self, "child_link[]") link.createValue = self.linkValue(self['last_block']) yield link else: for i in xrange(self['count'].value): yield DSRecord(self, "record[]") if self.current_size < self.size: yield PaddingBytes(self, "slack", (self.size - self.current_size) // 8, description="slack space")
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): for field in self.createUnpaddedFields(): yield field size = (self._size - self.current_size) // 8 if size > 0: yield PaddingBytes(self, "padding", size)
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 UInt8(self, "red", "Red") yield UInt8(self, "green", "Green") yield UInt8(self, "blue", "Blue") yield PaddingBytes(self, "pad", 1, "Padding (must be 0)")
def createFields(self): yield GUID(self, "file_id") yield UInt64(self, "packet_count") yield PaddingBytes(self, "reserved", 2) size = (self.size - self.current_size) // 8 yield RawBytes(self, "data", size)
def createFields(self): yield UInt32(self, "obj_count") yield PaddingBytes(self, "reserved[]", 2) for index in xrange(self["obj_count"].value): yield Object(self, "object[]")
def createFields(self): # Parse directories depth = 0 subdir = Directory(self, "root") yield subdir subdirs = [subdir] alldirs = [subdir] while subdirs: depth += 1 if MAX_DEPTH < depth: self.error( "EXE resource: depth too high (%s), stop parsing directories" % depth) break newsubdirs = [] for index, subdir in enumerate(subdirs): name = "directory[%u][%u][]" % (depth, index) try: for field in self.parseSub(subdir, name, depth): if field.__class__ == Directory: newsubdirs.append(field) yield field except Exception as err: self.error("Unable to create directory %s: %s" % (name, err)) subdirs = newsubdirs alldirs.extend(subdirs) # Create resource list resources = [] for directory in alldirs: for index in directory.array("index"): if not index["is_subdir"].value: resources.append(index) # Parse entries entries = [] for resource in resources: offset = resource["offset"].value if offset is None: continue self.seekByte(offset) entry = Entry(self, "entry[]", inode=resource) yield entry entries.append(entry) entries.sort(key=lambda entry: entry["rva"].value) # Parse resource content for entry in entries: try: offset = self.section.rva2file(entry["rva"].value) padding = self.seekByte(offset, relative=False) if padding: yield padding yield ResourceContent(self, "content[]", entry) except Exception as err: self.warning("Error when parsing entry %s: %s" % (entry.path, err)) size = (self.size - self.current_size) // 8 if size: yield PaddingBytes(self, "padding_end", size)
def createFields(self): yield UInt8(self, "frame") yield UInt8(self, "second") yield UInt8(self, "minute") yield PaddingBytes(self, "notused", 1)
def createFields(self): yield PaddingBytes(self, "data", self["../length"].value)