CreateProcessAsUser未正确设置用户

时间:2011-02-08 22:14:38

标签: .net winapi windows-7 createprocessasuser security-context

使用

调用GUI应用程序
[DllImport(
    "advapi32.dll",
    EntryPoint = "CreateProcessAsUser",
    SetLastError = true,
    CharSet = CharSet.Ansi,
    CallingConvention = CallingConvention.StdCall)]
private static extern bool CreateProcessAsUser(
    IntPtr hToken,
    string lpApplicationName,
    string lpCommandLine,
    ref SECURITY_ATTRIBUTES lpProcessAttributes,
    ref SECURITY_ATTRIBUTES lpThreadAttributes,
    bool bInheritHandle,
    int dwCreationFlags,
    IntPtr lpEnvironment,
    string lpCurrentDirectory,
    ref STARTUPINFO lpStartupInfo,
    out PROCESS_INFORMATION lpProcessInformation);


bool result = CreateProcessAsUser(
    hUserTokenDup,
    null,
    applicationName + " " + arguments,
    ref sa,                 // pointer to process SECURITY_ATTRIBUTES
    ref sa,                 // pointer to thread SECURITY_ATTRIBUTES
    false,                  // handles are not inheritable
    NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,        // creation flags
    IntPtr.Zero,            // pointer to new environment block 
    null,                   // name of current directory 
    ref si,                 // pointer to STARTUPINFO structure
    out procInfo);          // receives information about new process

从LocalSystem Windows服务工作。 该窗口在用户屏幕中弹出,但进程用户仍然是LocalSystem。有没有办法改变它?

PS 根据要求,我从

获得hUserTokenDup
[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
private static extern bool DuplicateTokenEx(
    IntPtr ExistingTokenHandle,
    uint dwDesiredAccess,
    ref SECURITY_ATTRIBUTES lpThreadAttributes,
    int TokenType,
    int ImpersonationLevel,
    ref IntPtr DuplicateTokenHandle);

 DuplicateTokenEx(
     hPToken,
     MAXIMUM_ALLOWED,
     ref sa,
     (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
     (int)TOKEN_TYPE.TokenPrimary,
     ref hUserTokenDup);

3 个答案:

答案 0 :(得分:2)

看起来不是使用DuplicateTokenEx来复制当前令牌,而是需要调用LogonUser来获取代表目标用户的令牌。简单地调用DuplicateTokenEx将为本地系统用户创建一个令牌..如果我正确理解你的代码片段。

此外,由于您的目标是交互式用户,请考虑使用 CreateProcessWithLogonW 功能。

答案 1 :(得分:2)

在我的服务中,我在调用WTSGetActiveConsoleSessionId()之前使用WTSQueryUserToken()DuplicationTokenEx()CreateProcessAsUser(),这对我来说很合适。生成的进程在用户帐户中运行,而不是在服务帐户中运行。

答案 2 :(得分:0)

感谢Remy Lebeau提示使用 WTSGetActiveConsoleSessionId()

下面的函数必须从“系统”调用 - 用户就像win-service一样,需要一个正在运行的物理控制台(普通的用户登录会话,没有远程终端会话)。您可以使用此用户安全属性从正在运行的登录会话中的win-service启动新进程。 如果调用者不是“系统”,则无法使用模拟用户启动新进程。

 public static bool StartProcessAndBypassUAC(ProcessStartInfo ps, out PROCESS_INFORMATION procInfo)
 {
 // code based on http://www.codeproject.com/Articles/35773/Subverting-Vista-UAC-in-Both-32-and-64-bit-Archite
    uint winlogonPid = 0;
    IntPtr hUserTokenDup = IntPtr.Zero, hPToken = IntPtr.Zero, hProcess = IntPtr.Zero;
    procInfo = new PROCESS_INFORMATION();

    // obtain the currently active session id; every logged on user in the system has a unique session id
    uint dwSessionId = WTSGetActiveConsoleSessionId();

    if (dwSessionId == 0xFFFFFFFF)
    {
        // no  physical console
        return false;
    }

    if (!WTSQueryUserToken(dwSessionId, ref hPToken))
    {
        return false ;
    }

    // Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
    // I would prefer to not have to use a security attribute variable and to just 
    // simply pass null and inherit (by default) the security attributes
    // of the existing token. However, in C# structures are value types and therefore
    // cannot be assigned the null value.
    SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
    sa.Length = Marshal.SizeOf(sa);

    // copy the access token of the winlogon process; the newly created token will be a primary token
    if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
    {
        CloseHandle(hProcess);
        CloseHandle(hPToken);
        return false;
    }

    // By default CreateProcessAsUser creates a process on a non-interactive window station, meaning
    // the window station has a desktop that is invisible and the process is incapable of receiving
    // user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user 
    // interaction with the new process.
    STARTUPINFO si = new STARTUPINFO();
    si.cb = (int)Marshal.SizeOf(si);
    si.lpDesktop = @"winsta0\default"; // interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop

    // flags that specify the priority and creation method of the process
    int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

    // create a new process in the current user's logon session
    bool result = CreateProcessAsUser(hUserTokenDup,        // client's access token
                                    null,                   // file to execute
                                    ps.FileName,            // command line
                                    ref sa,                 // pointer to process SECURITY_ATTRIBUTES
                                    ref sa,                 // pointer to thread SECURITY_ATTRIBUTES
                                    true,                  // handles are not inheritable
                                    dwCreationFlags,        // creation flags
                                    IntPtr.Zero,            // pointer to new environment block 
                                    ps.WorkingDirectory,    // name of current directory 
                                    ref si,                 // pointer to STARTUPINFO structure
                                    out procInfo            // receives information about new process
                                    );

    // invalidate the handles
    CloseHandle(hProcess);
    CloseHandle(hPToken);
    CloseHandle(hUserTokenDup);

    return result; // return the result
 }
相关问题