CreateProcessAsUser неправильно настраивает пользователя - PullRequest
0 голосов
/ 09 февраля 2011

Вызов приложения с графическим интерфейсом с помощью

[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 Service работает. Окно появляется на экране пользователя, но пользователь процесса по-прежнему 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 ]

2 голосов
/ 09 февраля 2011

В моем сервисе я использую WTSGetActiveConsoleSessionId(), WTSQueryUserToken() и DuplicationTokenEx() перед вызовом CreateProcessAsUser(), и он прекрасно работает для меня.Порожденный процесс выполняется в учетной записи пользователя, а не в учетной записи службы.

2 голосов
/ 09 февраля 2011

Похоже, вместо того, чтобы использовать DuplicateTokenEx для копирования текущего токена, вам нужно вызвать LogonUser, чтобы получить токен, который представляет целевого пользователя. Простой вызов DuplicateTokenEx создаст токен для пользователя локальной системы ... если я правильно понимаю ваш фрагмент кода.

Кроме того, поскольку вы нацелены на интерактивного пользователя, рассмотрите вместо него функцию CreateProcessWithLogonW .

0 голосов
/ 20 января 2014

Спасибо Реми Лебо за подсказку для использования WTSGetActiveConsoleSessionId ()

Приведенная ниже функция должна вызываться из «System» -пользователя как 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
 }
...