示例#1
0
    def test_next_cswitch(self, thread_registry_mock, kevent_mock):

        context_switch_registry = ContextSwitchRegistry(thread_registry_mock, kevent_mock)
        ts = datetime.strptime("12:05:45.233", '%H:%M:%S.%f')
        kcs1 = ddict({'old_thread_wait_ideal_processor': 2, 'previous_c_state': 1, 'old_thread_state': 2,
                      'old_thread_priority': 0, 'reserved': 777748717, 'spare_byte': 0,
                      'old_thread_wait_reason': 0, 'new_thread_wait_time': '0x0', 'old_thread_wait_mode': 0,
                      'new_thread_priority': 15, 'new_thread_id': '0x1054', 'old_thread_id': '0x0'})
        new_thread_id = int(kcs1.new_thread_id, 16)
        context_switch_registry.next_cswitch(1, ts, kcs1)

        thread_registry_mock.get_thread.assert_has_calls([call(new_thread_id),
                                                         call(int(kcs1.old_thread_id, 16))])

        assert (1, new_thread_id,) in context_switch_registry.context_switches()
        cs = context_switch_registry.context_switches()[(1, new_thread_id,)]
        assert cs

        assert cs.timestamp is ts
        assert cs.next_proc_name == "explorer.exe"
        assert cs.next_thread_wait_time == 0
        assert cs.next_thread_prio == 15
        assert cs.prev_thread_prio == 0
        assert cs.prev_thread_state is ThreadState.RUNNING
        assert cs.count == 1
        assert cs.prev_thread_wait_mode is WaitMode.KERNEL
        assert cs.prev_thread_wait_reason is WaitReason.EXECUTIVE
示例#2
0
    def test_next_cswitch_in_registry(self, thread_registry_empty_mock,
                                      kevent_mock):
        context_switch_registry = ContextSwitchRegistry(
            thread_registry_empty_mock, kevent_mock)

        kcs1 = ddict({
            'old_thread_wait_ideal_processor': 3,
            'previous_c_state': 0,
            'old_thread_state': 5,
            'old_thread_priority': 8,
            'reserved': 4294967294,
            'spare_byte': 0,
            'old_thread_wait_reason': 8,
            'new_thread_wait_time': '0x0',
            'old_thread_wait_mode': 1,
            'new_thread_priority': 8,
            'new_thread_id': '0x1fc8',
            'old_thread_id': '0x2348'
        })
        kcs2 = ddict({
            'old_thread_wait_ideal_processor': 3,
            'previous_c_state': 0,
            'old_thread_state': 3,
            'old_thread_priority': 8,
            'reserved': 4294967295,
            'spare_byte': 0,
            'old_thread_wait_reason': 8,
            'new_thread_wait_time': '0x0',
            'old_thread_wait_mode': 1,
            'new_thread_priority': 5,
            'new_thread_id': '0x1fc8',
            'old_thread_id': '0x2348'
        })

        context_switch_registry.next_cswitch(
            1, datetime.strptime("12:05:45.233", '%H:%M:%S.%f'), kcs1)
        context_switch_registry.next_cswitch(
            1, datetime.strptime("12:05:45.234", '%H:%M:%S.%f'), kcs2)

        k = (1, int(kcs1.new_thread_id, 16))
        cs = context_switch_registry.context_switches()[k]
        assert cs
        assert cs.count == 2
        assert cs.next_thread_prio == 5
        assert cs.prev_thread_state is ThreadState.STANDBY
        assert cs.timestamp == datetime.strptime("12:05:45.234", '%H:%M:%S.%f')
        assert cs.prev_thread_wait_reason is WaitReason.FREE_PAGE
示例#3
0
    def test_next_cswitch_in_registry(self, thread_registry_empty_mock, kevent_mock):
        context_switch_registry = ContextSwitchRegistry(thread_registry_empty_mock, kevent_mock)

        kcs1 = ddict({'old_thread_wait_ideal_processor': 3, 'previous_c_state': 0, 'old_thread_state': 5,
                      'old_thread_priority': 8, 'reserved': 4294967294, 'spare_byte': 0,
                      'old_thread_wait_reason': 8, 'new_thread_wait_time': '0x0', 'old_thread_wait_mode': 1,
                      'new_thread_priority': 8, 'new_thread_id': '0x1fc8', 'old_thread_id': '0x2348'})
        kcs2 = ddict({'old_thread_wait_ideal_processor': 3, 'previous_c_state': 0, 'old_thread_state': 3,
                      'old_thread_priority': 8, 'reserved': 4294967295, 'spare_byte': 0,
                      'old_thread_wait_reason': 8, 'new_thread_wait_time': '0x0', 'old_thread_wait_mode': 1,
                      'new_thread_priority': 5, 'new_thread_id': '0x1fc8', 'old_thread_id': '0x2348'})

        context_switch_registry.next_cswitch(1, datetime.strptime("12:05:45.233", '%H:%M:%S.%f'), kcs1)
        context_switch_registry.next_cswitch(1, datetime.strptime("12:05:45.234", '%H:%M:%S.%f'), kcs2)

        k = (1, int(kcs1.new_thread_id, 16))
        cs = context_switch_registry.context_switches()[k]
        assert cs
        assert cs.count == 2
        assert cs.next_thread_prio == 5
        assert cs.prev_thread_state is ThreadState.STANDBY
        assert cs.timestamp == datetime.strptime("12:05:45.234", '%H:%M:%S.%f')
        assert cs.prev_thread_wait_reason is WaitReason.FREE_PAGE
示例#4
0
    def test_next_cswitch(self, thread_registry_mock, kevent_mock):

        context_switch_registry = ContextSwitchRegistry(
            thread_registry_mock, kevent_mock)
        ts = datetime.strptime("12:05:45.233", '%H:%M:%S.%f')
        kcs1 = ddict({
            'old_thread_wait_ideal_processor': 2,
            'previous_c_state': 1,
            'old_thread_state': 2,
            'old_thread_priority': 0,
            'reserved': 777748717,
            'spare_byte': 0,
            'old_thread_wait_reason': 0,
            'new_thread_wait_time': '0x0',
            'old_thread_wait_mode': 0,
            'new_thread_priority': 15,
            'new_thread_id': '0x1054',
            'old_thread_id': '0x0'
        })
        new_thread_id = int(kcs1.new_thread_id, 16)
        context_switch_registry.next_cswitch(1, ts, kcs1)

        thread_registry_mock.get_thread.assert_has_calls(
            [call(new_thread_id),
             call(int(kcs1.old_thread_id, 16))])

        assert (
            1,
            new_thread_id,
        ) in context_switch_registry.context_switches()
        cs = context_switch_registry.context_switches()[(
            1,
            new_thread_id,
        )]
        assert cs

        assert cs.timestamp is ts
        assert cs.next_proc_name == "explorer.exe"
        assert cs.next_thread_wait_time == 0
        assert cs.next_thread_prio == 15
        assert cs.prev_thread_prio == 0
        assert cs.prev_thread_state is ThreadState.RUNNING
        assert cs.count == 1
        assert cs.prev_thread_wait_mode is WaitMode.KERNEL
        assert cs.prev_thread_wait_reason is WaitReason.EXECUTIVE
示例#5
0
    def run(self):
        """Filament main routine.

        Setups the interval repeating function and polls for
        the kernel events from the queue.
        """
        on_interval = self._find_filament_func('on_interval')
        if on_interval:
            self.scheduler.add_executor(ThreadPoolExecutor(max_workers=4))
            self.scheduler.start()
            self.scheduler.add_job(self._filament_module.on_interval,
                                   'interval',
                                   seconds=self._interval,
                                   max_instances=4,
                                   misfire_grace_time=60)
        while self._poll():
            try:
                kevent = self._keventq.get()
                self._filament_module.on_next_kevent(ddict(kevent))
            except Exception:
                self._logger.error('Unexpected filament error',
                                   exc_info=sys.exc_info())
示例#6
0
    def add_image_meta(self, path):
        """Registers image meta information.

        This method parses the PE (Portable Executable) binary format
        of the the image passed in the `path` parameter.

        It then extracts some basic headers present in the PE, as well
        as sections which form the binary image.

        Parameters
        ----------

        path: str
            the absolute path of the image file
        """
        if not self.enabled:
            return None
        try:
            if (path.endswith('exe') or
                path.endswith('dll') or
                path.endswith('sys')) and \
                 path not in self.image_metas:
                    pe = pefile.PE(path, fast_load=True)
                    file_header = ddict(underscore_dict_keys(pe.FILE_HEADER.dump_dict()))
                    # create image meta instance
                    image_meta = ImageMeta(file_header.machine.value,
                                           file_header.time_date_stamp.value,
                                           file_header.number_of_sections.value)
                    image_meta.sections = [dict(name=__decode__(ddict(se.dump_dict()).Name.Value),
                                                entropy=se.get_entropy(),
                                                md5=se.get_hash_md5(),
                                                sha1=se.get_hash_sha1(),
                                                sha256=se.get_hash_sha256(),
                                                sha512=se.get_hash_sha512())
                                           for se in pe.sections]
                    # parse directory entry imports
                    if self.imports:
                        pe.full_load()
                        self.full_loaded = True
                        for module in self.__directory_entry_import__(pe):
                            dll = __decode__(module.dll)
                            imports = [__decode__(i.name)
                                       for i in module.imports
                                       if not i.import_by_ordinal]
                            image_meta.imports[dll] = imports
                    # parse the string table to extract
                    # the copyright, company, description
                    # and other attributes
                    if self.file_info:
                        if not self.full_loaded:
                            pe.full_load()
                        if self.__pe_has_version_info__(pe):
                            file_info = pe.FileInfo
                            if file_info and len(file_info) > 0:
                                file_info = file_info[0]
                                if self.__fi_has_string_table__(file_info):
                                    string_table = sorted(list(file_info.StringTable[0].entries.items()))
                                    # get file info entries from table index
                                    image_meta.org = __from_idx__(string_table, 0)
                                    image_meta.description = __from_idx__(string_table, 1)
                                    image_meta.version = __from_idx__(string_table, 2)
                                    image_meta.internal_name = __from_idx__(string_table, 3)
                                    image_meta.copyright = __from_idx__(string_table, 4)

                    self.image_metas[path] = image_meta

                    return image_meta
        except Exception:
            # ignore the exception for now
            # but consider logging it to file
            # in case it can provide hints for
            # troubleshooting purposes
            pass
示例#7
0
    def _on_next_kevent(self, ktype, cpuid, ts, kparams):
        """Callback which fires when new kernel event arrives.

        This callback is invoked for every new kernel event
        forwarded from the kernel stream collector.

        Parameters
        ----------

        ktype: tuple
            Kernel event type.
        cpuid: int
            Indentifies the CPU core where the event
            has been captured.
        ts: str
            Temporal reference of the kernel event.
        kparams: dict
            Kernel event's parameters.
        """

        # initialize kernel event properties
        self.kevent.ts = ts
        self.kevent.cpuid = cpuid
        self.kevent.name = ktuple_to_name(ktype)
        kparams = ddict(kparams)
        # thread / process kernel events
        if ktype in [CREATE_PROCESS, CREATE_THREAD, ENUM_PROCESS, ENUM_THREAD]:
            self.thread_registry.add_thread(ktype, kparams)
            if ktype in [CREATE_PROCESS, CREATE_THREAD]:
                self.thread_registry.init_thread_kevent(
                    self.kevent, ktype, kparams)
                self._render(ktype)
        elif ktype in [TERMINATE_PROCESS, TERMINATE_THREAD]:
            self.thread_registry.init_thread_kevent(self.kevent, ktype,
                                                    kparams)
            self._render(ktype)
            self.thread_registry.remove_thread(ktype, kparams)

        # file system/disk kernel events
        elif ktype in [
                CREATE_FILE, DELETE_FILE, CLOSE_FILE, READ_FILE, WRITE_FILE
        ]:
            self.fsio.parse_fsio(ktype, kparams)
            self._render(ktype)

        # dll kernel events
        elif ktype in [LOAD_IMAGE, ENUM_IMAGE]:
            self.dll_repository.register_dll(kparams)
            if ktype == LOAD_IMAGE:
                self._render(ktype)
        elif ktype == UNLOAD_IMAGE:
            self.dll_repository.unregister_dll(kparams)
            self._render(ktype)

        # registry kernel events
        elif ktype == REG_CREATE_KCB:
            self.hive_parser.add_kcb(kparams)
        elif ktype == REG_DELETE_KCB:
            self.hive_parser.remove_kcb(kparams.key_handle)

        elif ktype in [
                REG_CREATE_KEY, REG_DELETE_KEY, REG_OPEN_KEY, REG_QUERY_KEY,
                REG_SET_VALUE, REG_DELETE_VALUE, REG_QUERY_VALUE
        ]:
            self.hive_parser.parse_hive(ktype, kparams)
            self._render(ktype)

        # network kernel events
        elif ktype in [
                SEND_SOCKET_TCPV4, SEND_SOCKET_UDPV4, RECV_SOCKET_TCPV4,
                RECV_SOCKET_UDPV4, ACCEPT_SOCKET_TCPV4, CONNECT_SOCKET_TCPV4,
                DISCONNECT_SOCKET_TCPV4, RECONNECT_SOCKET_TCPV4
        ]:
            self.tcpip_parser.parse_tcpip(ktype, kparams)
            self._render(ktype)

        if self._filament:
            # call filament method
            # to process the next
            # kernel event from the stream
            if ktype not in [ENUM_PROCESS, ENUM_THREAD, ENUM_IMAGE]:
                if self.kevent.name:
                    self._filament.process(self.kevent)
示例#8
0
    def add_image_meta(self, path):
        """Registers image meta information.

        This method parses the PE (Portable Executable) binary format
        of the the image passed in the `path` parameter.

        It then extracts some basic headers present in the PE, as well
        as sections which form the binary image.

        Parameters
        ----------

        path: str
            the absolute path of the image file
        """
        if not self.enabled:
            return None
        try:
            if (path.endswith('exe') or
                path.endswith('dll') or
                path.endswith('sys')) and \
                 path not in self.image_metas:
                pe = pefile.PE(path, fast_load=True)
                file_header = ddict(
                    underscore_dict_keys(pe.FILE_HEADER.dump_dict()))
                # create image meta instance
                image_meta = ImageMeta(file_header.machine.value,
                                       file_header.time_date_stamp.value,
                                       file_header.number_of_sections.value)
                image_meta.sections = [
                    dict(name=__decode__(ddict(se.dump_dict()).Name.Value),
                         entropy=se.get_entropy(),
                         md5=se.get_hash_md5(),
                         sha1=se.get_hash_sha1(),
                         sha256=se.get_hash_sha256(),
                         sha512=se.get_hash_sha512()) for se in pe.sections
                ]
                # parse directory entry imports
                if self.imports:
                    pe.full_load()
                    self.full_loaded = True
                    for module in self.__directory_entry_import__(pe):
                        dll = __decode__(module.dll)
                        imports = [
                            __decode__(i.name) for i in module.imports
                            if not i.import_by_ordinal
                        ]
                        image_meta.imports[dll] = imports
                # parse the string table to extract
                # the copyright, company, description
                # and other attributes
                if self.file_info:
                    if not self.full_loaded:
                        pe.full_load()
                    if self.__pe_has_version_info__(pe):
                        file_info = pe.FileInfo
                        if file_info and len(file_info) > 0:
                            file_info = file_info[0]
                            if self.__fi_has_string_table__(file_info):
                                string_table = sorted(
                                    list(file_info.StringTable[0].entries.
                                         items()))
                                # get file info entries from table index
                                image_meta.org = __from_idx__(string_table, 0)
                                image_meta.description = __from_idx__(
                                    string_table, 1)
                                image_meta.version = __from_idx__(
                                    string_table, 2)
                                image_meta.internal_name = __from_idx__(
                                    string_table, 3)
                                image_meta.copyright = __from_idx__(
                                    string_table, 4)

                self.image_metas[path] = image_meta

                return image_meta
        except Exception:
            # ignore the exception for now
            # but consider logging it to file
            # in case it can provide hints for
            # troubleshooting purposes
            pass
    def _on_next_kevent(self, ktype, cpuid, ts, kparams):
        """Callback which fires when new kernel event arrives.

        This callback is invoked for every new kernel event
        forwarded from the kernel stream collector.

        Parameters
        ----------

        ktype: tuple
            Kernel event type.
        cpuid: int
            Indentifies the CPU core where the event
            has been captured.
        ts: str
            Temporal reference of the kernel event.
        kparams: dict
            Kernel event's parameters.
        """

        # initialize kernel event properties
        self.kevent.ts = ts
        self.kevent.cpuid = cpuid
        self.kevent.name = ktuple_to_name(ktype)
        kparams = ddict(kparams)
        # thread / process kernel events
        if ktype in [CREATE_PROCESS,
                     CREATE_THREAD,
                     ENUM_PROCESS,
                     ENUM_THREAD]:
            self.thread_registry.add_thread(ktype, kparams)
            if ktype in [CREATE_PROCESS, CREATE_THREAD]:
                self.thread_registry.init_thread_kevent(self.kevent,
                                                        ktype,
                                                        kparams)
                self._render(ktype)
        elif ktype in [TERMINATE_PROCESS, TERMINATE_THREAD]:
            self.thread_registry.init_thread_kevent(self.kevent,
                                                    ktype,
                                                    kparams)
            self._render(ktype)
            self.thread_registry.remove_thread(ktype, kparams)

        # file system/disk kernel events
        elif ktype in [CREATE_FILE,
                       DELETE_FILE,
                       CLOSE_FILE,
                       READ_FILE,
                       WRITE_FILE]:
            self.fsio.parse_fsio(ktype, kparams)
            self._render(ktype)

        # dll kernel events
        elif ktype in [LOAD_IMAGE, ENUM_IMAGE]:
            self.dll_repository.register_dll(kparams)
            if ktype == LOAD_IMAGE:
                self._render(ktype)
        elif ktype == UNLOAD_IMAGE:
            self.dll_repository.unregister_dll(kparams)
            self._render(ktype)

        # registry kernel events
        elif ktype == REG_CREATE_KCB:
            self.hive_parser.add_kcb(kparams)
        elif ktype == REG_DELETE_KCB:
            self.hive_parser.remove_kcb(kparams.key_handle)

        elif ktype in [REG_CREATE_KEY,
                       REG_DELETE_KEY,
                       REG_OPEN_KEY,
                       REG_QUERY_KEY,
                       REG_SET_VALUE,
                       REG_DELETE_VALUE,
                       REG_QUERY_VALUE]:
            self.hive_parser.parse_hive(ktype, kparams)
            self._render(ktype)

        # network kernel events
        elif ktype in [SEND_SOCKET_TCPV4,
                       SEND_SOCKET_UDPV4,
                       RECV_SOCKET_TCPV4,
                       RECV_SOCKET_UDPV4,
                       ACCEPT_SOCKET_TCPV4,
                       CONNECT_SOCKET_TCPV4,
                       DISCONNECT_SOCKET_TCPV4,
                       RECONNECT_SOCKET_TCPV4]:
            self.tcpip_parser.parse_tcpip(ktype, kparams)
            self._render(ktype)

        if self._filament:
            # call filament method
            # to process the next
            # kernel event from the stream
            if ktype not in [ENUM_PROCESS,
                             ENUM_THREAD, ENUM_IMAGE]:
                if self.kevent.name:
                    self._filament.process(self.kevent)
示例#10
0
    def add_thread(self, ketype, kti):
        """Adds a new process or thread to thread registry.

        Parameters
        ----------

        ketype: tuple
            kernel event type
        kti: dict
            event payload as coming from the
            kernel event stream collector
        """
        if ketype == CREATE_PROCESS or ketype == ENUM_PROCESS:
            parent_pid = int(kti.parent_id, 16)
            process_id = int(kti.process_id, 16)
            # we assume the process id is
            # equal to thread id (in a single
            # threaded process)
            thread_id = process_id
            name = kti.image_file_name
            comm = kti.command_line

            thread = ThreadInfo(process_id, thread_id,
                                parent_pid,
                                name,
                                comm)
            if ketype == ENUM_PROCESS:
                thread.handles = [handle for handle in self._handles if handle.pid == process_id]
            if ketype == CREATE_PROCESS:
                image_meta = self.image_meta_registry.get_image_meta(thread.exe)
                if not image_meta:
                    image_meta = self.image_meta_registry.add_image_meta(thread.exe)
                thread.image_meta = image_meta
            self._threads[process_id] = thread

        elif ketype == CREATE_THREAD or ketype == ENUM_THREAD:
            # new thread created in the
            # context of the existing process
            # `procces_id` is the parent
            # of this thread
            process_id = int(kti.process_id, 16)
            parent_pid = process_id
            thread_id = int(kti.t_thread_id, 16)

            if parent_pid in self._threads:
                # copy info from the process
                # which created this thread
                pthread = self._threads[parent_pid]
                # increment the number of threads
                # for this process
                pthread.increment_child_count()

                name = pthread.name
                comm = pthread.comm

                thread = ThreadInfo(process_id, thread_id,
                                    parent_pid,
                                    name,
                                    comm)
                thread.ustack_base = hex(kti.user_stack_base)
                thread.kstack_base = hex(kti.stack_base)
                thread.base_priority = kti.base_priority
                thread.io_priority = kti.io_priority
                self._threads[thread_id] = thread
            else:
                # the parent process has not been found
                # query the os for process information
                handle = open_process(PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ,
                                      False,
                                      parent_pid)
                info = {}
                if handle:
                    info = self._query_process_info(handle)
                    close_handle(handle)
                else:
                    if get_last_error() == ERROR_ACCESS_DENIED:
                        if parent_pid == 0:
                            info = ddict(name='idle',
                                         comm='idle',
                                         parent_id=0)
                        else:
                            # the access to protected / system process
                            # can't be done with PROCESS_VM_READ or PROCESS_QUERY_INFORMATION
                            # flags. Open the process again but with
                            # restricted access rights, so we can get the process image file name
                            handle = open_process(PROCESS_QUERY_LIMITED_INFORMATION,
                                                  False,
                                                  parent_pid)
                            if handle:
                                info = self._query_process_info(handle, False)
                                close_handle(handle)

                # add a new thread and the parent process
                # we just found to avoid continuous lookup
                name = info.name if len(info) > 0 and info.name else NA
                comm = info.comm if len(info) > 0 and info.comm else NA
                ppid = info.parent_pid if len(info) > 0 and info.parent_pid else NA

                thread = ThreadInfo(process_id, thread_id,
                                    process_id,
                                    name,
                                    comm)
                thread.ustack_base = hex(kti.user_stack_base)
                thread.kstack_base = hex(kti.stack_base)
                thread.base_priority = kti.base_priority
                thread.io_priority = kti.io_priority

                parent = ThreadInfo(process_id, process_id,
                                    ppid,
                                    name,
                                    comm)
                # enumerate parent handles
                parent.handles = self.handle_repository.query_handles(process_id)

                self._threads[thread_id] = thread
                self._threads[parent_pid] = parent

        if self.on_thread_added_callback and callable(self.on_thread_added_callback):
            self.on_thread_added_callback(thread)
示例#11
0
 def on_next_kevent(self, kevent):
     try:
         self._filament_module.on_next_kevent(ddict(kevent))
     except Exception as e:
         self._logger.error('Unexpected filament error %s' % e)
示例#12
0
    def _enum_handles(self, process_id=None):
        """Enumerates handle information.

        Enumerates handle info on
        the start of the kernel capture.

        Returns a dictionary of handle's
        information including the handle id,
        access mask, and the process which owns
        the handle.
        """
        buff_size = MAX_BUFFER_SIZE
        size = c_ulong()
        # allocate the initial buffer
        buff = malloc(buff_size)
        handles = {}

        while True:
            status = zw_query_system_information(SYSTEM_HANDLE_INFORMATION_CLASS,
                                                 buff,
                                                 buff_size,
                                                 byref(size))
            if status == STATUS_INFO_LENGTH_MISMATCH:
                # the buffer is too small
                # increment the buffer size and try again
                buff_size += MAX_BUFFER_SIZE
            elif status == STATUS_SUCCESS:
                # cast the buffer to `SYSTEM_HANDLE_INFORMATION` struct
                # which contains an array of `SYSTEM_HANDLE` structures
                sys_handle_info = cast(buff, POINTER(SYSTEM_HANDLE_INFORMATION))
                sys_handle_info = sys_handle_info.contents
                handle_count = sys_handle_info.number_of_handles

                # resize the array size to the
                # actual number of file handles
                sys_handles = (SYSTEM_HANDLE * buff_size).from_address(addressof(sys_handle_info.handles))

                for i in range(handle_count):
                    sys_handle = sys_handles[i]
                    pid = sys_handle.process_id
                    handle = sys_handle.handle
                    obj = sys_handle.object
                    obj_type_index = sys_handle.object_type_number
                    access_mask = sys_handle.access_mask
                    if process_id and process_id == pid:
                        handles[obj] = ddict(pid=process_id,
                                             handle=handle,
                                             obj=obj,
                                             access_mask=access_mask,
                                             obj_type_index=obj_type_index)
                    elif process_id is None:
                        handles[obj] = ddict(pid=pid,
                                             handle=handle,
                                             obj=obj,
                                             access_mask=access_mask,
                                             obj_type_index=obj_type_index)
                break
            else:
                raise HandleEnumError(status)
            # reallocate the buffer
            buff = realloc(buff, buff_size)
        # free the buffer memory
        free(buff)

        return handles
示例#13
0
    def _on_next_kevent(self, ktype, cpuid, ts, kparams):
        """Callback which fires when new kernel event arrives.

        This callback is invoked for every new kernel event
        forwarded from the kernel stream collector.

        Parameters
        ----------

        ktype: tuple
            Kernel event type.
        cpuid: int
            Indentifies the CPU core where the event
            has been captured.
        ts: str
            Temporal reference of the kernel event.
        kparams: dict
            Kernel event's parameters.
        """

        # initialize kernel event properties
        self.kevent.ts = ts
        self.kevent.cpuid = cpuid
        self.kevent.name = ktuple_to_name(ktype)
        kparams = ddict(kparams)

        # thread / process kernel events
        if ktype in [CREATE_PROCESS, CREATE_THREAD, ENUM_PROCESS, ENUM_THREAD]:
            self.thread_registry.add_thread(ktype, kparams)
            if ktype in [CREATE_PROCESS, CREATE_THREAD]:
                self.thread_registry.init_thread_kevent(
                    self.kevent, ktype, kparams)
                self._aggregate(ktype)
        elif ktype in [TERMINATE_PROCESS, TERMINATE_THREAD]:
            self.thread_registry.init_thread_kevent(self.kevent, ktype,
                                                    kparams)
            self._aggregate(ktype)
            self.thread_registry.remove_thread(ktype, kparams)

        # file system/disk kernel events
        elif ktype in [
                CREATE_FILE, DELETE_FILE, CLOSE_FILE, READ_FILE, WRITE_FILE
        ]:
            self.fsio.parse_fsio(ktype, kparams)
            self._aggregate(ktype)

        # dll kernel events
        elif ktype in [LOAD_IMAGE, ENUM_IMAGE]:
            self.dll_repository.register_dll(kparams)
            if ktype == LOAD_IMAGE:
                self._aggregate(ktype)
        elif ktype == UNLOAD_IMAGE:
            self.dll_repository.unregister_dll(kparams)
            self._aggregate(ktype)
        #
        # # registry kernel events
        elif ktype == REG_CREATE_KCB:
            self.hive_parser.add_kcb(kparams)
        elif ktype == REG_DELETE_KCB:
            self.hive_parser.remove_kcb(kparams.key_handle)

        elif ktype in [
                REG_CREATE_KEY, REG_DELETE_KEY, REG_OPEN_KEY, REG_QUERY_KEY,
                REG_SET_VALUE, REG_DELETE_VALUE, REG_QUERY_VALUE
        ]:
            self.hive_parser.parse_hive(ktype, kparams)
            self._aggregate(ktype)

        # network kernel events
        elif ktype in [
                SEND_SOCKET_TCPV4, SEND_SOCKET_UDPV4, RECV_SOCKET_TCPV4,
                RECV_SOCKET_UDPV4, ACCEPT_SOCKET_TCPV4, CONNECT_SOCKET_TCPV4,
                DISCONNECT_SOCKET_TCPV4, RECONNECT_SOCKET_TCPV4
        ]:
            self.tcpip_parser.parse_tcpip(ktype, kparams)
            self._aggregate(ktype)

        # context switch events
        elif ktype == CONTEXT_SWITCH:
            self.context_switch_registry.next_cswitch(cpuid, ts, kparams)
            self._aggregate(ktype)

        if self._filament:
            # put the event on the queue
            # from where the filaments process
            # will poll for kernel events
            if ktype not in [
                    ENUM_PROCESS, ENUM_THREAD, ENUM_IMAGE, REG_CREATE_KCB,
                    REG_DELETE_KCB
            ]:
                ok = self.output_kevents[ktype] if ktype in self.output_kevents \
                    else False
                if self.kevent.name and ok:
                    thread = self.kevent.thread
                    # push the kernel event dict
                    # to processing queue
                    kevt = dict(params=self.kevent.params,
                                name=self.kevent.name,
                                pid=self.kevent.pid,
                                tid=self.kevent.tid,
                                timestamp=self.kevent.ts,
                                cpuid=self.kevent.cpuid,
                                category=self.kevent.category,
                                thread=dict(name=thread.name,
                                            exe=thread.exe,
                                            comm=thread.comm,
                                            pid=thread.pid,
                                            ppid=thread.ppid))
                    self.keventq.put(kevt)
示例#14
0
 def skips(self):
     return ddict(self._yaml.pop('skips', {}))
示例#15
0
 def image_meta(self):
     return ddict(self._yaml.pop('image_meta', {}))
示例#16
0
 def params(self, params):
     self._params = ddict(params)
示例#17
0
 def params(self, params):
     self._params = ddict(params)
示例#18
0
 def image_meta(self):
     return ddict(self._yaml.pop('image_meta', {}))
示例#19
0
 def skips(self):
     return ddict(self._yaml.pop('skips', {}))
示例#20
0
    def _query_process_info(self, handle, read_peb=True):
        """Gets an extended proc info.

        Parameters
        -----------

        handle: HANDLE
            handle to process for which the info
            should be acquired
        read_peb: boolean
            true in case the process PEB should be read

        """
        pbi_buff = malloc(sizeof(PROCESS_BASIC_INFORMATION))
        status = zw_query_information_process(
            handle, PROCESS_BASIC_INFO, pbi_buff,
            sizeof(PROCESS_BASIC_INFORMATION), byref(ULONG()))

        info = {}

        if status == STATUS_SUCCESS:
            pbi = cast(pbi_buff, POINTER(PROCESS_BASIC_INFORMATION))
            ppid = pbi.contents.inherited_from_unique_process_id
            if read_peb:
                # read the PEB to get the process parameters.
                # Because the PEB structure resides
                # in the address space of another process
                # we must read the memory block in order
                # to access the structure's fields
                peb_addr = pbi.contents.peb_base_address
                peb_buff = read_process_memory(handle, peb_addr, sizeof(PEB))
                if peb_buff:
                    peb = cast(peb_buff, POINTER(PEB))
                    # read the RTL_USER_PROCESS_PARAMETERS struct
                    # which contains the command line and the image
                    # name of the process
                    pp = peb.contents.process_parameters
                    pp_buff = read_process_memory(
                        handle, pp, sizeof(RTL_USER_PROCESS_PARAMETERS))
                    if pp_buff:
                        pp = cast(pp_buff,
                                  POINTER(RTL_USER_PROCESS_PARAMETERS))

                        comm = pp.contents.command_line.buffer
                        comm_len = pp.contents.command_line.length
                        exe = pp.contents.image_path_name.buffer
                        exe_len = pp.contents.image_path_name.length

                        # these memory reads are required
                        # to copy the command line and image name buffers
                        cb = read_process_memory(handle, comm, comm_len)
                        eb = read_process_memory(handle, exe, exe_len)

                        if cb and eb:
                            # cast the buffers to
                            # UNICODE strings
                            comm = cast(cb, c_wchar_p).value
                            exe = cast(eb, c_wchar_p).value

                            # the image name contains the full path
                            # split the string to get the exec name
                            name = exe[exe.rfind('\\') + 1:]
                            info = ddict(name=name, comm=comm, parent_pid=ppid)
                            free(cb)
                            free(eb)
                        free(pp_buff)

                    free(peb_buff)
            else:
                # query only the process image file name
                exe = ctypes.create_unicode_buffer(MAX_PATH)
                size = DWORD(MAX_PATH)
                name = None
                status = query_full_process_image_name(handle, 0, exe,
                                                       byref(size))
                if status:
                    exe = exe.value
                    name = exe[exe.rfind('\\') + 1:]
                info = ddict(name=name if name else NA,
                             comm=exe,
                             parent_pid=ppid)
        if pbi_buff:
            free(pbi_buff)

        return info
示例#21
0
    def _query_process_info(self, handle, read_peb=True):
        """Gets an extended proc info.

        Parameters
        -----------

        handle: HANDLE
            handle to process for which the info
            should be acquired
        read_peb: boolean
            true in case the process PEB should be read

        """
        pbi_buff = malloc(sizeof(PROCESS_BASIC_INFORMATION))
        status = zw_query_information_process(handle,
                                              PROCESS_BASIC_INFO,
                                              pbi_buff,
                                              sizeof(PROCESS_BASIC_INFORMATION),
                                              byref(ULONG()))

        info = {}

        if status == STATUS_SUCCESS:
            pbi = cast(pbi_buff, POINTER(PROCESS_BASIC_INFORMATION))
            ppid = pbi.contents.inherited_from_unique_process_id
            if read_peb:
                # read the PEB to get the process parameters.
                # Because the PEB structure resides
                # in the address space of another process
                # we must read the memory block in order
                # to access the structure's fields
                peb_addr = pbi.contents.peb_base_address
                peb_buff = read_process_memory(handle, peb_addr, sizeof(PEB))
                if peb_buff:
                    peb = cast(peb_buff, POINTER(PEB))
                    # read the RTL_USER_PROCESS_PARAMETERS struct
                    # which contains the command line and the image
                    # name of the process
                    pp = peb.contents.process_parameters
                    pp_buff = read_process_memory(handle,
                                                  pp,
                                                  sizeof(RTL_USER_PROCESS_PARAMETERS))
                    if pp_buff:
                        pp = cast(pp_buff, POINTER(RTL_USER_PROCESS_PARAMETERS))

                        comm = pp.contents.command_line.buffer
                        comm_len = pp.contents.command_line.length
                        exe = pp.contents.image_path_name.buffer
                        exe_len = pp.contents.image_path_name.length

                        # these memory reads are required
                        # to copy the command line and image name buffers
                        cb = read_process_memory(handle, comm, comm_len)
                        eb = read_process_memory(handle, exe, exe_len)

                        if cb and eb:
                            # cast the buffers to
                            # UNICODE strings
                            comm = cast(cb, c_wchar_p).value
                            exe = cast(eb, c_wchar_p).value

                            # the image name contains the full path
                            # split the string to get the exec name
                            name = exe[exe.rfind('\\') + 1:]
                            info = ddict(name=name,
                                         comm=comm,
                                         parent_pid=ppid)
                            free(cb)
                            free(eb)
                        free(pp_buff)

                    free(peb_buff)
            else:
                # query only the process image file name
                exe = ctypes.create_unicode_buffer(MAX_PATH)
                size = DWORD(MAX_PATH)
                name = None
                status = query_full_process_image_name(handle,
                                                       0,
                                                       exe,
                                                       byref(size))
                if status:
                    exe = exe.value
                    name = exe[exe.rfind('\\') + 1:]
                info = ddict(name=name if name else NA,
                             comm=exe if type(exe) is str else None,
                             parent_pid=ppid)
        if pbi_buff:
            free(pbi_buff)

        return info
示例#22
0
    def add_thread(self, ketype, kti):
        """Adds a new process or thread to thread registry.

        Parameters
        ----------

        ketype: tuple
            kernel event type
        kti: dict
            event payload as coming from the
            kernel event stream collector
        """
        if ketype == CREATE_PROCESS or ketype == ENUM_PROCESS:
            parent_pid = int(kti.parent_id, 16)
            process_id = int(kti.process_id, 16)
            # we assume the process id is
            # equal to thread id (in a single
            # threaded process)
            thread_id = process_id
            name = kti.image_file_name
            comm = kti.command_line
            suid = kti.user_sid

            thread = ThreadInfo(process_id, thread_id, parent_pid, name, comm,
                                suid)
            if ketype == ENUM_PROCESS:
                thread.handles = [
                    handle for handle in self._handles
                    if handle.pid == process_id
                ]
            else:
                thread.handles = self.handle_repository.query_handles(
                    process_id)
            self._threads[process_id] = thread
        elif ketype == CREATE_THREAD or ketype == ENUM_THREAD:
            # new thread created in the
            # context of the existing process
            # `procces_id` is the parent
            # of this thread
            process_id = int(kti.process_id, 16)
            parent_pid = process_id
            thread_id = int(kti.t_thread_id, 16)

            if parent_pid in self._threads:
                # copy info from the process
                # which created this thread
                pthread = self._threads[parent_pid]
                # increment the number of threads
                # for this process
                pthread.increment_child_count()

                name = pthread.name
                comm = pthread.comm
                suid = pthread.suid

                thread = ThreadInfo(process_id, thread_id, parent_pid, name,
                                    comm, suid)
                thread.ustack_base = hex(kti.user_stack_base)
                thread.kstack_base = hex(kti.stack_base)
                thread.base_priority = kti.base_priority
                thread.io_priority = kti.io_priority
                self._threads[thread_id] = thread
            else:
                # the parent process has not been found
                # query the os for process information
                handle = open_process(
                    PROCESS_QUERY_INFORMATION
                    | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ,
                    False, parent_pid)
                info = {}
                if handle:
                    info = self._query_process_info(handle)
                    close_handle(handle)
                else:
                    if get_last_error() == ERROR_ACCESS_DENIED:
                        if parent_pid == 0:
                            info = ddict(name='idle', comm='idle', parent_id=0)
                        else:
                            # the access to protected / system process
                            # can't be done with PROCESS_VM_READ or PROCESS_QUERY_INFORMATION
                            # flags. Open the process again but with
                            # restricted access rights, so we can get the process image file name
                            handle = open_process(
                                PROCESS_QUERY_LIMITED_INFORMATION, False,
                                parent_pid)
                            if handle:
                                info = self._query_process_info(handle, False)
                                close_handle(handle)

                # add a new thread and the parent process
                # we just found to avoid continuous lookup
                name = info.name if len(info) > 0 and info.name else NA
                comm = info.comm if len(info) > 0 and info.comm else NA
                ppid = info.parent_pid if len(
                    info) > 0 and info.parent_pid else NA

                thread = ThreadInfo(process_id, thread_id, process_id, name,
                                    comm, None)
                thread.ustack_base = hex(kti.user_stack_base)
                thread.kstack_base = hex(kti.stack_base)
                thread.base_priority = kti.base_priority
                thread.io_priority = kti.io_priority

                parent = ThreadInfo(process_id, process_id, ppid, name, comm,
                                    None)
                # enumerate parent handles
                parent.handles = self.handle_repository.query_handles(
                    process_id)

                self._threads[thread_id] = thread
                self._threads[parent_pid] = parent

        if self.on_thread_added_callback and callable(
                self.on_thread_added_callback):
            self.on_thread_added_callback(thread)
示例#23
0
    def _on_next_kevent(self, ktype, cpuid, ts, kparams):
        """Callback which fires when new kernel event arrives.

        This callback is invoked for every new kernel event
        forwarded from the kernel stream collector.

        Parameters
        ----------

        ktype: tuple
            Kernel event type.
        cpuid: int
            Indentifies the CPU core where the event
            has been captured.
        ts: str
            Temporal reference of the kernel event.
        kparams: dict
            Kernel event's parameters.
        """

        # initialize kernel event properties
        self.kevent.ts = ts
        self.kevent.cpuid = cpuid
        self.kevent.name = ktuple_to_name(ktype)
        kparams = ddict(kparams)

        # thread / process kernel events
        if ktype in [CREATE_PROCESS, CREATE_THREAD, ENUM_PROCESS, ENUM_THREAD]:
            self.thread_registry.add_thread(ktype, kparams)
            if ktype in [CREATE_PROCESS, CREATE_THREAD]:
                self.thread_registry.init_thread_kevent(
                    self.kevent, ktype, kparams)
                # apply yara binding by matching against the process's image path
                if ktype == CREATE_PROCESS:
                    yara_binding = self.__find_binding('yara')
                    pid = int(kparams.process_id, 16)
                    thread = self.thread_registry.get_thread(pid)
                    if thread and yara_binding:
                        yara_binding.run(thread_info=thread,
                                         kevent=self.kevent)
                self._aggregate(ktype)

        elif ktype in [TERMINATE_PROCESS, TERMINATE_THREAD]:
            self.thread_registry.init_thread_kevent(self.kevent, ktype,
                                                    kparams)
            self._aggregate(ktype)
            self.thread_registry.remove_thread(ktype, kparams)

        # file system/disk kernel events
        elif ktype in [
                CREATE_FILE, DELETE_FILE, CLOSE_FILE, READ_FILE, WRITE_FILE,
                RENAME_FILE, SET_FILE_INFORMATION
        ]:
            self.fsio.parse_fsio(ktype, kparams)
            self._aggregate(ktype)

        # dll kernel events
        elif ktype in [LOAD_IMAGE, ENUM_IMAGE]:
            self.dll_repository.register_dll(kparams)
            if ktype == LOAD_IMAGE:
                self._aggregate(ktype)
        elif ktype == UNLOAD_IMAGE:
            self.dll_repository.unregister_dll(kparams)
            self._aggregate(ktype)
        #
        # # registry kernel events
        elif ktype == REG_CREATE_KCB:
            self.hive_parser.add_kcb(kparams)
        elif ktype == REG_DELETE_KCB:
            self.hive_parser.remove_kcb(kparams.key_handle)

        elif ktype in [
                REG_CREATE_KEY, REG_DELETE_KEY, REG_OPEN_KEY, REG_QUERY_KEY,
                REG_SET_VALUE, REG_DELETE_VALUE, REG_QUERY_VALUE
        ]:
            self.hive_parser.parse_hive(ktype, kparams)
            self._aggregate(ktype)

        # network kernel events
        elif ktype in [
                SEND_SOCKET_TCPV4, SEND_SOCKET_UDPV4, RECV_SOCKET_TCPV4,
                RECV_SOCKET_UDPV4, ACCEPT_SOCKET_TCPV4, CONNECT_SOCKET_TCPV4,
                DISCONNECT_SOCKET_TCPV4, RECONNECT_SOCKET_TCPV4
        ]:
            self.tcpip_parser.parse_tcpip(ktype, kparams)
            self._aggregate(ktype)

        # context switch events
        elif ktype == CONTEXT_SWITCH:
            self.context_switch_registry.next_cswitch(cpuid, ts, kparams)
            self._aggregate(ktype)

        if self._filament:
            if ktype not in [
                    ENUM_PROCESS, ENUM_THREAD, ENUM_IMAGE, REG_CREATE_KCB,
                    REG_DELETE_KCB
            ]:
                ok = self.output_kevents[ktype] if ktype in self.output_kevents \
                    else False
                if self.kevent.name and ok:
                    thread = self.kevent.thread
                    kevent = {
                        'params': self.kevent.params,
                        'name': self.kevent.name,
                        'pid': self.kevent.pid,
                        'tid': self.kevent.tid,
                        'timestamp': self.kevent.ts,
                        'cpuid': self.kevent.cpuid,
                        'category': self.kevent.category
                    }
                    if thread:
                        kevent.update({
                            'thread': {
                                'name': thread.name,
                                'exe': thread.exe,
                                'comm': thread.comm,
                                'pid': thread.pid,
                                'ppid': thread.ppid
                            }
                        })
                    self._filament.on_next_kevent(kevent)
示例#24
0
    def _enum_handles(self, process_id=None):
        """Enumerates handle information.

        Enumerates handle info on
        the start of the kernel capture.

        Returns a dictionary of handle's
        information including the handle id,
        access mask, and the process which owns
        the handle.
        """
        buff_size = MAX_BUFFER_SIZE
        size = c_ulong()
        # allocate the initial buffer
        buff = malloc(buff_size)
        handles = {}

        while True:
            status = zw_query_system_information(
                SYSTEM_HANDLE_INFORMATION_CLASS, buff, buff_size, byref(size))
            if status == STATUS_INFO_LENGTH_MISMATCH:
                # the buffer is too small
                # increment the buffer size and try again
                buff_size += MAX_BUFFER_SIZE
            elif status == STATUS_SUCCESS:
                # cast the buffer to `SYSTEM_HANDLE_INFORMATION` struct
                # which contains an array of `SYSTEM_HANDLE` structures
                sys_handle_info = cast(buff,
                                       POINTER(SYSTEM_HANDLE_INFORMATION))
                sys_handle_info = sys_handle_info.contents
                handle_count = sys_handle_info.number_of_handles

                # resize the array size to the
                # actual number of file handles
                sys_handles = (SYSTEM_HANDLE * buff_size).from_address(
                    addressof(sys_handle_info.handles))

                for i in range(handle_count):
                    sys_handle = sys_handles[i]
                    pid = sys_handle.process_id
                    handle = sys_handle.handle
                    obj = sys_handle.object
                    obj_type_index = sys_handle.object_type_number
                    access_mask = sys_handle.access_mask
                    if process_id and process_id == pid:
                        handles[obj] = ddict(pid=process_id,
                                             handle=handle,
                                             obj=obj,
                                             access_mask=access_mask,
                                             obj_type_index=obj_type_index)
                    elif process_id is None:
                        handles[obj] = ddict(pid=pid,
                                             handle=handle,
                                             obj=obj,
                                             access_mask=access_mask,
                                             obj_type_index=obj_type_index)
                break
            else:
                raise HandleEnumError(status)
            # reallocate the buffer
            buff = realloc(buff, buff_size)
        # free the buffer memory
        free(buff)

        return handles
示例#25
0
 def on_next_kevent(self, kevent):
     try:
         self._filament_module.on_next_kevent(ddict(kevent))
     except Exception as e:
         self._logger.error('Unexpected filament error %s' % e)
示例#26
0
    def _on_next_kevent(self, ktype, cpuid, ts, kparams):
        """Callback which fires when new kernel event arrives.

        This callback is invoked for every new kernel event
        forwarded from the kernel stream collector.

        Parameters
        ----------

        ktype: tuple
            Kernel event type.
        cpuid: int
            Indentifies the CPU core where the event
            has been captured.
        ts: str
            Temporal reference of the kernel event.
        kparams: dict
            Kernel event's parameters.
        """

        # initialize kernel event properties
        self.kevent.ts = ts
        self.kevent.cpuid = cpuid
        self.kevent.name = ktuple_to_name(ktype)
        kparams = ddict(kparams)

        # thread / process kernel events
        if ktype in [CREATE_PROCESS,
                     CREATE_THREAD,
                     ENUM_PROCESS,
                     ENUM_THREAD]:
            self.thread_registry.add_thread(ktype, kparams)
            if ktype in [CREATE_PROCESS, CREATE_THREAD]:
                self.thread_registry.init_thread_kevent(self.kevent,
                                                        ktype,
                                                        kparams)
                # apply yara binding by matching against the process's image path
                if ktype == CREATE_PROCESS:
                    yara_binding = self.__find_binding('yara')
                    pid = int(kparams.process_id, 16)
                    thread = self.thread_registry.get_thread(pid)
                    if thread and yara_binding:
                        yara_binding.run(thread_info=thread,
                                         kevent=self.kevent)
                self._aggregate(ktype)

        elif ktype in [TERMINATE_PROCESS, TERMINATE_THREAD]:
            self.thread_registry.init_thread_kevent(self.kevent,
                                                    ktype,
                                                    kparams)
            self._aggregate(ktype)
            self.thread_registry.remove_thread(ktype, kparams)

        # file system/disk kernel events
        elif ktype in [CREATE_FILE,
                       DELETE_FILE,
                       CLOSE_FILE,
                       READ_FILE,
                       WRITE_FILE,
                       RENAME_FILE,
                       SET_FILE_INFORMATION]:
            self.fsio.parse_fsio(ktype, kparams)
            self._aggregate(ktype)

        # dll kernel events
        elif ktype in [LOAD_IMAGE, ENUM_IMAGE]:
            self.dll_repository.register_dll(kparams)
            if ktype == LOAD_IMAGE:
                self._aggregate(ktype)
        elif ktype == UNLOAD_IMAGE:
            self.dll_repository.unregister_dll(kparams)
            self._aggregate(ktype)
        #
        # # registry kernel events
        elif ktype == REG_CREATE_KCB:
            self.hive_parser.add_kcb(kparams)
        elif ktype == REG_DELETE_KCB:
            self.hive_parser.remove_kcb(kparams.key_handle)

        elif ktype in [REG_CREATE_KEY,
                       REG_DELETE_KEY,
                       REG_OPEN_KEY,
                       REG_QUERY_KEY,
                       REG_SET_VALUE,
                       REG_DELETE_VALUE,
                       REG_QUERY_VALUE]:
            self.hive_parser.parse_hive(ktype, kparams)
            self._aggregate(ktype)

        # network kernel events
        elif ktype in [SEND_SOCKET_TCPV4,
                       SEND_SOCKET_UDPV4,
                       RECV_SOCKET_TCPV4,
                       RECV_SOCKET_UDPV4,
                       ACCEPT_SOCKET_TCPV4,
                       CONNECT_SOCKET_TCPV4,
                       DISCONNECT_SOCKET_TCPV4,
                       RECONNECT_SOCKET_TCPV4]:
            self.tcpip_parser.parse_tcpip(ktype, kparams)
            self._aggregate(ktype)

        # context switch events
        elif ktype == CONTEXT_SWITCH:
            self.context_switch_registry.next_cswitch(cpuid, ts, kparams)
            self._aggregate(ktype)

        if self._filament:
            if ktype not in [ENUM_PROCESS,
                             ENUM_THREAD,
                             ENUM_IMAGE,
                             REG_CREATE_KCB,
                             REG_DELETE_KCB]:
                ok = self.output_kevents[ktype] if ktype in self.output_kevents \
                    else False
                if self.kevent.name and ok:
                    thread = self.kevent.thread
                    kevent = {
                        'params': self.kevent.params,
                        'name': self.kevent.name,
                        'pid': self.kevent.pid,
                        'tid': self.kevent.tid,
                        'timestamp': self.kevent.ts,
                        'cpuid': self.kevent.cpuid,
                        'category': self.kevent.category
                    }
                    if thread:
                        kevent.update({
                            'thread': {
                                'name': thread.name,
                                'exe': thread.exe,
                                'comm': thread.comm,
                                'pid': thread.pid,
                                'ppid': thread.ppid
                            }
                        })
                    self._filament.on_next_kevent(kevent)