def LockWorkStation(self): try: logging.debug("LockWorkStation was called.") sessionId = GetActiveSessionId() if sessionId != 0xffffffff: logging.debug("Locking workstation (session %d)", sessionId) dupToken = None userToken = win32ts.WTSQueryUserToken(sessionId) if userToken is not None: logging.debug("Got the active user token.") # The following access rights are required for # CreateProcessAsUser. access = win32security.TOKEN_QUERY access |= win32security.TOKEN_DUPLICATE access |= win32security.TOKEN_ASSIGN_PRIMARY dupToken = win32security.DuplicateTokenEx( userToken, win32security.SecurityImpersonation, access, win32security.TokenPrimary, None) userToken.Close() if dupToken is not None: logging.debug("Duplicated the active user token.") lockCmd = os.path.join(os.environ['WINDIR'], "system32\\rundll32.exe") lockCmd += " user32.dll,LockWorkStation" logging.debug("Executing \"%s\".", lockCmd) win32process.CreateProcessAsUser( dupToken, None, lockCmd, None, None, 0, 0, None, None, win32process.STARTUPINFO()) dupToken.Close() else: logging.debug("No active session. Ignoring lock workstation " "command.") except: logging.exception("LockWorkStation exception")
def CreateProcess(*args): startupinfo = args[-1] # If we are passed a LoginSTARTUPINFO, that means we need to use # CreateProcessAsUser instead of the CreateProcess in subprocess if isinstance(startupinfo, LoginSTARTUPINFO): # Gets the actual win32 STARTUPINFO object from LoginSTARTUPINFO win32startupinfo = startupinfo.win32startupinfo mkprocargs = args[:-1] + (win32startupinfo, ) login, domain, password = startupinfo.credentials # Get a user handle from the credentials userhandle = win32security.LogonUser( login, domain, password, win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT) try: # Return the pipes from CreateProcessAsUser return win32process.CreateProcessAsUser(userhandle, *mkprocargs) finally: # Close the userhandle before throwing whatever error arises userhandle.Close() return win32process.CreateProcess(*args)
def shell_as(th, enable_privs=0): t = thread(th) print t.as_text() new_tokenh = win32security.DuplicateTokenEx( th, 3, win32con.MAXIMUM_ALLOWED, win32security.TokenPrimary, win32security.SECURITY_ATTRIBUTES()) print "new_tokenh: %s" % new_tokenh print "Impersonating..." if enable_privs: get_all_privs(new_tokenh) commandLine = "cmd" si = win32process.STARTUPINFO() print "pysecdump: Starting shell with required privileges..." (hProcess, hThread, dwProcessId, dwThreadId) = win32process.CreateProcessAsUser( new_tokenh, None, # AppName commandLine, # Command line None, # Process Security None, # ThreadSecurity 1, # Inherit Handles? win32process.NORMAL_PRIORITY_CLASS, None, # New environment None, # Current directory si) # startup info. win32event.WaitForSingleObject(hProcess, win32event.INFINITE) print "pysecdump: Quitting"
def create_print_process(self): session_id = win32ts.WTSGetActiveConsoleSessionId() user_token = win32ts.WTSQueryUserToken(session_id) startup_info = win32process.STARTUPINFO() cmdline = "E:\\python_project\\happyWorkAutoPrint\\dist\\autoPrint\\autoPrint.exe" win32process.CreateProcessAsUser(user_token, None, cmdline, None, None, False, win32con.NORMAL_PRIORITY_CLASS, None, None, startup_info)
def main(self): #my_app_path = 'C:\\Windows\\System32\\cmd.exe' my_app_path = r'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' startup = win32process.STARTUPINFO() priority = win32con.NORMAL_PRIORITY_CLASS console_user_token = getusertoken() environment = win32profile.CreateEnvironmentBlock( console_user_token, False) handle, thread_id, pid, tid = win32process.CreateProcessAsUser( console_user_token, my_app_path, None, None, None, True, priority, environment, None, startup)
def run_as(self, command): # Importing these only on windows, as they won't exist on linux. import win32con import win32process import win32api import win32event exit_code = -1 process_handle = None thread_handle = None try: # Open process as that user: # https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera process_handle, thread_handle, _, _ = win32process.CreateProcessAsUser( self.get_logon_handle( ), # A handle to the primary token that represents a user. None, # The name of the module to be executed. command, # The command line to be executed. None, # Process attributes None, # Thread attributes True, # Should inherit handles win32con. NORMAL_PRIORITY_CLASS, # The priority class and the creation of the process. None, # An environment block for the new process. If this parameter is NULL, the new process # uses the environment of the calling process. None, # CWD. If this parameter is NULL, the new process will have the same current drive and # directory as the calling process. win32process.STARTUPINFO() # STARTUPINFO structure. # https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa ) logger.debug("Waiting for process to finish. Timeout: {}ms".format( WAIT_TIMEOUT_IN_MILLISECONDS)) # Ignoring return code, as we'll use `GetExitCode` to determine the state of the process later. _ = win32event.WaitForSingleObject( # Waits until the specified object is signaled, or time-out. process_handle, # Ping process handle WAIT_TIMEOUT_IN_MILLISECONDS # Timeout in milliseconds ) exit_code = win32process.GetExitCodeProcess(process_handle) finally: try: if process_handle is not None: win32api.CloseHandle(process_handle) if thread_handle is not None: win32api.CloseHandle(thread_handle) except Exception as err: logger.error("Close handle error: " + str(err)) return exit_code
def StartAgent(): #pythonw (run in background) my_app_path = r'C:\Users\Mathieu\AppData\Local\Programs\Python\Python37-32\pythonw.exe' #my_app_path = r'C:\Windows\System32\cmd.exe' startup = win32process.STARTUPINFO() priority = win32con.NORMAL_PRIORITY_CLASS console_user_token = getusertoken() environment = win32profile.CreateEnvironmentBlock(console_user_token, False) handle, thread_id ,pid, tid = win32process.CreateProcessAsUser(console_user_token, my_app_path, r' C:\git\WebsocketShelling\shell-pwned.py', None, None, True, priority, environment, None, startup) return pid
def run_as_cur_user(process, args): session_id = windll.kernel32.WTSGetActiveConsoleSessionId() token = win32ts.WTSQueryUserToken(session_id) win32process.CreateProcessAsUser( token, process, args, None, None, True, win32con.NORMAL_PRIORITY_CLASS, None, None, win32process.STARTUPINFO())
def runProcessInteractWithUser(self): hToken = win32security.OpenProcessToken( win32api.GetCurrentProcess(), win32con.TOKEN_DUPLICATE | win32con.TOKEN_ADJUST_DEFAULT | win32con.TOKEN_QUERY | win32con.TOKEN_ASSIGN_PRIMARY) hNewToken = win32security.DuplicateTokenEx( hToken, win32security.SecurityImpersonation, win32security.TOKEN_ALL_ACCESS, win32security.TokenPrimary) # Create sid level sessionId = win32ts.WTSGetActiveConsoleSessionId() win32security.SetTokenInformation(hNewToken, win32security.TokenSessionId, sessionId) priority = win32con.NORMAL_PRIORITY_CLASS | win32con.CREATE_NEW_CONSOLE startup = win32process.STARTUPINFO() handle, thread_id, pid, tid = win32process.CreateProcessAsUser( hNewToken, self.filePath, None, None, None, False, priority, None, None, startup)
def run_os_command_impersonated(cmd, user, password, domain='.'): si = win32process.STARTUPINFO() out_handle, err_handle, out_file, err_file = _create_tmp_files() ok, si.hStdInput = _safe_duplicate_handle( win32api.GetStdHandle(win32api.STD_INPUT_HANDLE)) if not ok: raise Exception("Unable to create StdInput for child process") ok, si.hStdOutput = _safe_duplicate_handle(out_handle) if not ok: raise Exception("Unable to create StdOut for child process") ok, si.hStdError = _safe_duplicate_handle(err_handle) if not ok: raise Exception("Unable to create StdErr for child process") si.dwFlags = win32process.STARTF_USESTDHANDLES si.lpDesktop = "" user_token = win32security.LogonUser(user, domain, password, win32con.LOGON32_LOGON_SERVICE, win32con.LOGON32_PROVIDER_DEFAULT) primary_token = win32security.DuplicateTokenEx( user_token, win32security.SecurityImpersonation, 0, win32security.TokenPrimary) info = win32process.CreateProcessAsUser(primary_token, None, cmd, None, None, 1, 0, None, None, si) hProcess, hThread, dwProcessId, dwThreadId = info hThread.Close() try: win32event.WaitForSingleObject(hProcess, win32event.INFINITE) except KeyboardInterrupt: pass out, err = _get_files_output(out_file, err_file) exitcode = win32process.GetExitCodeProcess(hProcess) return exitcode, out, err
def runas_session_user(cmd, executable=None, creationflags=0, cwd=None, startupinfo=None, return_handles=False): if not creationflags & win32con.DETACHED_PROCESS: creationflags |= win32con.CREATE_NEW_CONSOLE if cwd is None: cwd = os.getcwd() si = win32process.STARTUPINFO() if startupinfo: startupinfo_update(startupinfo, si) with impersonate_system(): htoken_user = win32ts.WTSQueryUserToken(win32ts.WTS_CURRENT_SESSION) hProcess, hThread, dwProcessId, dwThreadId = ( win32process.CreateProcessAsUser(htoken_user, executable, cmd, None, None, False, creationflags, None, cwd, si)) if return_handles: return hProcess, hThread return dwProcessId, dwThreadId
def _safeCreateProcess(avatar, appName, cmd, processSA, threadSA, inheritHandles, creationFlags, env, cwd, si): new_env = {} if env is not None: for key, value in env.iteritems(): new_env[unicode(key)] = unicode(value) env = new_env log.debug( """\ _SaferCreateProcess(appName=%r, cmd=%r, env=%r, cwd=%r) os.getcwd(): %r """, appName, cmd, env, cwd, os.getcwd()) si.lpDesktop = r"winsta0\default" params = (appName, cmd, processSA, threadSA, inheritHandles, creationFlags, env, cwd, si) # If we have been given an avatar with credentials, create the # process as the identified user. if avatar is not None and avatar.mUserHandle is not None: # Run the command ase the authenticated user. user = avatar.mUserHandle win32security.ImpersonateLoggedOnUser(user) process, thread, process_id, thread_id\ = win32process.CreateProcessAsUser(user, *params) win32security.RevertToSelf() else: process, thread, process_id, thread_id\ = win32process.CreateProcess(*params) return process, thread, process_id, thread_id
self.process.run() def main(self): app.debug = True # Product WSGI server "waitress" #serve(app, host='127.0.0.1', port='5000') #serve(app, host='0.0.0.0', port='5000') app.run() if __name__ == '__main__': # First create a token. We're pretending this user actually exists on your local computer or Active Directory domain. user = "******" pword = "password" domain = "." # means current domain logontype = win32con.LOGON32_LOGON_INTERACTIVE #logontype = win32con.LOGON32_LOGON_NEW_CREDENTIALS #provider = win32con.LOGON32_PROVIDER_WINNT50 provider = 0 #provider = win32con.LOGON32_LOGON_NEW_CREDENTIALS token = win32security.LogonUser(user, domain, pword, logontype, provider) # Now let's create the STARTUPINFO structure. Read the link above for more info on what these can do. startup = win32process.STARTUPINFO() # Finally, create a cmd.exe process using the "ltorvalds" token. appname = "c:\\windows\\system32\\cmd.exe" priority = win32con.NORMAL_PRIORITY_CLASS win32process.CreateProcessAsUser(token, appname, None, None, None, True, priority, None, None, startup) win32serviceutil.HandleCommandLine(Service)
def main(self, token): connection = Connection('localhost', port=5672) connection.open() session = connection.session(str(uuid4())) receiver = session.receiver('amq.topic') local_ip = socket.gethostbyname(socket.gethostname()) localhost_name = platform.uname()[1] def make_inheritable(token): """Return a duplicate of handle, which is inheritable""" return win32api.DuplicateHandle(win32api.GetCurrentProcess(), token, win32api.GetCurrentProcess(), 0, 1, win32con.DUPLICATE_SAME_ACCESS) while True: message = receiver.fetch() session.acknowledge() sender = session.sender(message.reply_to) command = base64.b64decode(message.content) if command.startswith('winrs' or 'winrm') != True or command.find( '-r:' ) == -1 or command.find('localhost') != -1 or command.find( localhost_name) != -1 or command.find(local_ip) != -1: sender.send( Message( base64.b64encode( 'Commands against the proxy are not accepted'))) else: #Start the process: # First let's create the communication pipes used by the process # we need to have the pipes inherit the rights from token stdin_read, stdin_write = win32pipe.CreatePipe(None, 0) stdin_read = make_inheritable(stdin_read) stdout_read, stdout_write = win32pipe.CreatePipe(None, 0) stdout_write = make_inheritable(stdout_write) stderr_read, stderr_write = win32pipe.CreatePipe(None, 0) stderr_write = make_inheritable(stderr_write) # Set start-up parameters the process will use. #Here we specify the pipes for input, output and error. si = win32process.STARTUPINFO() si.dwFlags = win32con.STARTF_USESTDHANDLES si.hStdInput = stdin_read si.hStdOutput = stdout_write si.hStdError = stderr_write procArgs = ( None, # appName command, # commandLine None, # processAttributes None, # threadAttributes 1, # bInheritHandles 0, # dwCreationFlags None, # newEnvironment None, # currentDirectory si) # startupinfo # CreateProcessAsUser takes the first parameter the token, # this way the process will impersonate a user try: hProcess, hThread, PId, TId = win32process.CreateProcessAsUser( token, *procArgs) hThread.Close() if stdin_read is not None: stdin_read.Close() if stdout_write is not None: stdout_write.Close() if stderr_write is not None: stderr_write.Close() stdin_write = msvcrt.open_osfhandle( stdin_write.Detach(), 0) stdout_read = msvcrt.open_osfhandle( stdout_read.Detach(), 0) stderr_read = msvcrt.open_osfhandle( stderr_read.Detach(), 0) stdin_file = os.fdopen(stdin_write, 'wb', 0) stdout_file = os.fdopen(stdout_read, 'rU', 0) stderr_file = os.fdopen(stderr_read, 'rU', 0) def readerthread(fh, buffer): buffer.append(fh.read()) def translate_newlines(data): data = data.replace("\r\n", "\n") data = data.replace("\r", "\n") return data def wait(): """Wait for child process to terminate. Returns returncode attribute.""" win32event.WaitForSingleObject(hProcess, win32event.INFINITE) returncode = win32process.GetExitCodeProcess(hProcess) return returncode def communicate(): if stdout_file: stdout = [] stdout_thread = threading.Thread( target=readerthread, args=(stdout_file, stdout)) stdout_thread.setDaemon(True) stdout_thread.start() if stderr_file: stderr = [] stderr_thread = threading.Thread( target=readerthread, args=(stderr_file, stderr)) stderr_thread.setDaemon(True) stderr_thread.start() stdin_file.close() if stdout_file: stdout_thread.join() if stderr_file: stderr_thread.join() if stdout is not None: stdout = stdout[0] if stderr is not None: stderr = stderr[0] if stdout: stdout = translate_newlines(stdout) if stderr: stderr = translate_newlines(stderr) return_code = wait() return (stdout, stderr, return_code) ret_stdout, ret_stderr, retcode = communicate() result = Message(base64.b64encode(str(ret_stdout))) result.properties["retcode"] = base64.b64encode( str(retcode)) if ret_stderr: result.properties["stderr"] = base64.b64encode( str(ret_stderr)) else: result.properties["stderr"] = base64.b64encode('') sender.send(result) except Exception as exception_message: result = Message(base64.b64encode('')) result.properties["retcode"] = base64.b64encode( str(exception_message[0])) result.properties["stderr"] = base64.b64encode( str(exception_message[2])) sender.send(result)
def __init__(self, cmd, login=None, hStdin=None, hStdout=None, hStderr=None, show=1, xy=None, xySize=None, desktop=None): """ Create a Windows process. cmd: command to run login: run as user 'Domain\nUser\nPassword' hStdin, hStdout, hStderr: handles for process I/O; default is caller's stdin, stdout & stderr show: wShowWindow (0=SW_HIDE, 1=SW_NORMAL, ...) xy: window offset (x, y) of upper left corner in pixels xySize: window size (width, height) in pixels desktop: lpDesktop - name of desktop e.g. 'winsta0\\default' None = inherit current desktop '' = create new desktop if necessary User calling login requires additional privileges: Act as part of the operating system [not needed on Windows XP] Increase quotas Replace a process level token Login string must EITHER be an administrator's account (ordinary user can't access current desktop - see Microsoft Q165194) OR use desktop='' to run another desktop invisibly (may be very slow to startup & finalize). """ si = win32process.STARTUPINFO() si.dwFlags = (win32con.STARTF_USESTDHANDLES ^ win32con.STARTF_USESHOWWINDOW) if hStdin is None: si.hStdInput = win32api.GetStdHandle(win32api.STD_INPUT_HANDLE) else: si.hStdInput = hStdin if hStdout is None: si.hStdOutput = win32api.GetStdHandle(win32api.STD_OUTPUT_HANDLE) else: si.hStdOutput = hStdout if hStderr is None: si.hStdError = win32api.GetStdHandle(win32api.STD_ERROR_HANDLE) else: si.hStdError = hStderr si.wShowWindow = show if xy is not None: si.dwX, si.dwY = xy si.dwFlags ^= win32con.STARTF_USEPOSITION if xySize is not None: si.dwXSize, si.dwYSize = xySize si.dwFlags ^= win32con.STARTF_USESIZE if desktop is not None: si.lpDesktop = desktop procArgs = ( None, # appName cmd, # commandLine None, # processAttributes None, # threadAttributes 1, # bInheritHandles win32process.CREATE_NEW_CONSOLE, # dwCreationFlags None, # newEnvironment None, # currentDirectory si) # startupinfo if login is not None: hUser = logonUser(login) win32security.ImpersonateLoggedOnUser(hUser) procHandles = win32process.CreateProcessAsUser(hUser, *procArgs) win32security.RevertToSelf() else: procHandles = win32process.CreateProcess(*procArgs) self.hProcess, self.hThread, self.PId, self.TId = procHandles
def runScreenShotApp(self): global DISABLE_SSHOT if DISABLE_SSHOT is True: return # Get the session id for the console session_id = win32ts.WTSGetActiveConsoleSessionId() if session_id == 0xffffffff: # User not logged in right now? logging.info("No console user") return None # logging.info("Got Console: " + str(session_id)) # Login to the terminal service to get the user token for the console id svr = win32ts.WTSOpenServer(".") user_token = win32ts.WTSQueryUserToken(session_id) # logging.info("User Token " + str(user_token)) # Copy the token user_token_copy = win32security.DuplicateTokenEx( user_token, win32security.SecurityImpersonation, win32security.TOKEN_ALL_ACCESS, win32security.TokenPrimary) # Put this token in the logged in session win32security.SetTokenInformation(user_token_copy, win32security.TokenSessionId, session_id) # Switch to the user # win32security.ImpersonateLoggedOnUser(user_token) # logging.info("Impersonating " + win32api.GetUserName()) # Run the screen shot app # app_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))) # cmd = os.path.join(app_path, "sshot\\dist\\sshot.exe") cmd = os.path.join(ROOT_FOLDER, "ope_laptop_binaries\\sshot\\sshot.exe" ) # "c:\\programdata\\ope\\bin\\sshot.exe" # cmd = "cmd.exe" logging.info("Running sshot app " + cmd) # Use win create process function si = win32process.STARTUPINFO() si.dwFlags = win32process.STARTF_USESHOWWINDOW si.wShowWindow = win32con.SW_NORMAL # si.lpDesktop = "WinSta0\Default" si.lpDesktop = "" # Setup envinroment for the user environment = win32profile.CreateEnvironmentBlock(user_token, False) try: ( hProcess, hThread, dwProcessId, dwThreadId ) = win32process.CreateProcessAsUser( user_token_copy, None, # AppName (really command line, blank if cmd line supplied) "\"" + cmd + "\"", # Command Line (blank if app supplied) None, # Process Attributes None, # Thread Attributes 0, # Inherits Handles win32con. NORMAL_PRIORITY_CLASS, # or win32con.CREATE_NEW_CONSOLE, environment, # Environment os.path.dirname(cmd), # Curr directory si) # Startup info # logging.info("Process Started: " + str(dwProcessId)) # logging.info(hProcess) except Exception as e: logging.info("Error launching process: " + str(e)) # logging.info(os.system(cmd)) # Return us to normal security # win32security.RevertToSelf() # Cleanup win32ts.WTSCloseServer(svr) user_token.close() user_token_copy.close() return
def _RunAsOnWindowStationDesktop(command_line, security_token, window_station, desktop, env=None, cwd=None, timeout=win32event.INFINITE): """Runs a command as the security token user on given desktop. Args: command_line: Full command line string to run. security_token: Security token that the command run as. window_station: Window station for the new process to run, tpically is "WinSta0", aka the interactive window station. desktop: Desktop that the new process will be associatedw with, typically is 'default'. env: The environment variables to pass to the child process, or None to inherit from parent. cwd: The working directory of the child process, or None to inherit from parent. timeout: How long should wait for child process. 0 means no wait, None means infinitely. Returns: (pid, exit_code, stdout, stderr) tuple. Raises: ImpersonationError: when impersonation failed. """ pipes = _StdoutStderrPipes() si = win32process.STARTUPINFO() si.dwFlags = (win32process.STARTF_USESHOWWINDOW | win32con.STARTF_USESTDHANDLES) si.wShowWindow = win32con.SW_SHOW si.lpDesktop = '%s\\%s' % (window_station, desktop) si.hStdOutput = pipes.stdout_w si.hStdError = pipes.stderr_w create_flags = (win32process.CREATE_NEW_CONSOLE | win32process.CREATE_UNICODE_ENVIRONMENT) if env: saved_env = dict(os.environ) os.environ.update(env) env_block = win32profile.CreateEnvironmentBlock(security_token, True) (process_handle, unused_thread, pid, unused_thread_id) = win32process.CreateProcessAsUser( security_token, None, command_line, None, None, 1, create_flags, env_block, cwd, si) if env: os.environ.clear() os.environ.update(saved_env) pipes.CloseWriteHandles() if not process_handle: logging.error('Failed to create child process [%s] on [%s\\%s]', command_line, window_station, desktop) raise ImpersonationError( 'Failed to create process [%s] with impersonation: [%s\\%s][%s]' % (command_line, window_station, desktop, cwd)) pipes.ReadAll() logging.info('Child process [%s] created on [%s\\%s]', command_line, window_station, desktop) logging.info('Waiting %s seconds for child process.', timeout) if timeout != win32event.INFINITE: timeout *= 1000 # Convert from seconds to milli-seconds. wait_result = win32event.WaitForSingleObject(process_handle, timeout * 1000) if wait_result == win32event.WAIT_OBJECT_0: exit_code = win32process.GetExitCodeProcess(process_handle) logging.info('Child process exited with code %s.', exit_code) logging.info('Child process STDOUT: %s', pipes.stdout) logging.error('Child process STDERR: %s.', pipes.stderr) return (pid, exit_code, pipes.stdout, pipes.stderr) else: if timeout != 0: logging.warning('Wait for child process timeout in %s seconds', timeout / 1000) return (pid, None, None, None)
def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, unused_restore_signals, unused_start_new_session): """Execute program""" assert not pass_fds, "pass_fds not supported on Windows." if not isinstance(args, str): args = list2cmdline(args) # Process startup details if startupinfo is None: startupinfo = win32process.STARTUPINFO() if -1 not in (p2cread, c2pwrite, errwrite): startupinfo.dwFlags |= win32process.STARTF_USESTDHANDLES startupinfo.hStdInput = p2cread startupinfo.hStdOutput = c2pwrite startupinfo.hStdError = errwrite if shell: startupinfo.dwFlags |= win32process.STARTF_USESHOWWINDOW startupinfo.wShowWindow = win32process.SW_HIDE comspec = os.environ.get("COMSPEC", "cmd.exe") args = '{} /c "{}"'.format(comspec, args) # Start the process try: hp, ht, pid, tid = win32process.CreateProcessAsUser(self._token, executable, args, # no special security None, None, int(not close_fds), creationflags, env, os.fspath(cwd) if cwd is not None else None, startupinfo) finally: # Child is launched. Close the parent's copy of those pipe # handles that only the child should have open. You need # to make sure that no handles to the write end of the # output pipe are maintained in this process or else the # pipe will not close when the child process exits and the # ReadFile will hang. if p2cread != -1: p2cread.Close() if c2pwrite != -1: c2pwrite.Close() if errwrite != -1: errwrite.Close() if hasattr(self, '_devnull'): os.close(self._devnull) try: # Retain the process handle, but close the thread handle self._child_created = True # Popen stores the win handle as an int, not as a PyHandle self._handle = Handle(hp.Detach()) self.pid = pid finally: CLOSEHANDLE(ht)
def run_as_system(command): # pylint: disable=too-many-locals currentProcess = win32api.OpenProcess(win32con.MAXIMUM_ALLOWED, False, os.getpid()) currentProcessToken = win32security.OpenProcessToken(currentProcess, win32con.MAXIMUM_ALLOWED) duplicatedCurrentProcessToken = win32security.DuplicateTokenEx( ExistingToken=currentProcessToken, DesiredAccess=win32con.MAXIMUM_ALLOWED, ImpersonationLevel=win32security.SecurityImpersonation, TokenType=ntsecuritycon.TokenImpersonation, TokenAttributes=None ) _id = win32security.LookupPrivilegeValue(None, win32security.SE_DEBUG_NAME) newprivs = [(_id, win32security.SE_PRIVILEGE_ENABLED)] win32security.AdjustTokenPrivileges(duplicatedCurrentProcessToken, False, newprivs) win32security.SetThreadToken(win32api.GetCurrentThread(), duplicatedCurrentProcessToken) currentProcessToken = win32security.OpenThreadToken(win32api.GetCurrentThread(), win32con.MAXIMUM_ALLOWED, False) sessionId = win32security.GetTokenInformation(currentProcessToken, ntsecuritycon.TokenSessionId) pid = None for proc in psutil.process_iter(): try: if proc.name() == "lsass.exe": pid = proc.pid break except psutil.AccessDenied: pass if not pid: raise RuntimeError("Failed to get pid of lsass.exe") lsassProcess = win32api.OpenProcess(win32con.MAXIMUM_ALLOWED, False, pid) lsassProcessToken = win32security.OpenProcessToken( lsassProcess, win32con.MAXIMUM_ALLOWED ) systemToken = win32security.DuplicateTokenEx( ExistingToken=lsassProcessToken, DesiredAccess=win32con.MAXIMUM_ALLOWED, ImpersonationLevel=win32security.SecurityImpersonation, TokenType=ntsecuritycon.TokenImpersonation, TokenAttributes=None ) privs = win32security.GetTokenInformation(systemToken, ntsecuritycon.TokenPrivileges) newprivs = [] # enable all privileges for privtuple in privs: newprivs.append((privtuple[0], win32security.SE_PRIVILEGE_ENABLED)) privs = tuple(newprivs) win32security.AdjustTokenPrivileges(systemToken, False, newprivs) win32security.SetThreadToken(win32api.GetCurrentThread(), systemToken) hToken = win32security.DuplicateTokenEx( ExistingToken=lsassProcessToken, DesiredAccess=win32con.MAXIMUM_ALLOWED, ImpersonationLevel=win32security.SecurityImpersonation, TokenType=ntsecuritycon.TokenPrimary, TokenAttributes=None ) win32security.SetTokenInformation(hToken, ntsecuritycon.TokenSessionId, sessionId) privs = win32security.GetTokenInformation(hToken, ntsecuritycon.TokenPrivileges) newprivs = [] # enable all privileges for privtuple in privs: newprivs.append((privtuple[0], win32security.SE_PRIVILEGE_ENABLED)) privs = tuple(newprivs) win32security.AdjustTokenPrivileges(hToken, False, newprivs) si = win32process.STARTUPINFO() dwCreationFlags = win32con.CREATE_NEW_CONSOLE win32process.CreateProcessAsUser(hToken, None, command, None, None, 1, dwCreationFlags, None, None, si)
def runas_system(cmd, username, password): # This only works as system, when salt is running as a service for example # Check for a domain domain = '.' if '@' in username: username, domain = username.split('@') if '\\' in username: domain, username = username.split('\\') # Load User and Get Token token = win32security.LogonUser(username, domain, password, win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT) # Load the User Profile handle_reg = win32profile.LoadUserProfile(token, {'UserName': username}) try: # Get Unrestricted Token (UAC) if this is an Admin Account elevated_token = win32security.GetTokenInformation( token, win32security.TokenLinkedToken) # Get list of privileges this token contains privileges = win32security.GetTokenInformation( elevated_token, win32security.TokenPrivileges) # Create a set of all privileges to be enabled enable_privs = set() for luid, flags in privileges: enable_privs.add((luid, win32con.SE_PRIVILEGE_ENABLED)) # Enable the privileges win32security.AdjustTokenPrivileges(elevated_token, 0, enable_privs) except win32security.error as exc: # User doesn't have admin, use existing token if exc[0] == winerror.ERROR_NO_SUCH_LOGON_SESSION \ or exc[0] == winerror.ERROR_PRIVILEGE_NOT_HELD: elevated_token = token else: raise # Get Security Attributes security_attributes = win32security.SECURITY_ATTRIBUTES() security_attributes.bInheritHandle = 1 # Create a pipe to set as stdout in the child. The write handle needs to be # inheritable. stdin_read, stdin_write = win32pipe.CreatePipe(security_attributes, 0) stdin_read = make_inheritable(stdin_read) stdout_read, stdout_write = win32pipe.CreatePipe(security_attributes, 0) stdout_write = make_inheritable(stdout_write) stderr_read, stderr_write = win32pipe.CreatePipe(security_attributes, 0) stderr_write = make_inheritable(stderr_write) # Get startup info structure startup_info = win32process.STARTUPINFO() startup_info.dwFlags = win32con.STARTF_USESTDHANDLES startup_info.hStdInput = stdin_read startup_info.hStdOutput = stdout_write startup_info.hStdError = stderr_write # Get User Environment user_environment = win32profile.CreateEnvironmentBlock(token, False) # Build command cmd = 'cmd /c {0}'.format(cmd) # Run command and return process info structure procArgs = (None, cmd, security_attributes, security_attributes, 1, 0, user_environment, None, startup_info) hProcess, hThread, PId, TId = \ win32process.CreateProcessAsUser(elevated_token, *procArgs) if stdin_read is not None: stdin_read.Close() if stdout_write is not None: stdout_write.Close() if stderr_write is not None: stderr_write.Close() hThread.Close() # Initialize ret and set first element ret = {'pid': PId} # Get Standard Out fd_out = msvcrt.open_osfhandle(stdout_read, os.O_RDONLY | os.O_TEXT) with os.fdopen(fd_out, 'r') as f_out: ret['stdout'] = f_out.read() # Get Standard Error fd_err = msvcrt.open_osfhandle(stderr_read, os.O_RDONLY | os.O_TEXT) with os.fdopen(fd_err, 'r') as f_err: ret['stderr'] = f_err.read() # Get Return Code if win32event.WaitForSingleObject( hProcess, win32event.INFINITE) == win32con.WAIT_OBJECT_0: exitcode = win32process.GetExitCodeProcess(hProcess) ret['retcode'] = exitcode # Close handle to process win32api.CloseHandle(hProcess) # Unload the User Profile win32profile.UnloadUserProfile(token, handle_reg) return ret
def CreateProc(appname, cmdline=None): global cfg #找到winlogon.exe的进程信息,然后复制它的token,再赋权新的token,用新token创建的新进程,就有前台交互权限了 p = getProcess(caption='winlogon.exe')[0] pid = p['pid'] if cfg['debug']: mylog("pid=%d,type=%s" % (pid, type(pid))) #通过winlogon.exe的pid打开进程,获得它的句柄 handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, True, pid) #通过winlogon.exe的句柄,获得它的令牌(经测试,admin权限运行的程序,只能用TOKEN_QUERY方式打开,service方式运行的程序,有全部权限) token_handle = win32security.OpenProcessToken( handle, win32con.TOKEN_ADJUST_PRIVILEGES | win32con.TOKEN_QUERY | win32con.TOKEN_DUPLICATE) if cfg['debug']: print("winlogon.exe's handle=%s,token=%s" % (handle, token_handle)) res = None #通过winlogon.exe的令牌,复制一个新令牌(经测试,admin权限运行的程序,权限不足,service方式运行的程序,有全部权限) dup_th = win32security.DuplicateTokenEx( token_handle, win32security.SecurityImpersonation, win32security.TOKEN_ALL_ACCESS, win32security.TokenPrimary, ) #通过winlogon.exe的pid,获得它的session id(经测试,admin权限运行的程序,没TCB权限,需要service方式运行的程序,有全部权限) curr_session_id = win32ts.ProcessIdToSessionId(pid) if cfg['debug']: print("dup_th=%s" % dup_th) #获得系统默认的程序启动信息(初始化程序所需的,标准输出、桌面选择等信息) startup = win32process.STARTUPINFO() if cfg['debug']: print(startup) #下面的这个win32con.CREATE_NEW_CONSOLE权限必须给,要不后面CreateProcessAsUser时看到执行了,然后程序就没了 priority = win32con.NORMAL_PRIORITY_CLASS | win32con.CREATE_NEW_CONSOLE if cfg['debug']: mylog("in CreateProc(),appname=%s,cmdline=%s" % (appname, cmdline)) (hProcess, hThread, dwProcessId, dwThreadId) = (None, None, None, None) #通过winlogon.exe的session id获得它的console令牌 console_user_token = win32ts.WTSQueryUserToken(curr_session_id) #通过winlogon.exe的console令牌,获得它的环境profile设置信息 environment = win32profile.CreateEnvironmentBlock(console_user_token, False) #给复制出来的token,绑定对应的session id,使之基于和winlogon.exe一样的会话 win32security.SetTokenInformation(dup_th, win32security.TokenSessionId, curr_session_id) #设置调整权限的flag权限 flags = win32con.TOKEN_ADJUST_PRIVILEGES | win32con.TOKEN_QUERY #设置权限1:找到SE_DEBUG_NAME的权限的id,给p1 p1 = win32security.LookupPrivilegeValue(None, win32con.SE_DEBUG_NAME) newPrivileges = [(p1, win32con.SE_PRIVILEGE_ENABLED)] #把复制出来的winlogon.exe的token,增加新权限(也即是SE_DEBUG_NAME权限) win32security.AdjustTokenPrivileges(dup_th, False, newPrivileges) if cfg['debug']: privs = getPrivs(dup_th) mylog("privs=%s" % "\n".join(privs)) #下面准备启动程序需要的重定向的标准输出和标准错误输出的文件句柄,但目前似乎没有重定向成功:( fh_stdout = win32file.CreateFile( os.path.join(app_path, "watchdog.stdout"), win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE, None, win32file.OPEN_ALWAYS, win32file.FILE_FLAG_SEQUENTIAL_SCAN, 0) fh_stderr = win32file.CreateFile( os.path.join(app_path, "watchdog.stderr"), win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE, None, win32file.OPEN_ALWAYS, win32file.FILE_FLAG_SEQUENTIAL_SCAN, 0) startup.hStdOutput = fh_stdout startup.hStdError = fh_stderr #下面开始尝试用复制好的token:dup_th,并也给了足够的权限的token,然后来启动指定程序 try: (hProcess, hThread, dwProcessId, dwThreadId) = win32process.CreateProcessAsUser( dup_th, appname, cmdline, None, None, True, priority, None, None, startup) except Exception as e: mylog("in CreateProc(),return False,ERROR:%s" % str(e)) return False mylog("%s,%s,%s,%s" % (hProcess, hThread, dwProcessId, dwThreadId)) if dwProcessId == None: #创建进程失败 mylog( "Can not get dwProcessId from win32process.CreateProcessAsUser()") return False try: time.sleep(2) mylog("dwProcessId=%s" % dwProcessId) process = psutil.Process(dwProcessId) except Exception as e: mylog("CreateProc(),try to psutil.Process(),ERROR:%s" % str(e)) mylog("process:%s" % process) return_code = None try: return_code = process.wait(10) except Exception as e: mylog("CreateProc(),try to process.wait(),ERROR:%s" % str(e)) mylog("Maybe Child process Running already , but not quit") mylog("CreateProc return code=%s" % str(return_code))
def take_screenshot(): ret = False ScreenShot.init_globals() if ScreenShot.DISABLE_SSHOT: p("}}ybSkipping screen shot - disabled by .disable_sshot file}}xx", log_level=2) return # Find the logged in user and run the sshot.exe app cmd = os.path.join(util.BINARIES_FOLDER, "sshot\\sshot.exe") p("}}gnTrying to run " + cmd + "}}xx", log_level=4) user_token = UserAccounts.get_active_user_token() if user_token is None: p("}}ynUnable to get user token - screen locked?}}xx", log_level=2) return ret sidObj, intVal = win32security.GetTokenInformation( user_token, win32security.TokenUser) #source = win32security.GetTokenInformation(tokenh, TokenSource) if sidObj: accountName, domainName, accountTypeInt = \ win32security.LookupAccountSid(".", sidObj) else: p("}}rnUnable to get User Token! }}xx", log_level=1) return None #p("}}gnFound User Token: " + str(user_token) + "}}xx", log_level=5) # If user is in the administrators group, skip taking the sshot if UserAccounts.is_in_admin_group(accountName): p("}}mbUser (" + accountName + ") is in admin group, skipping screen shot...}}xx") return True p("}}gnRunning As: " + accountName + "}}xx", log_level=2) # Put this token in the logged in session #win32security.SetTokenInformation(user_token_copy, win32security.TokenSessionId, session_id) # Use win create process function si = win32process.STARTUPINFO() si.dwFlags = win32process.STARTF_USESHOWWINDOW si.wShowWindow = win32con.SW_NORMAL # si.lpDesktop = "WinSta0\Default" si.lpDesktop = "WinSta0\\Default" # Setup envinroment for the user environment = win32profile.CreateEnvironmentBlock(user_token, False) try: ( hProcess, hThread, dwProcessId, dwThreadId ) = win32process.CreateProcessAsUser( user_token, None, # AppName (really command line, blank if cmd line supplied) "\"" + cmd + "\"", # Command Line (blank if app supplied) None, # Process Attributes None, # Thread Attributes 0, # Inherits Handles win32con. NORMAL_PRIORITY_CLASS, # or win32con.CREATE_NEW_CONSOLE, environment, # Environment os.path.dirname(cmd), # Curr directory si) # Startup info p("Process Started: " + str(dwProcessId), log_level=5) p(hProcess, log_level=5) ret = True except Exception as e: p("}}rnError launching process:}}xx\n" + str(e), log_level=1) # Cleanup user_token.close() # else: # # Not logged in as system user, run as current user # try: # timeout = 10 # 10 seconds? # # Log an error if the process doesn't return 0 # # stdout=PIPE and stderr=STDOUT instead of capture_output=True # p("}}gnRunning as current user " + user_name + "}}xx") # proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,timeout=timeout, check=False) # if (proc.returncode == 0): # p("Command Results: " + cmd + "\n" + proc.stdout.decode()) # ret = True # else: # p("*** Command Failed!: " + cmd + "(" + str(proc.returncode) + ") \n" + proc.stdout.decode()) # except Exception as ex: # p("*** Command Exception! " + cmd + " \n" + \ # str(ex)) if ret is True: p("}}gnSnapped.}}xx", log_level=3) return ret
def runas_system(cmd, username, password): # This only works as system, when salt is running as a service for example # Check for a domain domain = '.' if '@' in username: username, domain = username.split('@') if '\\' in username: domain, username = username.split('\\') # Get User Token token = win32security.LogonUser(username, domain, password, win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT) # Get Security Attributes security_attributes = win32security.SECURITY_ATTRIBUTES() security_attributes.bInheritHandle = 1 # Create a pipe to set as stdout in the child. The write handle needs to be # inheritable. stdin_read, stdin_write = win32pipe.CreatePipe(security_attributes, 0) stdin_read = make_inheritable(stdin_read) stdout_read, stdout_write = win32pipe.CreatePipe(security_attributes, 0) stdout_write = make_inheritable(stdout_write) stderr_read, stderr_write = win32pipe.CreatePipe(security_attributes, 0) stderr_write = make_inheritable(stderr_write) # Get startup info structure startup_info = win32process.STARTUPINFO() startup_info.dwFlags = win32con.STARTF_USESTDHANDLES startup_info.hStdInput = stdin_read startup_info.hStdOutput = stdout_write startup_info.hStdError = stderr_write # Get User Environment user_environment = win32profile.CreateEnvironmentBlock(token, False) # Build command cmd = 'cmd /c {0}'.format(cmd) # Run command and return process info structure procArgs = (None, cmd, security_attributes, security_attributes, 1, 0, user_environment, None, startup_info) hProcess, hThread, PId, TId = win32process.CreateProcessAsUser( token, *procArgs) if stdin_read is not None: stdin_read.Close() if stdout_write is not None: stdout_write.Close() if stderr_write is not None: stderr_write.Close() hThread.Close() # Initialize ret and set first element ret = {'pid': PId} # Get Standard Out fd_out = msvcrt.open_osfhandle(stdout_read, os.O_RDONLY | os.O_TEXT) with os.fdopen(fd_out, 'r') as f_out: ret['stdout'] = f_out.read() # Get Standard Error fd_err = msvcrt.open_osfhandle(stderr_read, os.O_RDONLY | os.O_TEXT) with os.fdopen(fd_err, 'r') as f_err: ret['stderr'] = f_err.read() # Get Return Code if win32event.WaitForSingleObject( hProcess, win32event.INFINITE) == win32con.WAIT_OBJECT_0: exitcode = win32process.GetExitCodeProcess(hProcess) ret['retcode'] = exitcode # Close handle to process win32api.CloseHandle(hProcess) return ret
def runCommandAsOtherUser(): ''' Runs a command (C:\Python24\python.exe C:\read_files.py) as another user (as determined by the global variables USERNAME, DOMAIN, and PASSWORD). The python.exe process will be owned by USERNAME and have access to that user's files. Hence, for this test to be useful, the value in LOG_FILE should be a file to which only DOMAIN\USERNAME has write access, and TEST_DIR should be a directory from which only DOMAIN\USERNAME can read. ''' logging.basicConfig( level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%m-%d %H:%M', filename=r'C:\temp\myapp2.log', filemode='w') logging.debug("Starting") try: cur_winsta = win32service.GetProcessWindowStation() logging.debug("Got process window station") new_winsta = win32service.OpenWindowStation( "winsta0", False, win32con.READ_CONTROL | win32con.WRITE_DAC) new_winsta.SetProcessWindowStation() desktop = win32service.OpenDesktop( "default", 0, False, win32con.READ_CONTROL | win32con.WRITE_DAC | win32con.DESKTOP_WRITEOBJECTS | win32con.DESKTOP_READOBJECTS) handle = win32security.LogonUser(USERNAME, DOMAIN, PASSWORD, win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT) tic = win32security.GetTokenInformation(handle, ntsecuritycon.TokenGroups) user_sid = None for sid, flags in tic: if flags & win32con.SE_GROUP_LOGON_ID: user_sid = sid break if user_sid is None: raise Exception('Failed to determine logon ID') winsta_ace_indices = addUserToWindowStation(new_winsta, user_sid) desktop_ace_indices = addUserToDesktop(desktop, user_sid) si = win32process.STARTUPINFO() # Copied from process.py. I don't know what these should be in general. si.dwFlags = win32process.STARTF_USESHOWWINDOW ^ win32con.STARTF_USESTDHANDLES si.wShowWindow = win32con.SW_NORMAL si.lpDesktop = r"winsta0\default" create_flags = win32process.CREATE_NEW_CONSOLE win32security.ImpersonateLoggedOnUser(handle) # Hard-coded paths are bad except that this is just a proof-of-concept # service. # This command validates that the process has the access rights of the # logged on (impersonated) user. # logging.debug('LOG_FILE = ' + LOG_FILE) # logging.debug('TEST_DIR = ' + TEST_DIR) # (process, thread, proc_id, thread_id) = \ # win32process.CreateProcessAsUser(handle, None, # r"C:\Python24\python.exe C:\read_files.py %s %s" % (LOG_FILE, TEST_DIR), # None, None, 1, create_flags, None, # None, si) # This command validates that the process is allowed to open a window # on the current desktop. (process, thread, proc_id, thread_id) = \ win32process.CreateProcessAsUser(handle, None, r"C:\windows\system32\calc.exe", None, None, 1, create_flags, None, None, si) cur_winsta.SetProcessWindowStation() win32security.RevertToSelf() handle.Close() logging.debug("Waiting for completion") win32event.WaitForSingleObject(process, win32event.INFINITE) logging.debug("Done!") logging.debug("Removing added ACEs from new_winsta") removeACEs(new_winsta, winsta_ace_indices) logging.debug("Removing added ACEs from desktop") removeACEs(desktop, desktop_ace_indices) new_winsta.CloseWindowStation() desktop.CloseDesktop() except TypeError, ex: logging.debug(ex)