代码之家  ›  专栏  ›  技术社区  ›  Brad

从服务启动用户会话中的进程

  •  13
  • Brad  · 技术社区  · 14 年前

    我读到的每一篇文章似乎都在说这是不可能的,但我想在完全放弃之前我应该先问一下。

    我正在用VB.NET编写代码,但会采纳任何建议。

    5 回复  |  直到 8 年前
        1
  •  21
  •   Community iksemyonov    7 年前

    这真的是有可能的。您遇到的主要问题是,Windows应该被视为终端服务器,而用户会话应该被视为远程会话。您的服务应该能够启动在属于用户的远程会话中运行的进程。

    顺便说一句,如果您编写了一个在Windows XP下运行的服务,而该服务没有添加到域中,并且激活了快速用户切换,那么在第二个(第三个等)登录的用户桌面上运行进程时,您可能会遇到同样的问题。

    我希望你有一个用户令牌,你收到例如关于模仿或你有一个 dwSessionId http://msdn.microsoft.com/en-us/library/aa383464.aspx ,例如 WTSEnumerateProcesses WTSGetActiveConsoleSessionId )或LSA-API找到相应的用户会话( LsaEnumerateLogonSessions http://msdn.microsoft.com/en-us/library/aa378275.aspx LsaGetLogonSessionData 看见 http://msdn.microsoft.com/en-us/library/aa378290.aspx )或者 ProcessIdToSessionId http://msdn.microsoft.com/en-us/library/aa382990.aspx ).

    GetTokenInformation 带参数的函数 TokenSessionId (见 http://msdn.microsoft.com/en-us/library/aa446671.aspx )接收会话id dwSessionId文件 如果您知道users令牌 hClient .

    BOOL bSuccess;
    HANDLE hProcessToken = NULL, hNewProcessToken = NULL;
    DWORD dwSessionId, cbReturnLength;
    
    bSuccess = GetTokenInformation (hClient, TokenSessionId, &dwSessionId,
                                    sizeof(DWORD), &cbReturnLength);
    bSuccess = OpenProcessToken (GetCurrentProcess(), MAXIMUM_ALLOWED, &hProcessToken);
    bSuccess = DuplicateTokenEx (hProcessToken, MAXIMUM_ALLOWED, NULL,
                                 SecurityImpersonation,
                                 TokenPrimary, &hNewProcessToken);
    EnablePrivilege (SE_TCB_NAME);
    bSuccess = SetTokenInformation (hNewProcessToken, TokenSessionId, &dwSessionId,
                                    sizeof(DWORD));
    bSuccess = CreateProcessAsUser (hNewProcessToken, NULL, szCommandToExecute, ...);
    

    此代码只是一个架构。 EnablePrivilege AdjustTokenPrivileges 启用 SE_TCB_NAME 特权(参见 http://msdn.microsoft.com/en-us/library/aa446619.aspx seu TCB\u名称

    再说一句。在上面的代码中,我们使用与当前进程相同的帐户启动新进程(例如本地系统)。将代码更改为使用另一个帐户,例如users令牌 . 重要的是要有一个 primary token

    STARTUPINFO 中使用的结构 CreateProcessAsUser lpDesktop = WinSta0\默认值。

    CreateEnvironmentBlock 创建要传递给新进程的新环境块。

    我建议你也读一读 How to ensure process window launched by Process.Start(ProcessStartInfo) has focus of all Forms? 在这里,我描述了如何强制在前台用户桌面上启动进程。

        2
  •  5
  •   Steve    9 年前

    如果有帮助的话,我也面临着类似的问题,但是我想要一个纯powershell解决方案。

    我从其他网站拼凑了一些信息,得出了这个结论:

    function Invoke-CommandInSession 
    {
        [CmdletBinding()]
        param(
            [Parameter(Mandatory = $true)]
            [ValidateNotNullOrEmpty()]
            [ScriptBlock] $expression
        )
    
        $commandLine = “powershell“
    
        ## Convert the command into an encoded command for PowerShell
        $commandBytes = [System.Text.Encoding]::Unicode.GetBytes($expression)
        $encodedCommand = [Convert]::ToBase64String($commandBytes)
        $args = “-Output XML -EncodedCommand $encodedCommand”
    
    
        $action = New-ScheduledTaskAction -Execute $commandLine -Argument $args
        $setting = New-ScheduledTaskSettingsSet -DeleteExpiredTaskAfter ([Timespan]::Zero)
        $trigger = New-ScheduledTaskTrigger -Once -At ((Get-Date) + ([Timespan]::FromSeconds(5)))
        $task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $setting
        Register-ScheduledTask "Invoke-CommandInSession - $([Guid]::NewGuid())" -InputObject $task
    }
    

        3
  •  3
  •   Bear Monkey    14 年前

    这是可以做到的,但服务直接与用户会话交互并不被认为是好的做法,因为这会造成严重的安全漏洞。

    http://support.microsoft.com/kb/327618

        4
  •  3
  •   John Saunders    14 年前

    是的,使用 CreateProcessAsUser

        5
  •  0
  •   tchelidze    8 年前

    Subverting Vista UAC in Both 32 and 64 bit Architectures

    提供的代码是针对Vista的,但也适用于Win7和Win10