def calculate(self):
     if self._config.PID:
         filter_pid = self._config.PID
         # This is so that when -p option is given it can still enumerate all processes to determine parent
         self._config.PID = None
     else:
         filter_pid = None
     ps = PSList(self._config)
     psdata = ps.calculate()
     self.update_proc_peb_info(psdata)
     proc_peb_info = self.get_proc_peb_info()
     self.update_parent_proc_info(proc_peb_info)
     parent_proc_info = self.get_parent_proc_info()
     self.update_proc_vad_info(proc_peb_info)
     proc_vad_info = self.get_proc_vad_info()
     if not filter_pid:
         for pid in proc_peb_info:
             similar_procs = self.get_similar_procs(pid)
             yield (proc_peb_info[pid], proc_vad_info[pid],
                    parent_proc_info[pid], similar_procs)
     else:
         for p in filter_pid.split(','):
             fil_pid = int(p)
             similar_procs = self.get_similar_procs(fil_pid)
             yield (proc_peb_info[fil_pid], proc_vad_info[fil_pid],
                    parent_proc_info[fil_pid], similar_procs)
Esempio n. 2
0
 def calculate(self):
     if self._config.PID:
         filter_pid = self._config.PID
         # This is so that when -p option is given it can still enumerate all processes to determine similar processes
         self._config.PID = None
     else:
         filter_pid = None
     ps = PSList(self._config)
     psdata = ps.calculate()
     self.update_proc_peb_info(psdata)
     proc_peb_info = self.get_proc_peb_info()
     self.update_parent_proc_info(proc_peb_info)
     parent_proc_info = self.get_parent_proc_info()
     self.update_proc_vad_info(proc_peb_info)
     hol_procs = self.detect_proc_hollow()
     proc_vad_info = self.get_proc_vad_info()  
     if hol_procs:
         for (hol_pid, hol_type) in hol_procs.items():
             similar_procs = self.get_similar_procs(hol_pid)
             if not filter_pid:
                 yield (proc_peb_info[hol_pid], 
                        proc_vad_info[hol_pid],
                        hol_pid, hol_type,
                        similar_procs,
                        parent_proc_info[hol_pid] )
             else:
                 for p in filter_pid.split(','):
                     fil_pid = int(p)
                     if int(fil_pid) == hol_pid:
                         yield (proc_peb_info[hol_pid],
                                proc_vad_info[hol_pid],
                                hol_pid, hol_type,
                                similar_procs,
                                parent_proc_info[hol_pid])
Esempio n. 3
0
 def calculate(self):
     if self._config.PID:
         filter_pid = self._config.PID
         # This is so that when -p option is given it can still enumerate all processes to determine parent
         self._config.PID = None
     else:
         filter_pid = None
     ps = PSList(self._config)
     psdata = ps.calculate()
     self.update_proc_peb_info(psdata)
     proc_peb_info = self.get_proc_peb_info()
     self.update_parent_proc_info(proc_peb_info)
     parent_proc_info = self.get_parent_proc_info()
     self.update_proc_vad_info(proc_peb_info)
     proc_vad_info = self.get_proc_vad_info()
     if not filter_pid:
         for pid in proc_peb_info:
             similar_procs = self.get_similar_procs(pid)
             yield(proc_peb_info[pid], proc_vad_info[pid], parent_proc_info[pid], similar_procs)
     else:
         for p in filter_pid.split(','):
             fil_pid = int(p)
             similar_procs = self.get_similar_procs(fil_pid)
             yield(proc_peb_info[fil_pid], proc_vad_info[fil_pid], parent_proc_info[fil_pid], similar_procs)
Esempio n. 4
0
    def calculate(self):

        # Get kernel modules
        self.kernel_modules = self.get_kernel_modules()

        # Get processes
        ps = PSList(self._config)
        psdata = ps.calculate()

        for proc in psdata:

            proc_addr_space = proc.get_process_address_space()
            thread_points_to_proc_image = False
            suspicious_thread_in_process = False
            threads_for_process = []
            proc_name = self.get_proc_name(proc, proc_addr_space)
            threats_in_proc = []

            # Skip terminated processes when verbose is off
            if proc.ProcessDelete.v() != 0 and proc.ProcessExiting != 0 \
                and not self._config.verbose:
                continue

            # Get vads for process
            self.proc_vads = self.get_vad_for_process(proc)

            # Check every thread from given process
            for thread in self.get_threads_for_process(proc):

                # Create a new thread
                thread = ThreadFindings(thread)
                thread_entry_point = thread.struct.Win32StartAddress

                in_vad_range = self.check_where_in_vad(thread_entry_point)

                # Check if the thread points to a kernel module
                if not in_vad_range:

                    at_kernel_module = self.check_where_in_kernel(thread_entry_point)

                    # Thread is not at kernel space
                    if at_kernel_module:
                        module_name, module_start_addr = at_kernel_module
                        thread.add_location_in_kernel(module_name, module_start_addr)
                        threads_for_process.append(thread)
                    else:
                        thread.no_location = True
                        threads_for_process.append(thread)

                else:

                    vad, vad_addr_space = in_vad_range
                    thread.add_location_in_vad(vad)

                    # Found a thread is mapped to vad without a file object
                    if not thread.file_object_name:
                        thread.reason.append(THREAD_THREATS["Thread Without File Object"])
                        suspicious_thread_in_process = True

                        # Add reason only once
                        if THREAD_THREATS["Thread Without File Object"] \
                                not in threats_in_proc:
                            threats_in_proc.append(THREAD_THREATS["Thread Without File Object"])

                    else:

                        # Found a thread that is pointing to the vad that contains
                        # the process's legitimate image file
                        if thread.file_object_name in proc_name:
                            thread_points_to_proc_image = PROCESS_MESSAGES["Points to Process Image"]

                            wait_reason = int(thread.struct.Tcb.WaitReason)
                            state = int(thread.struct.Tcb.State)

                            # Check if the file object thread is suspended
                            if state == WAIT and wait_reason == SUSPEND:
                                thread_points_to_proc_image = PROCESS_MESSAGES["Thread Suspended"]

                        else:

                            # Found a thread is mapped to a vad that contains an
                            # exe file object that is different from the loaded process's image file
                            if thread.file_object_name.split(".")[-1].lower() == "exe":
                                thread.reason.append(THREAD_THREATS["Different EXE"])
                                suspicious_thread_in_process = True

                                # Add reason only once
                                if THREAD_THREATS["Different EXE"] not in threats_in_proc:
                                    threats_in_proc.append(THREAD_THREATS["Different EXE"])

                        # Check if the vad is mapped to an image file
                        if vad.u.VadFlags.VadType.v() != IMAGE_FILE_TYPE:
                            suspicious_thread_in_process = True

                            # Add the reason only once
                            if THREAD_THREATS["PE that isn't Image File"] not in threats_in_proc:
                                threats_in_proc.append(THREAD_THREATS["PE that isn't Image File"])

                    # Check for suspicious jumps only for threads that are not in kernel mode
                    if thread.mapped_to_vad:

                        self.check_for_jmp(thread, proc, proc_addr_space)

                        # A suspicious JMP/CALL is found within the thread
                        if thread.jmp_data:
                            suspicious_thread_in_process = True

                            # Add suspicious jump/call message to process only once
                            if THREAD_THREATS["Suspicious JMP"] not in threats_in_proc:
                                threats_in_proc.append(THREAD_THREATS["Suspicious JMP"])

                            thread.reason.append(THREAD_THREATS["Suspicious JMP"])

                    threads_for_process.append(thread)

            yield (proc, threads_for_process,
                   thread_points_to_proc_image,
                   suspicious_thread_in_process)
    def calculate(self):

        # Get kernel modules
        self.kernel_modules = self.get_kernel_modules()

        # Get processes
        ps = PSList(self._config)
        psdata = ps.calculate()

        for proc in psdata:

            proc_addr_space = proc.get_process_address_space()
            thread_points_to_proc_image = False
            suspicious_thread_in_process = False
            threads_for_process = []
            proc_name = self.get_proc_name(proc, proc_addr_space)
            threats_in_proc = []

            # Skip terminated processes when verbose is off
            if proc.ProcessDelete.v() != 0 and proc.ProcessExiting != 0 \
                and not self._config.verbose:
                continue

            # Get vads for process
            self.proc_vads = self.get_vad_for_process(proc)

            # Check every thread from given process
            for thread in self.get_threads_for_process(proc):

                # Create a new thread
                thread = ThreadFindings(thread)
                thread_entry_point = thread.struct.Win32StartAddress

                in_vad_range = self.check_where_in_vad(thread_entry_point)

                # Check if the thread points to a kernel module
                if not in_vad_range:

                    at_kernel_module = self.check_where_in_kernel(thread_entry_point)

                    # Thread is not at kernel space
                    if at_kernel_module:
                        module_name, module_start_addr = at_kernel_module
                        thread.add_location_in_kernel(module_name, module_start_addr)
                        threads_for_process.append(thread)
                    else:
                        print "Process", proc.UniqueProcessId, proc.ImageFileName, "Thread", hex(thread_entry_point)
                        thread.no_location = True
                        threads_for_process.append(thread)

                else:

                    vad, vad_addr_space = in_vad_range
                    thread.add_location_in_vad(vad)

                    # Found a thread is mapped to vad without a file object
                    if not thread.file_object_name:
                        thread.reason.append(THREAD_THREATS["Thread Without File Object"])
                        suspicious_thread_in_process = True

                        # Add reason only once
                        if THREAD_THREATS["Thread Without File Object"] \
                                not in threats_in_proc:
                            threats_in_proc.append(THREAD_THREATS["Thread Without File Object"])

                    else:

                        # Found a thread that is pointing to the vad that contains
                        # the process's legitimate image file
                        if thread.file_object_name in proc_name:
                            thread_points_to_proc_image = PROCESS_MESSAGES["Points to Process Image"]

                            wait_reason = int(thread.struct.Tcb.WaitReason)
                            state = int(thread.struct.Tcb.State)

                            # Check if the file object thread is suspended
                            if state == WAIT and wait_reason == SUSPEND:
                                thread_points_to_proc_image = PROCESS_MESSAGES["Thread Suspended"]

                        else:

                            # Found a thread is mapped to a vad that contains an
                            # exe file object that is different from the loaded process's image file
                            if thread.file_object_name.split(".")[-1].lower() == "exe":
                                thread.reason.append(THREAD_THREATS["Different EXE"])
                                suspicious_thread_in_process = True

                                # Add reason only once
                                if THREAD_THREATS["Different EXE"] not in threats_in_proc:
                                    threats_in_proc.append(THREAD_THREATS["Different EXE"])

                        # Check if the vad is mapped to an image file
                        if vad.u.VadFlags.VadType.v() != IMAGE_FILE_TYPE:
                            suspicious_thread_in_process = True

                            # Add the reason only once
                            if THREAD_THREATS["PE that isn't Image File"] not in threats_in_proc:
                                threats_in_proc.append(THREAD_THREATS["PE that isn't Image File"])

                    # Check for suspicious jumps only for threads that are not in kernel mode
                    if thread.mapped_to_vad:

                        self.check_for_jmp(thread, proc, proc_addr_space)

                        # A suspicious JMP/CALL is found within the thread
                        if thread.jmp_data:
                            suspicious_thread_in_process = True

                            # Add suspicious jump/call message to process only once
                            if THREAD_THREATS["Suspicious JMP"] not in threats_in_proc:
                                threats_in_proc.append(THREAD_THREATS["Suspicious JMP"])

                            thread.reason.append(THREAD_THREATS["Suspicious JMP"])

                    threads_for_process.append(thread)

            yield (proc, threads_for_process,
                   thread_points_to_proc_image,
                   suspicious_thread_in_process)
Esempio n. 6
0
    def calculate(self):

        # Get processes
        ps = PSList(self._config)
        psdata = ps.calculate()

        for proc in psdata:

            # get address space
            proc_addr_space = proc.get_process_address_space()
            suspicious_threads = []

            proc_token = proc.get_token()
            sus_reason = ""

            # Impersonate creation
            if self._config.DETECT_CTRATION:
                if proc.Job != 0 and proc.CrossSessionCreate == 1 and proc.OverrideAddressSpace == 0 and proc.WriteWatch == 0:
                    sus_reason += "\tImpersonate Process Creation Detected \n"

            process_elevated = self.get_elevated_info(proc_token.TokenFlags)

            # checks the select users option
            if self._config.SELECT_USERS:
                users = self._config.SELECT_USERS.split(",")
                proc_full_username = "******".format(
                    proc_token.LogonSession.AuthorityName,
                    proc_token.LogonSession.AccountName)

                # only selected users
                if proc_full_username not in users:
                    continue

            for thread in self.get_threads_for_process(proc):

                imp_token = thread.ClientSecurity.ImpersonationToken

                if imp_token:
                    token_offset = thread.ClientSecurity.ImpersonationToken - thread.ClientSecurity.ImpersonationLevel
                    thread_token = obj.Object("_TOKEN", token_offset,
                                              proc_addr_space)

                    # validation
                    if thread_token.v() != 0 and thread_token.is_valid() and \
                       thread_token.TokenInUse == 0 and bin(thread.CrossThreadFlags.v())[2:][::-1][3] == "1":

                        # second validation
                        if thread_token.LogonSession.AuthorityName:

                            # get elevated info
                            elevated = self.get_elevated_info(
                                thread_token.TokenFlags)


                            if self._config.verbose or \
                            elevated != process_elevated or \
                            proc_token.LogonSession.AuthorityName != thread_token.LogonSession.AuthorityName or \
                            proc_token.LogonSession.AccountName != thread_token.LogonSession.AccountName:

                                # non suspicious impersonation
                                if elevated == process_elevated and \
                                proc_token.LogonSession.AuthorityName == thread_token.LogonSession.AuthorityName or \
                                proc_token.LogonSession.AccountName == thread_token.LogonSession.AccountName:
                                    sus_flag = False
                                else:
                                    sus_flag = True

                                suspicious_threads.append(
                                    (thread_token.LogonSession.AuthorityName,
                                     thread_token.LogonSession.AccountName,
                                     "".join(
                                         chr(i) for i in
                                         thread_token.TokenSource.SourceName),
                                     thread.Cid.UniqueThread, elevated))

            #suspicious threads
            if suspicious_threads:

                if sus_flag:
                    sus_reason += "\tActive Impersonated Thread(s) With Differnet Token(s) found \n"
                else:
                    sus_reason += "\tNon suspicious impersonation detected (verbose mode)\n"

            # verbose option
            if self._config.verbose:
                sus_reason += "\tVerbose Mode\n"

            if sus_reason:
                yield proc, sus_reason, suspicious_threads