Пример #1
0
    def render(self):
        """Renders the kevent to standard output stream.

        Uses the default output format to render the
        kernel event to standard output stream.

        The default output format is as follows:

        id  timestamp  cpu  process  (process id) - kevent (parameters)
        --  ---------  ---  -------  -----------   ------- ------------

        Example:

        160 13:27:27.554 0 wmiprvse.exe (1012) - CloseFile (file=C:\\WINDOWS\\SYSTEM32\\RSAENH.DLL, tid=2668)

        """
        self._thread = self.thread
        if self._thread:
            kevt = RENDER_FORMAT % (self._id,
                                    self._ts.time(),
                                    self._cpuid,
                                    self._thread.name,
                                    self._thread.pid,
                                    self._name,
                                    self._format_params())
        else:
            # figure out the process id from thread
            # if the process can't be found in
            # thread registry
            pid = NA
            if self._pid is None:
                if self._tid:
                    # get the thread handle
                    handle = open_thread(THREAD_QUERY_INFORMATION,
                                         False,
                                         self._tid)
                    if handle:
                        pid = get_process_id_of_thread(handle)
                        close_handle(handle)
            else:
                pid = self._pid
            kevt = RENDER_FORMAT % (self._id,
                                    self._ts.time(),
                                    self._cpuid,
                                    NA,
                                    pid,
                                    self._name,
                                    self._format_params())
        IO.write_console(kevt)
        self._id += 1
Пример #2
0
    def render(self):
        """Renders the kevent to standard output stream.

        Uses the default output format to render the
        kernel event to standard output stream.

        The default output format is as follows:

        id  timestamp  cpu  process  (process id) - kevent (parameters)
        --  ---------  ---  -------  -----------   ------- ------------

        Example:

        160 13:27:27.554 0 wmiprvse.exe (1012) - CloseFile (file=C:\\WINDOWS\\SYSTEM32\\RSAENH.DLL, tid=2668)

        """
        self._thread = self.thread
        if self._thread:
            kevt = RENDER_FORMAT % (self._id,
                                    self._ts.time(),
                                    self._cpuid,
                                    self._thread.name,
                                    self._thread.pid,
                                    self._name,
                                    self._format_params())
        else:
            # figure out the process id from thread
            # if the process can't be found in
            # thread registry
            pid = NA
            if self._pid is None:
                if self._tid:
                    # get the thread handle
                    handle = open_thread(THREAD_QUERY_INFORMATION,
                                         False,
                                         self._tid)
                    if handle:
                        pid = get_process_id_of_thread(handle)
                        close_handle(handle)
            else:
                pid = self._pid
            kevt = RENDER_FORMAT % (self._id,
                                    self._ts.time(),
                                    self._cpuid,
                                    NA,
                                    pid,
                                    self._name,
                                    self._format_params())
        IO.write_console(kevt)
        self._id += 1
Пример #3
0
    def query_handles(self, pid=None):
        raw_handles = self._enum_handles(pid)
        current_ps = HANDLE(get_current_process())
        handles = []
        # find the object handles for the process
        for _, handle in raw_handles.items():
            ps_handle = open_process(PROCESS_DUP_HANDLE,
                                     False,
                                     handle.pid)
            if ps_handle:
                handle_copy = HANDLE()
                # to query the object handle
                # we need to duplicate it in
                # the address space of the current process
                status = duplicate_handle(ps_handle,
                                          handle.handle,
                                          current_ps,
                                          byref(handle_copy),
                                          0, 0, 0)
                if status != ERROR_SUCCESS:
                    # get the object type
                    handle_type = self._query_handle(handle_copy,
                                                     PUBLIC_OBJECT_TYPE_INFORMATION,
                                                     OBJECT_TYPE_INFORMATION)
                    if handle_type:
                        handle_type = cast(handle_type.contents.type_name.buffer, c_wchar_p) \
                            .value \
                            .upper().replace(' ', '_')
                        # query for object name
                        # (file names, registry keys,
                        # sections, ALPC ports, etc)
                        # check the access mask to make
                        # sure `NtQueryObject` won't hang
                        if handle_type in self._handle_types and \
                                handle.access_mask not in self._nasty_access_masks:
                            handle_name = self._query_handle(handle_copy,
                                                             PUBLIC_OBJECT_NAME_INFORMATION,
                                                             UNICODE_STRING)
                            if handle_name:
                                handle_name = cast(handle_name.contents.buffer, c_wchar_p).value
                            handle_info = HandleInfo(handle.handle,
                                                     handle.obj,
                                                     HandleType(HandleType.__getattr__(handle_type)),
                                                     handle_name,
                                                     handle.pid)
                            handles.append(handle_info)

                    close_handle(handle_copy)
                close_handle(ps_handle)
        return handles
Пример #4
0
    def query_handles(self, pid=None):
        raw_handles = self._enum_handles(pid)
        current_ps = HANDLE(get_current_process())
        handles = []
        # find the object handles for the process
        for _, handle in raw_handles.items():
            ps_handle = open_process(PROCESS_DUP_HANDLE, False, handle.pid)
            if ps_handle:
                handle_copy = HANDLE()
                # to query the object handle
                # we need to duplicate it in
                # the address space of the current process
                status = duplicate_handle(ps_handle, handle.handle, current_ps,
                                          byref(handle_copy), 0, 0, 0)
                if status != ERROR_SUCCESS:
                    # get the object type
                    handle_type = self._query_handle(
                        handle_copy, PUBLIC_OBJECT_TYPE_INFORMATION,
                        OBJECT_TYPE_INFORMATION)
                    if handle_type:
                        handle_type = cast(handle_type.contents.type_name.buffer, c_wchar_p) \
                            .value \
                            .upper().replace(' ', '_')
                        # query for object name
                        # (file names, registry keys,
                        # sections, ALPC ports, etc)
                        # check the access mask to make
                        # sure `NtQueryObject` won't hang
                        if handle_type in self._handle_types and \
                                handle.access_mask not in self._nasty_access_masks:
                            handle_name = self._query_handle(
                                handle_copy, PUBLIC_OBJECT_NAME_INFORMATION,
                                UNICODE_STRING)
                            if handle_name:
                                handle_name = cast(handle_name.contents.buffer,
                                                   c_wchar_p).value
                            handle_info = HandleInfo(
                                handle.handle, handle.obj,
                                HandleType(
                                    HandleType.__getattr__(handle_type)),
                                handle_name, handle.pid)
                            handles.append(handle_info)

                    close_handle(handle_copy)
                close_handle(ps_handle)
        return handles
Пример #5
0
    def _get_proc(self, thread_id):
        handle = open_thread(THREAD_QUERY_INFORMATION, False, thread_id)

        if handle:
            # if it was possible to get the process id
            # which is the parent of the thread, we can
            # try to get the process name from its pid
            pid = get_process_id_of_thread(handle)
            close_handle(handle)
            handle = open_process(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                                  False, pid)
            if handle:
                exe = ctypes.create_unicode_buffer(MAX_PATH)
                status = query_full_process_image_name(handle, 0, exe,
                                                       DWORD(MAX_PATH))
                close_handle(handle)
                if status:
                    return os.path.basename(exe.value)
Пример #6
0
    def _get_proc(self, thread_id):
        handle = open_thread(THREAD_QUERY_INFORMATION,
                             False,
                             thread_id)

        if handle:
            # if it was possible to get the process id
            # which is the parent of the thread, we can
            # try to get the process name from its pid
            pid = get_process_id_of_thread(handle)
            close_handle(handle)
            handle = open_process(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                                  False,
                                  pid)
            if handle:
                exe = ctypes.create_unicode_buffer(MAX_PATH)
                status = query_full_process_image_name(handle, 0,
                                                       exe, DWORD(MAX_PATH))
                close_handle(handle)
                if status:
                    return os.path.basename(exe.value)
Пример #7
0
 def get_thread(self):
     """Gets the thread associated with the kernel event.
     """
     thread = self._find_thread()
     if thread:
         return thread.pid, thread.name
     else:
         # figure out the process id from thread
         # if the process can't be found in
         # the thread registry
         pid = NA
         if self._pid is None:
             if self._tid:
                 # get the thread handle
                 handle = open_thread(THREAD_QUERY_INFORMATION, False,
                                      self._tid)
                 if handle:
                     pid = get_process_id_of_thread(handle)
                     close_handle(handle)
         else:
             pid = self._pid
         return pid, NA
Пример #8
0
 def get_thread(self):
     """Gets the thread associated with the kernel event.
     """
     thread = self._find_thread()
     if thread:
         return thread.pid, thread.name
     else:
         # figure out the process id from thread
         # if the process can't be found in
         # the thread registry
         pid = NA
         if self._pid is None:
             if self._tid:
                 # get the thread handle
                 handle = open_thread(THREAD_QUERY_INFORMATION,
                                      False,
                                      self._tid)
                 if handle:
                     pid = get_process_id_of_thread(handle)
                     close_handle(handle)
         else:
             pid = self._pid
         return pid, NA
Пример #9
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)
Пример #10
0
 def __del__(self):
     if self._stdout_handle:
         close_handle(self._stdout_handle)
Пример #11
0
 def __del__(self):
     if self._stdout_handle:
         close_handle(self._stdout_handle)
Пример #12
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)