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 get_filesystem_read_write_file_details(io, metadata, event, details_io, extra_detail_io):
    event.category = "Read" if event.operation == "ReadFile" else "Write"
    details_io.seek(0x4, 1)
    io_flags_and_priority = read_u32(details_io)
    io_flags = io_flags_and_priority & 0xe000ff
    priority = (io_flags_and_priority >> 0x11) & 7
    details_io.seek(0x4, 1)
    length = read_u32(details_io)
    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
    offset = read_s64(details_io)

    event.details["Offset"] = offset
    if extra_detail_io:
        length = read_u32(extra_detail_io)
    event.details["Length"] = length

    if io_flags != 0:
        event.details["I/O Flags"] = get_filesysyem_io_flags(io_flags)

    if priority != 0:
        event.details["Priority"] = FilesystemPriority.get(priority, "0x{:x}".format(priority))
def get_process_started_details(io, metadata, event, extra_detail_io):
    event.details["Parent PID"] = read_u32(io)
    command_line_info = read_detail_string_info(io)
    current_directory_info = read_detail_string_info(io)
    environment_character_count = read_u32(io)
    event.details["Command line"] = read_detail_string(io, command_line_info)
    event.details["Current directory"] = read_detail_string(io, current_directory_info)
    event.details["Environment"] = read_utf16_multisz(io, environment_character_count * 2)
예제 #4
0
 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
예제 #5
0
 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 get_filesystem_ioctl_details(io, metadata, event, details_io, extra_detail_io):
    details_io.seek(0x8, 1)
    write_length = read_u32(details_io)
    read_length = read_u32(details_io)
    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

    ioctl = read_u32(details_io)
    event.details["Control"] = get_ioctl_name(ioctl)
    if event.details["Control"] in ["FSCTL_OFFLOAD_READ", "FSCTL_GET_REPARSE_POINT", "FSCTL_READ_RAW_ENCRYPTED"]:
        event.category = "Read"
    elif event.details["Control"] in ["FSCTL_OFFLOAD_WRITE", "FSCTL_MOVE_FILE", "FSCTL_DELETE_REPARSE_POINT",
                                      "FSCTL_WRITE_RAW_ENCRYPTED", "FSCTL_PIPE_TRANSCEIVE",
                                      "FSCTL_PIPE_INTERNAL_TRANSCEIVE"]:
        event.category = "Write"
    elif event.details["Control"] in ["FSCTL_SET_COMPRESSION", "FSCTL_WRITE_PROPERTY_DATA", "FSCTL_SET_OBJECT_ID",
                                      "FSCTL_DELETE_OBJECT_ID", "FSCTL_SET_REPARSE_POINT", "FSCTL_SET_SPARSE",
                                      "FSCTL_SET_ENCRYPTION", "FSCTL_CREATE_USN_JOURNAL",
                                      "FSCTL_WRITE_USN_CLOSE_RECORD", "FSCTL_EXTEND_VOLUME",
                                      "FSCTL_DELETE_USN_JOURNAL"]:
        event.category = "Write Metadata"
    elif event.details["Control"] in ["FSCTL_QUERY_RETRIEVAL_POINTERS", "FSCTL_GET_COMPRESSION",
                                      "FSCTL_QUERY_FAT_BPB", "FSCTL_QUERY_FAT_BPB",
                                      "FSCTL_FILESYSTEM_GET_STATISTICS", "FSCTL_GET_NTFS_VOLUME_DATA",
                                      "FSCTL_GET_NTFS_FILE_RECORD", "FSCTL_GET_VOLUME_BITMAP",
                                      "FSCTL_GET_RETRIEVAL_POINTERS", "FSCTL_IS_VOLUME_DIRTY",
                                      "FSCTL_READ_PROPERTY_DATA", "FSCTL_FIND_FILES_BY_SID", "FSCTL_GET_OBJECT_ID",
                                      "FSCTL_READ_USN_JOURNAL", "FSCTL_SET_OBJECT_ID_EXTENDED",
                                      "FSCTL_CREATE_OR_GET_OBJECT_ID", "FSCTL_READ_FILE_USN_DATA",
                                      "FSCTL_QUERY_USN_JOURNAL"]:
        event.category = "Read Metadata"

    if event.operation == "FileSystemControl":
        if event.details["Control"] == "FSCTL_PIPE_INTERNAL_WRITE":
            event.details["Length"] = write_length
        elif event.details["Control"] == "FSCTL_OFFLOAD_READ":
            details_io.seek(0x8, 1)
            event.details["Offset"] = read_s64(io)
            event.details["Length"] = read_u64(io)
        elif event.details["Control"] == "FSCTL_OFFLOAD_WRITE":
            event.details["Offset"] = read_s64(io)
            event.details["Length"] = read_u64(io)
        elif event.details["Control"] == "FSCTL_PIPE_INTERNAL_READ":
            event.details["Length"] = read_length
        elif event.details["Control"] in ["FSCTL_PIPE_TRANSCEIVE", "FSCTL_PIPE_INTERNAL_TRANSCEIVE"]:
            event.details["WriteLength"] = write_length
            event.details["ReadLength"] = read_length
예제 #7
0
    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 get_registry_set_info_key_extra_details(metadata, event, extra_detail_io, details_info):
    event.category = "Write Metadata"
    event.details["KeySetInformationClass"] = RegistryKeySetInformationClass.get(
        details_info["key_set_information_class"],
        "<Unknown: {}>".format(details_info["key_set_information_class"])
    )
    event.details["Length"] = details_info["length"]
    if details_info["length"] > 0:
        if event.details["KeySetInformationClass"] == "KeyWriteTimeInformation":
            event.details["LastWriteTime"] = read_filetime(extra_detail_io)
        elif event.details["KeySetInformationClass"] == "KeyWow64FlagsInformation":
            event.details["Wow64Flags"] = read_u32(extra_detail_io)
        elif event.details["KeySetInformationClass"] == "KeyWriteTimeInformation":
            event.details["HandleTags"] = read_u32(extra_detail_io)
예제 #9
0
    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)
예제 #10
0
    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)
def get_filesystem_notify_change_directory_details(io, metadata, event, details_io, extra_detail_io):
    event.category = "Read Metadata"

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

    event.details["Filter"] = get_filesysyem_notify_change_flags(read_u32(details_io))
예제 #12
0
 def __init__(self, io, total_size, number_of_events):
     super(EventOffsetsArray, self).__init__()
     stream = BytesIO(io.read(total_size))
     offsets = [0] * number_of_events
     for i in range(number_of_events):
         offsets[i] = read_u32(stream)
         _ = read_u8(stream)  # Unknown flags
     self.extend(offsets)
def get_filesystem_create_file_details(io, metadata, event, details_io, extra_detail_io):
    event.details["Desired Access"] = get_filesystem_access_mask_string(read_u32(io))
    impersonating_sid_length = read_u8(io)
    io.seek(0x3, 1)  # padding

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

    disposition_and_options = read_u32(details_io)
    disposition = disposition_and_options >> 0x18
    options = disposition_and_options & 0xffffff
    if metadata.sizeof_pvoid == 8:
        details_io.seek(4, 1)  # Padding for 64 bit
    attributes = read_u16(details_io)
    share_mode = read_u16(details_io)

    event.details["Disposition"] = get_enum_name_or(FilesystemDisposition, disposition, "<unknown>")
    event.details["Options"] = get_filesysyem_create_options(options)
    event.details["Attributes"] = get_filesysyem_create_attributes(attributes)
    event.details["ShareMode"] = get_filesysyem_create_share_mode(share_mode)

    details_io.seek(0x4 + metadata.sizeof_pvoid * 2, 1)
    allocation = read_u32(details_io)
    allocation_value = allocation if disposition in [FilesystemDisposition.Supersede, FilesystemDisposition.Create,
                                                     FilesystemDisposition.OpenIf,
                                                     FilesystemDisposition.OverwriteIf] else "n/a"
    event.details["AllocationSize"] = allocation_value

    if impersonating_sid_length:
        event.details["Impersonating"] = get_sid_string(io.read(impersonating_sid_length))

    open_result = None
    if extra_detail_io:
        open_result = read_u32(extra_detail_io)
        event.details["OpenResult"] = get_enum_name_or(FilesystemOpenResult, open_result, "<unknown>")

    if open_result in [FilesystemOpenResult.Superseded, FilesystemOpenResult.Created, FilesystemOpenResult.Overwritten]:
        event.category = "Write"
    elif open_result in [FilesystemOpenResult.Opened, FilesystemOpenResult.Exists, FilesystemOpenResult.DoesNotExist]:
        pass
    elif event.details["Disposition"] in ["Open", "<unknown>"]:
        pass
    else:
        event.category = "Write"
예제 #14
0
    def __init__(self, io, read_pvoid, strings_table):
        super(ProcessTable, self).__init__()
        self._read_pvoid = read_pvoid
        self._strings_table = strings_table
        process_table_start = io.tell()
        number_of_processes = read_u32(io)

        # The array of process indexes is not essential becuase they appear in the process structure itself.
        # process_index_array = [read_u32(io) for _ in range(number_of_processes)]
        io.seek(number_of_processes * 4,
                1)  # jump over the process indexes array

        process_offsets_array = [
            read_u32(io) for _ in range(number_of_processes)
        ]
        for offset in process_offsets_array:
            io.seek(process_table_start + offset, 0)
            process_index, process = self.__read_process(io)
            self[process_index] = process
def get_process_created_details(io, metadata, event, extra_detail_io):
    io.seek(4, 1)  # Unknown fields
    event.details["PID"] = read_u32(io)
    io.seek(0x24, 1)  # Unknown fields
    unknown_size1 = read_u8(io)
    unknown_size2 = read_u8(io)
    path_info = read_detail_string_info(io)
    command_line_info = read_detail_string_info(io)
    io.seek(2 + unknown_size1 + unknown_size2, 1)  # Unknown fields
    event.path = read_detail_string(io, path_info)
    event.details["Command line"] = read_detail_string(io, command_line_info)
def get_registry_open_or_create_key_extra_details(metadata, event, extra_detail_io, details_info):
    event.category = "Read"
    if 0 == details_info["desired_access"]:
        return

    event.details["Desired Access"] = get_registry_access_mask_string(details_info["desired_access"])
    if not extra_detail_io:
        return

    if event.details["Desired Access"] == "Maximum Allowed":
        event.details["Granted Access"] = get_registry_access_mask_string(read_u32(extra_detail_io))
    else:
        extra_detail_io.seek(4, 1)

    disposition = read_u32(extra_detail_io)
    try:
        event.details["Disposition"] = RegistryDisposition(disposition).name
        if event.details["Disposition"] == RegistryDisposition.REG_CREATED_NEW_KEY.name:
            event.category = "Write"
    except ValueError:
        pass
def get_registry_event_details(io, metadata, event, extra_detail_io):
    path_info = read_detail_string_info(io)
    details_info = dict()  # information that is needed by the extra details structure

    if event.operation in [RegistryOperation.RegLoadKey.name, RegistryOperation.RegRenameKey.name]:
        details_info["new_path_info"] = read_detail_string_info(io)
        extra_detail_io = io  # the new path is a part of the details structure
    elif event.operation in [RegistryOperation.RegOpenKey.name, RegistryOperation.RegCreateKey.name]:
        io.seek(2, 1)  # Unknown field
        details_info["desired_access"] = read_u32(io)
    elif event.operation in [RegistryOperation.RegQueryKey.name, RegistryOperation.RegQueryValue.name]:
        io.seek(2, 1)  # Unknown field
        details_info["length"] = read_u32(io)
        details_info["information_class"] = read_u32(io)
    elif event.operation in [RegistryOperation.RegEnumValue.name, RegistryOperation.RegEnumKey.name]:
        io.seek(2, 1)  # Unknown field
        details_info["length"] = read_u32(io)
        details_info["index"] = read_u32(io)
        details_info["information_class"] = read_u32(io)
    elif event.operation == RegistryOperation.RegSetInfoKey.name:
        io.seek(2, 1)  # Unknown field
        details_info["key_set_information_class"] = read_u32(io)
        io.seek(4, 1)  # Unknown field
        details_info["length"] = read_u16(io)
        io.seek(2, 1)  # Unknown field
        extra_detail_io = io  # For RegSetInfoKey the data is in the details structure
    elif event.operation == RegistryOperation.RegSetValue.name:
        io.seek(2, 1)  # Unknown field
        details_info["reg_type"] = read_u32(io)
        details_info["length"] = read_u32(io)
        details_info["data_length"] = read_u32(io)
        extra_detail_io = io  # For RegSetValue the data is in the details structure

    event.path = read_detail_string(io, path_info)

    # Get the extra details structure
    if metadata.should_get_details and event.operation in RegistryExtraDetailsHandler:
        RegistryExtraDetailsHandler[event.operation](metadata, event, extra_detail_io, details_info)
def get_process_exit_details(io, metadata, event, extra_details_io):
    event.details["Exit Status"] = read_u32(io)
    kernel_time = read_duration(io)
    user_time = read_duration(io)
    working_set = read_u64(io)
    peak_working_set = read_u64(io)
    private_bytes = read_u64(io)
    peak_private_bytes = read_u64(io)

    event.details["User Time"] = user_time
    event.details["Kernel Time"] = kernel_time
    event.details["Private Bytes"] = private_bytes
    event.details["Peak Private Bytes"] = peak_private_bytes
    event.details["Working Set"] = working_set
    event.details["Peak Working Set"] = peak_working_set
예제 #19
0
    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.")
예제 #20
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 ''
예제 #21
0
 def __read_module(self, stream):
     _ = read_pvoid(stream, self._is_64bit)  # Unknown field
     base_address = read_pvoid(stream, self._is_64bit)
     size = read_u32(stream)
     image_path = self._strings_table[read_u32(stream)]
     version = self._strings_table[read_u32(stream)]
     company = self._strings_table[read_u32(stream)]
     description = self._strings_table[read_u32(stream)]
     timestamp = read_u32(stream)
     stream.seek(0x18, 1)  # Unknown field
     return Module(base_address=base_address, size=size, path=image_path, version=version, company=company,
                   description=description, timestamp=timestamp)
예제 #22
0
    def __init__(self, io, total_size, is_64bit, strings_table):
        super(ProcessTable, self).__init__()
        self._is_64bit = is_64bit
        self._strings_table = strings_table
        stream = BytesIO(io.read(total_size))
        number_of_processes = read_u32(stream)

        # The array of process indexes is not essential becuase they appear in the process structure itself.
        # process_index_array = [read_u32(stream) for _ in range(number_of_processes)]
        stream.seek(number_of_processes * 4, 1)  # jump over the process indexes array

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

        for _ in range(number_of_processes):
            process_index, process = self.__read_process(stream)
            self[process_index] = process
def get_network_event_details(io, metadata, event, extra_detail_io):
    flags = read_u16(io)
    is_source_ipv4 = flags & 1 != 0
    is_dest_ipv4 = flags & 2 != 0
    is_tcp = flags & 4 != 0

    protocol = "TCP" if is_tcp else "UDP"
    event.operation = protocol + " " + event.operation

    io.seek(2, 1)  # Unknown field
    event.details['Length'] = read_u32(io)
    source_ip = io.read(16)
    dest_ip = io.read(16)
    source_port = read_u16(io)
    dest_port = read_u16(io)

    event.path = "{}:{} -> {}:{}".format(
        metadata.hostname_idx(source_ip, is_source_ipv4), metadata.port_idx(source_port, is_tcp),
        metadata.hostname_idx(dest_ip, is_dest_ipv4), metadata.port_idx(dest_port, is_tcp))

    extra_details = read_utf16_multisz(io)
    for i in range(len(extra_details) // 2):
        event.details[extra_details[i * 2]] = extra_details[i * 2 + 1]
예제 #24
0
def read_event(io, metadata):
    """Reads the event that the stream points to.

    :param io: the stream.
    :param metadata: metadata of the PML file.
    :return: Event object.
    """
    COMMON_EVENT_INFO_SIZE = 0x34  # the size of the fields that are common to all events.
    stream = BytesIO(io.read(COMMON_EVENT_INFO_SIZE))

    process = metadata.process_idx(read_u32(stream))
    tid = read_u32(stream)
    event_class = EventClass(read_u32(stream))
    operation = EventClassOperation[event_class](read_u16(stream))
    stream.seek(6, 1)  # Unknown field
    duration = read_duration(stream)
    date = read_filetime(stream)
    result = read_u32(stream)
    stacktrace_depth = read_u16(stream)
    stream.seek(2, 1)  # Unknown field
    details_size = read_u32(stream)
    extra_details_offset = read_u32(stream)

    stream = BytesIO(io.read(stacktrace_depth * sizeof_pvoid(metadata.is_64bit)))
    stacktrace = [read_pvoid(stream, metadata.is_64bit) for _ in range(stacktrace_depth)]

    details = OrderedDict()
    event = Event(process=process, tid=tid, event_class=event_class, operation=operation, duration=duration, date=date,
                  result=result, stacktrace=stacktrace, category='', path='', details=details)

    details_stream = BytesIO(io.read(details_size))
    extra_details_stream = None
    if extra_details_offset > 0:
        # The extra details structure surprisingly can be separated from the event structure
        extra_details_offset -= \
            (COMMON_EVENT_INFO_SIZE + details_size + stacktrace_depth * sizeof_pvoid(metadata.is_64bit))
        assert extra_details_offset >= 0

        current_offset = io.tell()
        io.seek(extra_details_offset, 1)
        extra_details_stream_size = read_u16(io)
        extra_details_stream = BytesIO(io.read(extra_details_stream_size))
        io.seek(current_offset, 0)
    get_event_details(details_stream, metadata, event, extra_details_stream)
    return event
예제 #25
0
    def __read_process(self, stream):
        process_index = read_u32(stream)
        pid = read_u32(stream)
        parent_pid = read_u32(stream)

        stream.seek(4, 1)  # Unknown field
        authentication_id = read_u64(stream)
        session = read_u32(stream)

        stream.seek(4, 1)  # Unknown field
        start_time = read_filetime(stream)
        end_time = read_filetime(stream)
        virtualized = read_u32(stream)
        is_process_64bit = read_u32(stream)

        integrity = self._strings_table[read_u32(stream)]
        user = self._strings_table[read_u32(stream)]
        process_name = self._strings_table[read_u32(stream)]
        image_path = self._strings_table[read_u32(stream)]
        command_line = self._strings_table[read_u32(stream)]
        company = self._strings_table[read_u32(stream)]
        version = self._strings_table[read_u32(stream)]
        description = self._strings_table[read_u32(stream)]

        _ = read_pvoid(stream, self._is_64bit)  # Unknown field
        _ = read_u64(stream)  # Unknown field
        number_of_modules = read_u32(stream)
        modules = [self.__read_module(stream) for _ in range(number_of_modules)]
        return process_index, Process(pid=pid, parent_pid=parent_pid, authentication_id=authentication_id,
                                      session=session, virtualized=virtualized, is_process_64bit=is_process_64bit,
                                      integrity=integrity, user=user, process_name=process_name, image_path=image_path,
                                      command_line=command_line, company=company, version=version,
                                      description=description, start_time=start_time, end_time=end_time,
                                      modules=modules)
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
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_load_image_details(io, metadata, event, extra_detail_io):
    event.details["Image Base"] = metadata.read_pvoid(io)
    event.details["Image Size"] = read_u32(io)
    path_info = read_detail_string_info(io)
    io.seek(2, 1)  # Unknown field
    event.path = read_detail_string(io, path_info)
def get_thread_create_details(io, metadata, event, extra_detail_io):
    event.details["Thread ID"] = read_u32(io)