Код ошибки CreateProcessAsUser 6 - PullRequest
0 голосов
/ 08 июня 2018

Я использую LogonUser для получения токена основного пользователя, а затем API-интерфейсы CreateProcessAsUser для создания процесса.Но я получаю код ошибки 6. Не уверен, в чем проблема.Ниже приведен код.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LogOnUserTestWindows
{
    using System;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Security.Principal;

    class Program
    {
        // Define the Windows LogonUser and CloseHandle functions.
        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        internal static extern bool LogonUser(String username, String domain, IntPtr password,
                int logonType, int logonProvider, ref IntPtr token);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);

        private enum SW
        {
            SW_HIDE = 0,
            SW_SHOWNORMAL = 1,
            SW_NORMAL = 1,
            SW_SHOWMINIMIZED = 2,
            SW_SHOWMAXIMIZED = 3,
            SW_MAXIMIZE = 3,
            SW_SHOWNOACTIVATE = 4,
            SW_SHOW = 5,
            SW_MINIMIZE = 6,
            SW_SHOWMINNOACTIVE = 7,
            SW_SHOWNA = 8,
            SW_RESTORE = 9,
            SW_SHOWDEFAULT = 10,
            SW_MAX = 10
        }


        [StructLayout(LayoutKind.Sequential)]
        private struct STARTUPINFO
        {
            public int cb;
            public String lpReserved;
            public String lpDesktop;
            public String lpTitle;
            public uint dwX;
            public uint dwY;
            public uint dwXSize;
            public uint dwYSize;
            public uint dwXCountChars;
            public uint dwYCountChars;
            public uint dwFillAttribute;
            public uint dwFlags;
            public short wShowWindow;
            public short cbReserved2;
            public IntPtr lpReserved2;
            public IntPtr hStdInput;
            public IntPtr hStdOutput;
            public IntPtr hStdError;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct PROCESS_INFORMATION
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public uint dwProcessId;
            public uint dwThreadId;
        }


        [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        private static extern bool CreateProcessAsUser(
                IntPtr hToken,
                String lpApplicationName,
                String lpCommandLine,
                IntPtr lpProcessAttributes,
                IntPtr lpThreadAttributes,
                bool bInheritHandle,
                uint dwCreationFlags,
                IntPtr lpEnvironment,
                String lpCurrentDirectory,
                ref STARTUPINFO lpStartupInfo,
                out PROCESS_INFORMATION lpProcessInformation);
        // Define the required LogonUser enumerations.
        const int LOGON32_PROVIDER_DEFAULT = 0;
        const int LOGON32_LOGON_INTERACTIVE = 2;

        private const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
        private const int CREATE_NO_WINDOW = 0x08000000;

        private const int CREATE_NEW_CONSOLE = 0x00000010;


        static void Main()
        {
            // Display the current user before impersonation.
            Console.WriteLine("Before impersonation: {0}",
                              WindowsIdentity.GetCurrent().Name);

            // Ask the user for a network domain.
            Console.Write("Please enter your domain: ");
            string domain = Console.ReadLine();

            // Ask the user for a user name.
            Console.Write("Please enter your user name: ");
            string username = Console.ReadLine();

            // Ask the user for a password.
            Console.Write("Please enter your password: ");
            SecureString passWord = GetPassword();

            // Impersonate the account provided by the user.
            try
            {
                //WindowsImpersonationContext userContext = ImpersonateUser(passWord, username, domain);
                IntPtr token = ImpersonateUser(passWord, username, domain);

                // Display the current user after impersonation.
                Console.WriteLine("After impersonation: {0}",
                                  WindowsIdentity.GetCurrent().Name);
            }
            catch (ArgumentException e)
            {
                Console.WriteLine("{0}: {1}", e.GetType().Name, e.Message);
            }
            catch (Win32Exception e)
            {
                Console.WriteLine("{0}: {1}", e.GetType().Name, e.Message);
            }
            finally
            {
                passWord.Dispose();
            }
        }

        public static SecureString GetPassword()
        {
            SecureString password = new SecureString();

            // get the first character of the password
            ConsoleKeyInfo nextKey = Console.ReadKey(true);

            while (nextKey.Key != ConsoleKey.Enter)
            {
                if (nextKey.Key == ConsoleKey.Backspace)
                {
                    if (password.Length > 0)
                    {
                        password.RemoveAt(password.Length - 1);

                        // erase the last * as well
                        Console.Write(nextKey.KeyChar);
                        Console.Write(" ");
                        Console.Write(nextKey.KeyChar);
                    }
                }
                else
                {
                    password.AppendChar(nextKey.KeyChar);
                    Console.Write("*");
                }

                nextKey = Console.ReadKey(true);
            }

            Console.WriteLine();

            // lock the password down
            password.MakeReadOnly();
            return password;
        }

        public static IntPtr ImpersonateUser(SecureString password, string userName, string domainName)
        {
            IntPtr tokenHandle = IntPtr.Zero;
            IntPtr passwordPtr = IntPtr.Zero;
            bool returnValue = false;
            int error = 0;

            // Marshal the SecureString to unmanaged memory.
            passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password);

            // Pass LogonUser the unmanaged (and decrypted) copy of the password.
            returnValue = LogonUser(userName, domainName, passwordPtr,
                                    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                                    ref tokenHandle);
            if (!returnValue && tokenHandle == IntPtr.Zero)
                error = Marshal.GetLastWin32Error();

            // Perform cleanup whether or not the call succeeded.
            // Zero-out and free the unmanaged string reference.
            Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr);
            // Close the token handle.
            CloseHandle(tokenHandle);

            // Throw an exception if an error occurred.
            if (error != 0)
            {
                throw new System.ComponentModel.Win32Exception(error);
            }
            // The token that is passed to the following constructor must 
            // be a primary token in order to use it for impersonation.
            //WindowsIdentity newId = new WindowsIdentity(tokenHandle);

            //String workgroup;
            string cmdLine = null;
            string workDir = null;
            bool visible = true;
            var pEnv = IntPtr.Zero;
            var startInfo = new STARTUPINFO();
            var procInfo = new PROCESS_INFORMATION();
            int iResultOfCreateProcessAsUser;

            uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
            startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE);
            startInfo.lpDesktop = "winsta0\\default";




            if (!CreateProcessAsUser(
                tokenHandle,
                "C:/Windows/System32/notepad.exe", // Application Name
                cmdLine, // Command Line
                IntPtr.Zero,
                IntPtr.Zero,
                false,
                dwCreationFlags,
                pEnv,
                workDir, // Working directory
                ref startInfo,
                out procInfo))
            {
                iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();

                throw new Exception("StartProcessAsCurrentUser: CreateProcessAsUser failed.  Error Code -" + iResultOfCreateProcessAsUser);
            }
            return tokenHandle;
        }
    }
}

Ниже приведена ошибка

System.Exception
  HResult=0x80131500
  Message=StartProcessAsCurrentUser: CreateProcessAsUser failed.  Error Code -6
  Source=LogOnUserTestWindows
  StackTrace:
   at LogOnUserTestWindows.Program.ImpersonateUser(SecureString password, String userName, String domainName) in C:\Users\santosh\source\repos\LogOnUserTestWindows\LogOnUserTestWindows\Program.cs:line 242
   at LogOnUserTestWindows.Program.Main() in C:\Users\santosh\source\repos\LogOnUserTestWindows\LogOnUserTestWindows\Program.cs:line 122

Мне не удалось найти надлежащую документацию для API logonUser и CreateProcessAsUser.Я пытаюсь запустить этот код на моей машине, которая имеет несколько вариантов использования.Я вошел в систему от одного пользователя и пытаюсь создать процесс от другого пользователя.Было бы здорово, если бы кто-нибудь указал мне на соответствующую документацию или примерыПожалуйста помоги.Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Вы закрыли tokenHandle перед тем, как передать его CreateProcessAsUser.

Результат: ERROR_INVALID_HANDLE (= 6).

0 голосов
/ 08 июня 2018

Пожалуйста, попробуйте вместо этого CreateProcessWithToken, хотя я не знаю, почему функция вернула код ошибки -6, но несколько дней назад я пытался запустить приложение с указанным токеном пользователя, но CreateProcessAsUser не работал, но CreateProcessWithToken сделал,Может быть, это также сработает для вас, удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...