Получить приложение для запуска от имени другого пользователя из службы Windows - PullRequest
0 голосов
/ 10 января 2019

Я провел много исследований и не уверен, почему это не работает, возможно, упустил что-то простое. Код запускает программу, но запускает ее как пользователь локальной системы, а не как предполагаемый пользователь.

Часть службы, которая выполняет код:

APIProcess.PROCESS_INFORMATION PI = new APIProcess.PROCESS_INFORMATION();
if (!APIProcess.Launch(@"C:\Windows\System32\notepad.exe", ".",
                "admin", "test", out string MSG, out PI))
            {
                logger.Debug(MSG);
            }
            else
            {
                logger.Debug(MSG);
                logger.Debug(PI.dwProcessID);
            }

Часть кода, которая имеет заднюю функцию:

public static bool Launch(string appCmdLine, string Domain, string Username, string Password,out string MSG, out PROCESS_INFORMATION pi)
    {
        MSG = "";
        pi = new PROCESS_INFORMATION();
        bool ret = false;

        IntPtr Token = IntPtr.Zero;

        if (LogonUserA(Username,Domain,Password,LogonType.LOGON_NEW_CREDENTIALS,LogonProvider.PROVIDER_WINNT50,ref Token))
        {
            if (Token != IntPtr.Zero)
            {
                IntPtr envBlock = GetEnvironmentBlock(Token);
                ret = LaunchProcessAsUser(appCmdLine, Token, envBlock, out MSG, out pi);
                MSG = string.Join(", ",Token.ToString(),envBlock.ToString());
                if (envBlock != IntPtr.Zero)
                    DestroyEnvironmentBlock(envBlock);


                CloseHandle(Token);
            }

        }
        else
        {
            MSG = "Failed To Logon User";
        }
        return ret;
    }

[DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUserA(
        string Username,
        string Domain,
        string Password,
        LogonType LogonType,
        LogonProvider LogonProvider,
        ref IntPtr Token);

private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock, out string Error, out PROCESS_INFORMATION pi)
    {
        bool result = false;
        Error = "";

        pi = new PROCESS_INFORMATION();
        SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
        SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
        saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
        saThread.nLength = (uint)Marshal.SizeOf(saThread);

        STARTUPINFO si = new STARTUPINFO();
        si.cb = (uint)Marshal.SizeOf(si);


        si.lpDesktop = @"WinSta0\Default"; //Modify as needed 
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
        si.wShowWindow = SW_SHOW;


        result = CreateProcessAsUser(
            token,
            null,
            cmdLine,
            ref saProcess,
            ref saThread,
            false,
            CREATE_UNICODE_ENVIRONMENT,
            envBlock,
            null,
            ref si,
            out pi);


        if (result == false)
        {
            int error = Marshal.GetLastWin32Error();
            string message = String.Format("CreateProcessAsUser Error: {0}", error);
            Error = message;
            //Debug.WriteLine(message);

        }

        return result;
    }

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool CreateProcessAsUser(
       IntPtr hToken,
       string lpApplicationName,
       string lpCommandLine,
       ref SECURITY_ATTRIBUTES lpProcessAttributes,
       ref SECURITY_ATTRIBUTES lpThreadAttributes,
       bool bInheritHandles,
       uint dwCreationFlags,
       IntPtr lpEnvironment,
       string lpCurrentDirectory,
       ref STARTUPINFO lpStartupInfo,
       out PROCESS_INFORMATION lpProcessInformation);

У меня есть запись в журнал, и похоже, что токен пользователя и токен окружения созданы просто отлично. Он также запускает намеченное приложение, но запускается как системный пользователь вместо предполагаемого пользователя олицетворения. Я могу заставить его работать, если под этим пользователем уже запущена программа. Для примера я изменил нужную программу для запуска, а также домен / имя пользователя / пароль.

1 Ответ

0 голосов
/ 10 января 2019

Проблема заключается в использовании типа LOGON_NEW_CREDENTIALS при вызове LogonUser. С документация :

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

Попробуйте вместо этого использовать LOGON32_LOGON_BATCH.

...