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 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
Exemple #3
0
def create_env(user_token, inherit, timeout=1):
    """
    CreateEnvironmentBlock might fail when we close a login session and then
    try to re-open one very quickly. Run the method multiple times to work
    around the async nature of logoffs.
    """
    start = time.time()
    env = None
    exc = None
    while True:
        try:
            env = win32profile.CreateEnvironmentBlock(user_token, False)
        except pywintypes.error as exc:
            pass
        else:
            break
        if time.time() - start > timeout:
            break
    if env is not None:
        return env
    raise exc
Exemple #4
0
## Marshal saved credential and use it to log on
mc = win32cred.CredMarshalCredential(win32cred.UsernameTargetCredential,
                                     target)
th = win32security.LogonUser(mc, None, '', win32con.LOGON32_LOGON_INTERACTIVE,
                             win32con.LOGON32_PROVIDER_DEFAULT)
win32security.ImpersonateLoggedOnUser(th)
print 'GetUserName:'******'s profile.  (first check if user has a roaming profile)
username, domain = win32cred.CredUIParseUserName(target)
user_info_4 = win32net.NetUserGetInfo(None, username, 4)
profilepath = user_info_4['profile']
## LoadUserProfile apparently doesn't like an empty string
if not profilepath:
    profilepath = None

## leave Flags in since 2.3 still chokes on some types of optional keyword args
hk = win32profile.LoadUserProfile(th, {
    'UserName': username,
    'Flags': 0,
    'ProfilePath': profilepath
})
## Get user's environment variables in a form that can be passed to win32process.CreateProcessAsUser
env = win32profile.CreateEnvironmentBlock(th, False)

## Cleanup should probably be in a finally block
win32profile.UnloadUserProfile(th, hk)
th.Close()
Exemple #5
0
    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
Exemple #6
0
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)
Exemple #7
0
    async def start(self):
        """Start the single-user server."""
        self.port = random_port()
        cmd = []
        env = self.get_env()
        token = None

        cmd.extend(self.cmd)

        cmd.extend(self.get_args())

        if self.shell_cmd:
            # using shell_cmd (e.g. bash -c),
            # add our cmd list as the last (single) argument:
            cmd = self.shell_cmd + [' '.join(pipes.quote(s) for s in cmd)]

        self.log.info("Spawning %s", ' '.join(pipes.quote(s) for s in cmd))

        auth_state = await self.user.get_auth_state()
        if auth_state:
            token = pywintypes.HANDLE(auth_state['auth_token'])

        user_env = None
        cwd = None

        try:
            # Will load user variables, if the user profile is loaded
            user_env = win32profile.CreateEnvironmentBlock(token, False)
        except Exception as exc:
            self.log.warning("Failed to load user environment for %s: %s", self.user.name, exc)
        else:
            # Only load user environment if we hold a valid auth token
            if token:
                env.update(user_env)
            if not 'APPDATA' in user_env:
                #If the 'APPDATA' does not exist, the USERPROFILE points at the default
                #directory which is not writable. this changes the path over to public
                #documents, so at least its a writable location.
                user_env['USERPROFILE'] = user_env['PUBLIC']

        # On Posix, the cwd is set to ~ before spawning the singleuser server (preexec_fn).
        # Windows Popen doesn't have preexec_fn support, so we need to set cwd directly.
        if self.notebook_dir:
            cwd = os.getcwd()
        elif env['APPDATA']:
            cwd = user_env['USERPROFILE']
        else:
            # Set CWD to a temp directory, since we failed to load the user profile
            cwd = mkdtemp()

        popen_kwargs = dict(
            token=token,
            cwd=cwd,
        )

        popen_kwargs.update(self.popen_kwargs)
        # don't let user config override env
        popen_kwargs['env'] = env
        try:
            self.proc = PopenAsUser(cmd, **popen_kwargs)
        except PermissionError:
            # use which to get abspath
            script = shutil.which(cmd[0]) or cmd[0]
            self.log.error("Permission denied trying to run %r. Does %s have access to this file?",
                           script, self.user.name,
                          )
            if token:
                token.Detach()
            raise

        self.pid = self.proc.pid
        if token:
            token.Detach()

        if self.__class__ is not LocalProcessSpawner:
            # subclasses may not pass through return value of super().start,
            # relying on deprecated 0.6 way of setting ip, port,
            # so keep a redundant copy here for now.
            # A deprecation warning will be shown if the subclass
            # does not return ip, port.
            if self.ip:
                self.server.ip = self.ip
            self.server.port = self.port
            self.db.commit()

        return (self.ip or '127.0.0.1', self.port)
Exemple #8
0
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
Exemple #9
0
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))
Exemple #10
0
    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
Exemple #11
0
def runas(cmdLine, username, password=None, cwd=None):
    '''
    Run a command as another user. If the process is running as an admin or
    system account this method does not require a password. Other non
    privileged accounts need to provide a password for the user to runas.
    Commands are run in with the highest level privileges possible for the
    account provided.
    '''
    # Validate the domain and sid exist for the username
    username, domain = split_username(username)
    try:
        _, domain, _ = win32security.LookupAccountName(domain, username)
    except pywintypes.error as exc:
        message = win32api.FormatMessage(exc.winerror).rstrip('\n')
        raise CommandExecutionError(message)

    # Elevate the token from the current process
    access = (
        win32security.TOKEN_QUERY |
        win32security.TOKEN_ADJUST_PRIVILEGES
    )
    th = win32security.OpenProcessToken(win32api.GetCurrentProcess(), access)
    hubblestack.platform.win.elevate_token(th)

    # Try to impersonate the SYSTEM user. This process needs to be running as a
    # user who as been granted the SeImpersonatePrivilege, Administrator
    # accounts have this permission by default.
    try:
        impersonation_token = hubblestack.platform.win.impersonate_sid(
            hubblestack.platform.win.SYSTEM_SID,
            session_id=0,
            privs=['SeTcbPrivilege'],
        )
    except WindowsError:  # pylint: disable=undefined-variable
        log.debug("Unable to impersonate SYSTEM user")
        impersonation_token = None
        win32api.CloseHandle(th)

    # Impersonation of the SYSTEM user failed. Fallback to an un-privileged
    # runas.
    if not impersonation_token:
        log.debug("No impersonation token, using unprivileged runas")
        return runas_unpriv(cmdLine, username, password, cwd)

    if domain == 'NT AUTHORITY':
        # Logon as a system level account, SYSTEM, LOCAL SERVICE, or NETWORK
        # SERVICE.
        user_token = win32security.LogonUser(
            username,
            domain,
            '',
            win32con.LOGON32_LOGON_SERVICE,
            win32con.LOGON32_PROVIDER_DEFAULT,
        )
    elif password:
        # Login with a password.
        user_token = win32security.LogonUser(
            username,
            domain,
            password,
            win32con.LOGON32_LOGON_INTERACTIVE,
            win32con.LOGON32_PROVIDER_DEFAULT,
        )
    else:
        # Login without a password. This always returns an elevated token.
        user_token = hubblestack.platform.win.logon_msv1_s4u(username).Token

    # Get a linked user token to elevate if needed
    elevation_type = win32security.GetTokenInformation(
        user_token, win32security.TokenElevationType
    )
    if elevation_type > 1:
        user_token = win32security.GetTokenInformation(
            user_token,
            win32security.TokenLinkedToken
        )

    # Elevate the user token
    hubblestack.platform.win.elevate_token(user_token)

    # Make sure the user's token has access to a windows station and desktop
    hubblestack.platform.win.grant_winsta_and_desktop(user_token)

    # Create pipes for standard in, out and error streams
    security_attributes = win32security.SECURITY_ATTRIBUTES()
    security_attributes.bInheritHandle = 1

    stdin_read, stdin_write = win32pipe.CreatePipe(security_attributes, 0)
    stdin_read = hubblestack.platform.win.make_inheritable(stdin_read)

    stdout_read, stdout_write = win32pipe.CreatePipe(security_attributes, 0)
    stdout_write = hubblestack.platform.win.make_inheritable(stdout_write)

    stderr_read, stderr_write = win32pipe.CreatePipe(security_attributes, 0)
    stderr_write = hubblestack.platform.win.make_inheritable(stderr_write)

    # Run the process without showing a window.
    creationflags = (
        win32process.CREATE_NO_WINDOW |
        win32process.CREATE_NEW_CONSOLE |
        win32process.CREATE_SUSPENDED
    )

    startup_info = hubblestack.platform.win.STARTUPINFO(
        dwFlags=win32con.STARTF_USESTDHANDLES,
        hStdInput=stdin_read.handle,
        hStdOutput=stdout_write.handle,
        hStdError=stderr_write.handle,
    )

    # Create the environment for the user
    env = win32profile.CreateEnvironmentBlock(user_token, False)

    hProcess = None
    try:
        # Start the process in a suspended state.
        process_info = hubblestack.platform.win.CreateProcessWithTokenW(
            int(user_token),
            logonflags=1,
            applicationname=None,
            commandline=cmdLine,
            currentdirectory=cwd,
            creationflags=creationflags,
            startupinfo=startup_info,
            environment=env,
        )

        hProcess = process_info.hProcess
        hThread = process_info.hThread
        dwProcessId = process_info.dwProcessId
        dwThreadId = process_info.dwThreadId

        # We don't use these so let's close the handle
        hubblestack.platform.win.kernel32.CloseHandle(stdin_write.handle)
        hubblestack.platform.win.kernel32.CloseHandle(stdout_write.handle)
        hubblestack.platform.win.kernel32.CloseHandle(stderr_write.handle)

        ret = {'pid': dwProcessId}
        # Resume the process
        psutil.Process(dwProcessId).resume()

        # Wait for the process to exit and get it's return code.
        if win32event.WaitForSingleObject(hProcess, win32event.INFINITE) == win32con.WAIT_OBJECT_0:
            exitcode = win32process.GetExitCodeProcess(hProcess)
            ret['retcode'] = exitcode

        # Read standard out
        fd_out = msvcrt.open_osfhandle(stdout_read.handle, os.O_RDONLY | os.O_TEXT)
        with os.fdopen(fd_out, 'r') as f_out:
            stdout = f_out.read()
            ret['stdout'] = stdout

        # Read standard error
        fd_err = msvcrt.open_osfhandle(stderr_read.handle, os.O_RDONLY | os.O_TEXT)
        with os.fdopen(fd_err, 'r') as f_err:
            stderr = f_err.read()
            ret['stderr'] = stderr
    finally:
        if hProcess is not None:
            hubblestack.platform.win.kernel32.CloseHandle(hProcess)
        win32api.CloseHandle(th)
        win32api.CloseHandle(user_token)
        if impersonation_token:
            win32security.RevertToSelf()
        win32api.CloseHandle(impersonation_token)

    return ret
Exemple #12
0
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
Exemple #13
0
    def onRunCommand(self, nodeId, avatar, command, args, cwd, envMap):
        def merge(d1, d2):
            '''
         Merges the two dictionaries into one so that d1 contains all the
         keys of d2. If d1 already contains a key in d2, d1 retains its
         key/value pair.
         '''
            for k in d2.keys():
                if not d1.has_key(k):
                    d1[k] = d2[k]

        self.mLogger.debug("LaunchService.onRunCommand(%s, %s, %s, %s)" % \
                           (command, str(args), cwd, envMap))

        try:
            if self.mProcess is not None:
                running, exit_code = self.isProcessRunning()
                if running:
                    self.mLogger.warning("Command already running.")
                    return False
                else:
                    self.mProcess = None
                    env = maestro.core.Environment()
                    env.mEventManager.emit("*", "launch.report_is_running",
                                           False, exit_code)

            #self.mLogger.debug("Original env: " + str(envMap))

            # Ensure that common environment variables that may be referenced in
            # command or the current working directory are set according to the
            # user execution environment rather than the daemon execution
            # environment.
            # TODO: What about Windows?
            if not sys.platform.startswith('win'):
                user_name = avatar.mUserName

                # Do not overwrite settings that were provided as part of the
                # command execution request.
                if not envMap.has_key('HOME'):
                    envMap['HOME'] = pwd.getpwnam(user_name)[5]
                if not envMap.has_key('USER'):
                    envMap['USER'] = user_name
                if not envMap.has_key('LOG_NAME'):
                    envMap['LOG_NAME'] = user_name

            # Retrieve the user's environment.
            # TODO: Need to find a way to do this on other platforms.
            if sys.platform.startswith('win'):
                user_env = win32profile.CreateEnvironmentBlock(
                    avatar.mUserHandle, False)
            else:
                # XXX: This might not give us what we think it does because on UNIX
                #      os.environ is bound when the service starts. This will happen
                #      before many things get set up in the environment, $HOSTNAME
                #      for example is not defined yet. On Windows it should give
                #      us the System Environment.
                user_env = os.environ

            # Merge our environment with the local environment.
            merge(envMap, user_env)

            # No need to do this since we are merging the entire os.environ.
            if sys.platform.startswith("win"):
                # XXX: For some reason SYSTEMROOT is not getting into user env.
                envMap["SYSTEMROOT"] = os.environ["SYSTEMROOT"]
            else:
                # XXX: This could be better.
                if user_env.has_key('DISPLAY'):
                    envMap['DISPLAY'] = user_env['DISPLAY']
                if user_env.has_key('USER_XAUTHORITY'):
                    envMap['XAUTHORITY'] = user_env['USER_XAUTHORITY']

            # Expand all environment variables.
            # XXX: Do we really need to do this in all cases? The operating system
            #      should be able to do this for us. Except we are not using cross
            #      platform envvar syntax.
            self.evaluateEnvVars(envMap, user_env)
            command = self.expandEnv(command, envMap, user_env)[0]

            if args is not None:
                for i in xrange(len(args)):
                    args[i] = self.expandEnv(args[i], envMap, user_env)[0]

            match_obj = self.cmd_space_re.search(command)

            # If command contains spaces, ensure that it is wrapped in double
            # quotes.
            # NOTE: For Windows, what will happen is that the command will be
            # run as ""command" <args>". This is valid behavior because the
            # command gets executed within a command shell where that quoting
            # indicates a special interpretation. Specifically, it applies to
            # this part of the output from running 'cmd /?':
            #
            #    If /C or /K is specified, then the remainder of the command line
            #    after the switch is processed as a command line, where the
            #    following logic is used to process quote (") characters:
            #
            #        1. [...]
            #
            #        2. Otherwise, old behavior is to see if the first character
            #           is a quote character and if so, strip the leading
            #           character and remove the last quote character on the
            #           command line, preserving any text after the last quote
            #           character.
            #
            # This behavior is why we are using double quotes rather than single
            # quotes for wrapping command. For non-Windows platforms, using
            # double quotes allows shell variable interpolation when the command
            # gets executed (since it is run within a /bin/sh process).
            if match_obj is not None:
                match_obj = self.single_quote_cmd_re.search(command)

                # If command is enclosed in single quotes, change them to double
                # quotes.
                if match_obj:
                    command = '"%s"' % match_obj.group(1)
                else:
                    match_obj = self.double_quote_cmd_re.search(command)

                    # If command is not enclosed in single quotes or double quotes,
                    # wrap it in double quotes.
                    if match_obj is None:
                        command = '"%s"' % command

            if cwd is not None:
                cwd = self.expandEnv(cwd, envMap, user_env)[0]
            #command = command.replace('\\', '\\\\')
            self.mLogger.info("Running command: " + command)
            self.mLogger.debug("Working Dir: " + str(cwd))
            self.mLogger.debug("Translated env: " + str(envMap))

            # Construct the actual command that will be executed. At this point,
            # all quoting on command and the individual arguments has to be
            # correct.
            if args is not None and len(args) > 0:
                command = '%s %s' % (command, ' '.join(args))

            self.mProcess = process.ProcessOpen(cmd=command,
                                                cwd=cwd,
                                                env=envMap,
                                                avatar=avatar)

            self.mStdoutThread = OutputThread(self, self.mProcess.stdout)
            #self.mStderrThread = OutputThread(self, self.mProcess.stderr)
            self.mLogger.debug("BEFORE THREAD START")
            sys.stdout.flush()
            self.mStdoutThread.start()
            #self.mStderrThread.start()
            self.mLogger.debug("AFTER THREAD START")
            sys.stdout.flush()
            return True
        except KeyError, ex:
            #traceback.print_stack()
            self.mLogger.error("runCommand() failed with KeyError: " + str(ex))
            return False