def __init__(self, io):
        stream = BytesIO(io.read(self.SIZE))
        self.signature = stream.read(4)
        assert self.signature == b"PML_", "Wrong PML header"
        self.version = read_u32(stream)
        if self.version not in [9]:
            raise NotImplementedError("Not supporting PML version {}".format(self.version))
        self.is_64bit = read_u32(stream)
        self.computer_name = read_utf16(stream, 0x20)
        self.system_root = read_utf16(stream, 0x208)
        self.number_of_events = read_u32(stream)

        stream.seek(8, 1)  # Unknown field
        self.events_offset = read_u64(stream)
        self.events_offsets_array_offset = read_u64(stream)
        self.process_table_offset = read_u64(stream)
        self.strings_table_offset = read_u64(stream)
        self.unknown_table_offset = read_u64(stream)

        stream.seek(12, 1)  # Unknown fields
        self.windows_major_number = read_u32(stream)
        self.windows_minor_number = read_u32(stream)
        self.windows_build_number = read_u32(stream)
        self.windows_build_number_after_decimal_point = read_u32(stream)

        self.service_pack_name = read_utf16(stream, 0x32)

        stream.seek(0xd6, 1)  # Unknown field
        self.number_of_logical_processors = read_u32(stream)
        self.ram_memory_size = read_u64(stream)
        self.header_size = read_u64(stream)
        self.hosts_and_ports_tables_offset = read_u64(stream)
def get_registry_query_or_enum_key_extra_details(metadata, event, extra_detail_io, details_info):
    event.category = "Read"  # RegQueryKey and RegEnumKey is always Read
    key_information_class = RegistryKeyInformationClass(details_info["information_class"])

    if event.operation == RegistryOperation.RegEnumKey.name:
        event.details["Index"] = details_info["index"]  # Only in enum
    elif event.operation == RegistryOperation.RegQueryKey.name:
        event.details["Query"] = key_information_class.name # Only in query

    if not extra_detail_io:
        #  There is no extra details
        event.details["Length"] = details_info["length"]
        return

    if key_information_class == RegistryKeyInformationClass.Name:
        # KEY_NAME_INFORMATION structure
        name_size = read_u32(extra_detail_io)
        event.details["Name"] = read_utf16(extra_detail_io, name_size)
    elif key_information_class == RegistryKeyInformationClass.HandleTags:
        event.details["HandleTags"] = read_u32(extra_detail_io)
    elif key_information_class == RegistryKeyInformationClass.Flags:
        event.details["UserFlags"] = read_u32(extra_detail_io)
    elif key_information_class == RegistryKeyInformationClass.Cached:
        # KEY_CACHED_INFORMATION structure
        event.details["LastWriteTime"] = read_filetime(extra_detail_io)
        event.details["TitleIndex"] = read_u32(extra_detail_io)
        event.details["SubKeys"] = read_u32(extra_detail_io)
        event.details["MaxNameLen"] = read_u32(extra_detail_io)
        event.details["Values"] = read_u32(extra_detail_io)
        event.details["MaxValueNameLen"] = read_u32(extra_detail_io)
        event.details["MaxValueDataLen"] = read_u32(extra_detail_io)
    elif key_information_class == RegistryKeyInformationClass.Basic:
        # KEY_BASIC_INFORMATION structure
        event.details["LastWriteTime"] = read_filetime(extra_detail_io)
        event.details["TitleIndex"] = read_u32(extra_detail_io)
        name_size = read_u32(extra_detail_io)
        event.details["Name"] = read_utf16(extra_detail_io, name_size)
    elif key_information_class == RegistryKeyInformationClass.Full:
        # KEY_FULL_INFORMATION structure
        event.details["LastWriteTime"] = read_filetime(extra_detail_io)
        event.details["TitleIndex"] = read_u32(extra_detail_io)
        event.details["ClassOffset"] = read_u32(extra_detail_io)
        event.details["ClassLength"] = read_u32(extra_detail_io)
        event.details["SubKeys"] = read_u32(extra_detail_io)
        event.details["MaxNameLen"] = read_u32(extra_detail_io)
        event.details["MaxClassLen"] = read_u32(extra_detail_io)
        event.details["Values"] = read_u32(extra_detail_io)
        event.details["MaxValueNameLen"] = read_u32(extra_detail_io)
        event.details["MaxValueDataLen"] = read_u32(extra_detail_io)
    elif key_information_class == RegistryKeyInformationClass.Node:
        # KEY_NODE_INFORMATION structure
        event.details["LastWriteTime"] = read_filetime(extra_detail_io)
        event.details["TitleIndex"] = read_u32(extra_detail_io)
        event.details["ClassOffset"] = read_u32(extra_detail_io)
        event.details["ClassLength"] = read_u32(extra_detail_io)
        name_size = read_u32(extra_detail_io)
        event.details["Name"] = read_utf16(extra_detail_io, name_size)
def get_registry_query_or_enum_value_extra_details(metadata, event, extra_detail_io, details_info):
    event.category = "Read"  # RegQueryValue and RegEnumValue are always Read
    key_value_information_class = RegistryKeyValueInformationClass(details_info["information_class"])

    if event.operation == RegistryOperation.RegEnumValue.name:
        event.details["Index"] = details_info["index"]  # Only in enum

    if not extra_detail_io:
        #  There is no extra details
        event.details["Length"] = details_info["length"]
        return

    extra_detail_io.seek(4, 1)  # Unknown field
    reg_type_name = get_reg_type_name(read_u32(extra_detail_io))

    if key_value_information_class == RegistryKeyValueInformationClass.KeyValueFullInformation:
        offset_to_data = read_u32(extra_detail_io)
        length_value = read_u32(extra_detail_io)
        name_size = read_u32(extra_detail_io)
        event.details["Name"] = read_utf16(extra_detail_io, name_size)
        extra_detail_io.seek(offset_to_data, 0)  # the stream starts at the start of the struct so the seek is good
    elif key_value_information_class == RegistryKeyValueInformationClass.KeyValuePartialInformation:
        length_value = read_u32(extra_detail_io)
    else:
        # Only KeyValuePartialInformation and KeyValueFullInformation have Data property
        event.details["Type"] = reg_type_name  # the Type is still known...
        return

    event.details["Type"] = reg_type_name  # I do this assignment here because "Name" comes before "Type"
    event.details["Length"] = length_value

    if length_value > 0:
        event.details["Data"] = read_registry_data(extra_detail_io, reg_type_name, length_value)
 def __init__(self, io):
     super(HostnamesTable, self).__init__()
     number_of_hostnames = read_u32(io)
     for _ in range(number_of_hostnames):
         ip = io.read(16)
         hostname_len = read_u32(io)
         hostname = read_utf16(io, hostname_len)
         self[ip] = hostname
def read_detail_string(io, string_info):
    """Reads a string in the details that has an info field declared before
    """
    is_ascii, character_count = string_info
    if is_ascii:
        return io.read(character_count).decode("ascii")
    else:
        return read_utf16(io, character_count * 2)
    def __init__(self, io):
        stream = BytesIO(io.read(self.SIZE))
        self.signature = stream.read(4)
        if self.signature != b"PML_":
            raise PMLError(
                "not a Process Monitor backing file (signature missing).")
        self.version = read_u32(stream)
        if self.version not in [9]:
            raise NotImplementedError("Not supporting PML version {}".format(
                self.version))
        self.is_64bit = read_u32(stream)
        self.computer_name = read_utf16(stream, 0x20)
        self.system_root = read_utf16(stream, 0x208)
        self.number_of_events = read_u32(stream)

        stream.seek(8, 1)  # Unknown field
        self.events_offset = read_u64(stream)
        self.events_offsets_array_offset = read_u64(stream)
        self.process_table_offset = read_u64(stream)
        self.strings_table_offset = read_u64(stream)

        # currently not being parsed because I don't know how to show icons in python.
        # Docs of this table's layout are in "docs\PML Format.md"
        self.icon_table_offset = read_u64(stream)

        stream.seek(12, 1)  # Unknown fields
        self.windows_major_number = read_u32(stream)
        self.windows_minor_number = read_u32(stream)
        self.windows_build_number = read_u32(stream)
        self.windows_build_number_after_decimal_point = read_u32(stream)

        self.service_pack_name = read_utf16(stream, 0x32)

        stream.seek(0xd6, 1)  # Unknown field
        self.number_of_logical_processors = read_u32(stream)
        self.ram_memory_size = read_u64(stream)
        self.header_size = read_u64(stream)
        self.hosts_and_ports_tables_offset = read_u64(stream)

        if self.events_offset == 0 or self.events_offsets_array_offset == 0 or self.process_table_offset == 0 or self.strings_table_offset == 0 or self.icon_table_offset == 0:
            raise PMLError(
                "PML was not closed cleanly during capture and is corrupt.")

        if self.header_size != self.SIZE or self.hosts_and_ports_tables_offset == 0:
            raise PMLError("PML is corrupt and cannot be opened.")
 def __init__(self, io):
     super(PortsTable, self).__init__()
     number_of_ports = read_u32(io)
     for _ in range(number_of_ports):
         port_value = read_u16(io)
         is_tcp = bool(read_u16(io))
         port_len = read_u32(io)
         port_name = read_utf16(io, port_len)
         self[(port_value, is_tcp)] = port_name
    def __init__(self, io, total_size):
        super(StringsTable, self).__init__()
        stream = BytesIO(io.read(total_size))
        number_of_strings = read_u32(stream)

        # relative offsets to strings are not essential since they come one after another
        # strings_offsets_array = [read_u32(stream) for _ in range(number_of_strings)]
        stream.seek(number_of_strings * 4, 1)  # jump over the strings offsets array

        strings = [''] * number_of_strings
        for i in range(number_of_strings):
            string_size = read_u32(stream)
            strings[i] = read_utf16(stream, string_size)
        self.extend(strings)
    def __init__(self, io):
        super(StringsTable, self).__init__()
        string_table_start = io.tell()
        number_of_strings = read_u32(io)

        strings_offsets_array = [
            read_u32(io) for _ in range(number_of_strings)
        ]

        strings = [''] * number_of_strings
        for i, offset in enumerate(strings_offsets_array):
            io.seek(string_table_start + offset, 0)
            string_size = read_u32(io)
            strings[i] = read_utf16(io, string_size)
        self.extend(strings)
Example #10
0
def read_registry_data(io, reg_type_name, length=0):
    """Reads registry data (which is present in the Detail column in original Procmon) according to ``reg_type``
    """
    if reg_type_name == RegistryTypes.REG_DWORD.name:
        return read_u32(io)
    elif reg_type_name == RegistryTypes.REG_QWORD.name:
        return read_u64(io)
    elif reg_type_name == RegistryTypes.REG_EXPAND_SZ.name or reg_type_name == RegistryTypes.REG_SZ.name:
        return read_utf16(io)
    elif reg_type_name == RegistryTypes.REG_BINARY.name:
        # Assuming the stream ends at the end of the extra detail, so just read everything
        return io.read(length)
    elif reg_type_name == RegistryTypes.REG_MULTI_SZ.name:
        return read_utf16_multisz(io, length)

    return ''
def get_filesystem_query_directory_details(io, metadata, event, details_io, extra_detail_io):
    event.category = "Read Metadata"
    directory_name_info = read_detail_string_info(io)
    directory_name = read_detail_string(io, directory_name_info)
    if directory_name:
        event.path = event.path + directory_name if event.path[-1] == "\\" else event.path + "\\" + directory_name
        event.details['Filter'] = directory_name

    details_io.seek(0x10, 1)
    if metadata.sizeof_pvoid == 8:
        details_io.seek(4, 1)  # Padding for 64 bit
    details_io.seek(0x4, 1)
    if metadata.sizeof_pvoid == 8:
        details_io.seek(4, 1)  # Padding for 64 bit

    file_information_class = FileInformationClass(read_u32(details_io))
    event.details["FileInformationClass"] = file_information_class.name

    if extra_detail_io and file_information_class in [FileInformationClass.FileDirectoryInformation,
                                                      FileInformationClass.FileFullDirectoryInformation,
                                                      FileInformationClass.FileBothDirectoryInformation,
                                                      FileInformationClass.FileNamesInformation,
                                                      FileInformationClass.FileIdBothDirectoryInformation,
                                                      FileInformationClass.FileIdFullDirectoryInformation]:
        extra_detail_length = len(extra_detail_io.getvalue())
        next_entry_offset = -1  # hack so the first iteration won't exit
        current_entry_offset = 1

        i = 0 if directory_name else -1
        while True:
            i += 1
            if next_entry_offset == 0 or (current_entry_offset + next_entry_offset) > extra_detail_length:
                break  # No more structures

            extra_detail_io.seek(current_entry_offset + next_entry_offset, 0)
            current_entry_offset = extra_detail_io.tell()
            next_entry_offset = read_u32(extra_detail_io)
            file_index = read_u32(extra_detail_io)
            if file_information_class == FileInformationClass.FileNamesInformation:
                # FILE_NAMES_INFORMATION structure
                file_name_length = read_u32(extra_detail_io)
                event.details[str(i)] = read_utf16(extra_detail_io, file_name_length)
                continue
            creation_time = read_filetime(extra_detail_io)
            last_access_time = read_filetime(extra_detail_io)
            last_write_time = read_filetime(extra_detail_io)
            change_time = read_filetime(extra_detail_io)
            end_of_file = read_u64(extra_detail_io)
            allocation_size = read_u64(extra_detail_io)
            file_attributes = read_u32(extra_detail_io)
            file_name_length = read_u32(extra_detail_io)
            if file_information_class == FileInformationClass.FileDirectoryInformation:
                # FILE_DIRECTORY_INFORMATION structure
                event.details[str(i)] = read_utf16(extra_detail_io, file_name_length)
                continue
            ea_size = read_u32(extra_detail_io)
            if file_information_class == FileInformationClass.FileFullDirectoryInformation:
                # FILE_FULL_DIR_INFORMATION structure
                event.details[str(i)] = read_utf16(extra_detail_io, file_name_length)
                continue
            if file_information_class == FileInformationClass.FileIdFullDirectoryInformation:
                # FILE_ID_FULL_DIR_INFORMATION structure
                file_id = read_u64(extra_detail_io)
                event.details[str(i)] = read_utf16(extra_detail_io, file_name_length)
                continue
            short_name_length = read_u8(extra_detail_io)
            extra_detail_io.seek(1, 1)  # Padding
            short_name = extra_detail_io.read(12 * 2)
            if file_information_class == FileInformationClass.FileBothDirectoryInformation:
                # FILE_BOTH_DIR_INFORMATION structure
                event.details[str(i)] = read_utf16(extra_detail_io, file_name_length)
                continue

            # FILE_ID_BOTH_DIR_INFORMATION structure
            extra_detail_io.seek(2, 1)  # Padding
            file_id = read_u64(extra_detail_io)
            event.details[str(i)] = read_utf16(extra_detail_io, file_name_length)
            continue