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)
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])
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)
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)
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