CreateProcessAsUser
От: solvitz Украина  
Дата: 17.09.11 19:23
Оценка:
Пытаюсь запустить из сервиса (SYSTEM) приложение, чтобы оно работало под учеткой текущего пользователя. Калькулятор запускается нормально а вот cmd.exe не получается. Значит последовательность моих действий: ищу explorer.exe, открываю его, беру его токен, копирую токен, создаю блок окружения и запускаю приложение. Все АПИшки возвращают нормальные значения но вот GetLastError говорит, что происходит ошибка.


OpenProcess - без ошибок
OpenProcessToken - без ошибок
DuplicateTokenEx - без ошибок
CreateEnvironmentBlock - ERROR_FILE_NOT_FOUND
CreateProcessAsUser - ERROR_INVALID_OWNER


Кто с подобным сталкивался? Помогите советом пожалуйста.
Re: CreateProcessAsUser
От: rus blood Россия  
Дата: 17.09.11 20:03
Оценка:
Здравствуйте, solvitz, Вы писали:

LoadUserProfile ?
Имею скафандр — готов путешествовать!
Re[2]: CreateProcessAsUser
От: solvitz Украина  
Дата: 17.09.11 20:19
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Здравствуйте, solvitz, Вы писали:


RB>LoadUserProfile ?


Нет, я эту функцию не использовал. Это из-за этого ошибки идут?
Re: CreateProcessAsUser
От: ononim  
Дата: 17.09.11 20:43
Оценка:
S>Пытаюсь запустить из сервиса (SYSTEM) приложение, чтобы оно работало под учеткой текущего пользователя. Калькулятор запускается нормально а вот cmd.exe не получается. Значит последовательность моих действий: ищу explorer.exe, открываю его, беру его токен, копирую токен, создаю блок окружения и запускаю приложение. Все АПИшки возвращают нормальные значения но вот GetLastError говорит, что происходит ошибка.
GetLastError не говорит о том что произошла ошибка (если в MSDN не указано обратного в конкретной API). GetLastEror говорит КАКАЯ произошла ошибка, если она произошла. Если ошибки не произошло — то что возвращает GetLastError мона юзать максимум в качестве seed'f для srand
Как много веселых ребят, и все делают велосипед...
Re[2]: CreateProcessAsUser
От: solvitz Украина  
Дата: 17.09.11 22:40
Оценка:
Здравствуйте, ononim, Вы писали:

S>>Пытаюсь запустить из сервиса (SYSTEM) приложение, чтобы оно работало под учеткой текущего пользователя. Калькулятор запускается нормально а вот cmd.exe не получается. Значит последовательность моих действий: ищу explorer.exe, открываю его, беру его токен, копирую токен, создаю блок окружения и запускаю приложение. Все АПИшки возвращают нормальные значения но вот GetLastError говорит, что происходит ошибка.

O>GetLastError не говорит о том что произошла ошибка (если в MSDN не указано обратного в конкретной API). GetLastEror говорит КАКАЯ произошла ошибка, если она произошла. Если ошибки не произошло — то что возвращает GetLastError мона юзать максимум в качестве seed'f для srand
Получается, что ошибок не было так как функции вернули TRUE, тогда почему не запускается cmd.exe?
Re[2]: CreateProcessAsUser
От: solvitz Украина  
Дата: 17.09.11 22:46
Оценка:
Здравствуйте, ononim, Вы писали:

S>>Пытаюсь запустить из сервиса (SYSTEM) приложение, чтобы оно работало под учеткой текущего пользователя. Калькулятор запускается нормально а вот cmd.exe не получается. Значит последовательность моих действий: ищу explorer.exe, открываю его, беру его токен, копирую токен, создаю блок окружения и запускаю приложение. Все АПИшки возвращают нормальные значения но вот GetLastError говорит, что происходит ошибка.

O>GetLastError не говорит о том что произошла ошибка (если в MSDN не указано обратного в конкретной API). GetLastEror говорит КАКАЯ произошла ошибка, если она произошла. Если ошибки не произошло — то что возвращает GetLastError мона юзать максимум в качестве seed'f для srand
Ага получается ошибки нет раз функция вернула TRUE, тогда почему не запускается cmd.exe?
Re[3]: CreateProcessAsUser
От: ononim  
Дата: 17.09.11 22:55
Оценка:
S>Получается, что ошибок не было так как функции вернули TRUE, тогда почему не запускается cmd.exe?
а он точно не запускается? В taskmanager или Process Explorer'е его не видно?
Как много веселых ребят, и все делают велосипед...
Re[4]: CreateProcessAsUser
От: solvitz Украина  
Дата: 17.09.11 22:58
Оценка:
Здравствуйте, ononim, Вы писали:

S>>Получается, что ошибок не было так как функции вернули TRUE, тогда почему не запускается cmd.exe?

O>а он точно не запускается? В taskmanager или Process Explorer'е его не видно?
Все GUI'шные проги запускаются, а cmd.exe нивкакую уже мозги кипят не могу понять в чем дело.
Re[5]: CreateProcessAsUser
От: мыщъх США http://nezumi-lab.org
Дата: 18.09.11 01:29
Оценка:
Здравствуйте, solvitz, Вы писали:

S>Здравствуйте, ononim, Вы писали:


S>>>Получается, что ошибок не было так как функции вернули TRUE, тогда почему не запускается cmd.exe?

O>>а он точно не запускается? В taskmanager или Process Explorer'е его не видно?
S>Все GUI'шные проги запускаются, а cmd.exe нивкакую уже мозги кипят не могу понять в чем дело.
баян ведь: http://verbalprocessor.com/2007/12/05/running-a-cmd-prompt-as-local-system/
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re[6]: CreateProcessAsUser
От: мыщъх США http://nezumi-lab.org
Дата: 18.09.11 01:33
Оценка: 6 (1) :)
Здравствуйте, мыщъх, Вы писали:

М>Здравствуйте, solvitz, Вы писали:


S>>Здравствуйте, ononim, Вы писали:


S>>>>Получается, что ошибок не было так как функции вернули TRUE, тогда почему не запускается cmd.exe?

O>>>а он точно не запускается? В taskmanager или Process Explorer'е его не видно?
S>>Все GUI'шные проги запускаются, а cmd.exe нивкакую уже мозги кипят не могу понять в чем дело.
М>баян ведь: http://verbalprocessor.com/2007/12/05/running-a-cmd-prompt-as-local-system/
тьфу. баян, да не тот: http://forum.sysinternals.com/why-does-this-work-createprocessasuser_topic25936.html
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Re: CreateProcessAsUser
От: okman Беларусь https://searchinform.ru/
Дата: 18.09.11 04:45
Оценка:
Здравствуйте, solvitz, Вы писали:

S>Пытаюсь запустить из сервиса (SYSTEM) приложение, чтобы оно работало под учеткой текущего пользователя. Калькулятор запускается нормально а вот cmd.exe не получается. Значит последовательность моих действий: ищу explorer.exe, открываю его, беру его токен, копирую токен, создаю блок окружения и запускаю приложение. Все АПИшки возвращают нормальные значения но вот GetLastError говорит, что происходит ошибка.

S>Кто с подобным сталкивался? Помогите советом пожалуйста.

Этот вопрос разбирался на RSDN по косточкам много раз, нужно просто воспользоваться поиском.
Я кое-где приводил код с подробными комментариями и ссылками на другие источники.
Отсылаю вот к этой теме — http://www.rsdn.ru/forum/winapi/4195821.flat.aspx
Автор: kovbas
Дата: 15.03.11
Re: CreateProcessAsUser
От: Jolly Roger  
Дата: 18.09.11 04:46
Оценка: 6 (1)
Здравствуйте, solvitz, Вы писали:

S>Пытаюсь запустить из сервиса (SYSTEM) приложение, чтобы оно работало под учеткой текущего пользователя. Калькулятор запускается нормально а вот cmd.exe не получается. Значит последовательность моих действий: ищу explorer.exe, открываю его, беру его токен, копирую токен, создаю блок окружения и запускаю приложение. Все АПИшки возвращают нормальные значения но вот GetLastError говорит, что происходит ошибка.



S>
S>OpenProcess - без ошибок
S>OpenProcessToken - без ошибок
S>DuplicateTokenEx - без ошибок
S>CreateEnvironmentBlock - ERROR_FILE_NOT_FOUND
S>CreateProcessAsUser - ERROR_INVALID_OWNER
S>


S>Кто с подобным сталкивался? Помогите советом пожалуйста.


В Вашем вопросе недостаёт информации. Необходимо знать целевую ОС, так как на разных системах действия отличаются. Также нужно указать, в какой оконной станции (в случае W2k или более ранней ОС) или в какой сессии (WinXP и более поздние) должна работать запускаемое приложение.

В качестве примера, вот такой код на WinXP запускает CMD в интерактивной сессии без проблем как от имени системы, так и от имени текущего интерактивного юзера


  пример на C#
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public partial class RunApp : ServiceBase, IRunApp
    {
        ServiceHost WcfHost;
        IPermission admins;

        public string[] Arguments;

        bool IRunApp.CreateProcess(string FileName, string Arguments, 
            string CurrentDir, string DesktopName, bool UseServiceAccount, 
            out string ErrorText)
        {
            admins.Demand();
            var SessId = WTSGetActiveConsoleSessionId();
            WriteEventLog(string.Format("SessId = {0}", SessId));
            int R;
            IntPtr pBuf = new IntPtr();
            Int32 bufLen;
            if (!WTSQuerySessionInformation(
                IntPtr.Zero, SessId, WTSConnectState, out pBuf, out bufLen))
            {
                R = Marshal.GetLastWin32Error();
                ErrorText = string.Format(
                    "Query session information failed({0}: {1}",
                    R, GetErrorMessage(R));
                return false;
            }

            WTS_CONNECTSTATE_CLASS state =
                (WTS_CONNECTSTATE_CLASS)Marshal.ReadInt32(pBuf);
            WTSFreeMemory(pBuf);

            if (state != WTS_CONNECTSTATE_CLASS.WTSActive)
            {
                ErrorText =
                    string.Format("Console session is inactive. Current state = {0}", state);
                return false;
            }

            R = RunInteractiveProcess(
                SessId, FileName, Arguments, DesktopName, UseServiceAccount);
            if (R != 0)
            {
                ErrorText = string.Format(
                    "RunInteractiveProcess failed({0}): {1}", R, GetErrorMessage(R));
                return false;
            }

            ErrorText = "";
            return true;
        }

        public RunApp()
        {
            InitializeComponent();
            EventLog.Source = this.ServiceName;
        }

        public void AddUsers(NetPeerTcpBinding binding)
        {
        }

        protected override void OnStart(string[] args)
        {
            var id = new SecurityIdentifier(
                WellKnownSidType.BuiltinAdministratorsSid, null);
            var ntId = id.Translate(typeof(NTAccount));
            admins = new PrincipalPermission(null, ntId.ToString());

            WcfHost = new ServiceHost(this);
            //var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport);
            var binding = new NetNamedPipeBinding();
            //binding.Security.Transport.ProtectionLevel = 
                //System.Net.Security.ProtectionLevel.EncryptAndSign;
            var endPoint = WcfHost.AddServiceEndpoint(
                typeof(IRunApp), binding, "net.pipe://localhost/RunAppService");
            WcfHost.Open();
        }

        protected override void OnStop()
        {
            WcfHost.Close();
            admins = null;
        }

        private void Execute()
        {
        }

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

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

        const UInt32 WTSConnectState = 8;

        enum WTS_CONNECTSTATE_CLASS
        {
            WTSActive,
            WTSConnected,
            WTSConnectQuery,
            WTSShadow,
            WTSDisconnected,
            WTSIdle,
            WTSListen,
            WTSReset,
            WTSDown,
            WTSInit
        }

        [DllImport("kernel32.dll")]
        public static extern int FormatMessage(
            int Flags, IntPtr Source, int MessageID, int LanguageID,
            StringBuilder Buffer, int Size, IntPtr Args);

        public static string GetErrorMessage(int ErrorCode)
        {
            var buf = new StringBuilder(256);
            int len = FormatMessage(0x1200, IntPtr.Zero,
                ErrorCode, 0, buf, buf.Capacity, IntPtr.Zero);
            if (len <= 0) return "";
            int k = buf.Length - 1;
            for (; k > 0; k--)
            {
                char u = buf[k];
                if (u > ' ' && u != '.') break;
            }
            buf.Length = k + 1;
            buf.Append('.');
            return buf.ToString();
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll")]
        public static extern Int32 WTSGetActiveConsoleSessionId();

        [DllImport("Wtsapi32.dll", SetLastError = true)]
        static extern bool WTSQueryUserToken(Int32 SessionId, ref IntPtr hToken);

        [DllImport("Wtsapi32.dll", SetLastError = true)]
        static extern bool WTSQuerySessionInformation(
            IntPtr hServer, Int32 SessionId, UInt32 WTSInfoClass,
            out IntPtr ppBuffer, out Int32 BytesReturned);

        [DllImport("Wtsapi32.dll")]
        static extern void WTSFreeMemory(IntPtr pBuf);

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

        [DllImport("kernel32.dll")]
        static extern IntPtr GetCurrentProcess();

        [DllImport("advapi32", SetLastError = true)]
        static extern bool OpenProcessToken(
            IntPtr ProcessHandle, Int32 DesiredAccess, ref IntPtr TokenHandle);

        [DllImport("userenv.dll", SetLastError = true)]
        static extern bool CreateEnvironmentBlock(
            ref IntPtr lpEnvironment, IntPtr hToken, Boolean bInherit);

        [DllImport("userenv.dll", SetLastError = true)]
        static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment);

        [DllImport("advapi32.dll", SetLastError = true)]
        static extern bool SetTokenInformation(
            IntPtr TokenHandle, UInt32 TokenInformationClass, 
            ref Int32 TokenInformation, Int32 TokenInformationLength);

        [Conditional("LOG_ON")]
        private void WriteEventLog(string s) { EventLog.WriteEntry(s); }

        private int RunInteractiveProcess(
            Int32 SessId, string FileName, string Args, string Desktop, bool AsSystem)
        {
            WriteEventLog("Enter");
            var userToken = IntPtr.Zero; ;
            var Environment = IntPtr.Zero;
            try
            {
                int result;
                if (AsSystem)
                {
                    if (!OpenProcessToken(GetCurrentProcess(), 0x2000000, ref userToken))
                        return Marshal.GetLastWin32Error();
                    if (!SetTokenInformation(userToken, 12, ref SessId, Marshal.SizeOf(SessId)))
                        return Marshal.GetLastWin32Error();
                }
                else
                {
                    if (!WTSQueryUserToken(SessId, ref userToken))
                    {
                        result = Marshal.GetLastWin32Error();
                        WriteEventLog(string.Format("QueryToken = {0}", result));
                        return result;
                    }
                    if (!CreateEnvironmentBlock(ref Environment, userToken, false))
                        return Marshal.GetLastWin32Error();
                    WriteEventLog("Environment created");
                }

                var SI = new STARTUPINFO();
                SI.cb = Marshal.SizeOf(SI);
                SI.lpDesktop = Desktop;
                UInt32 ctorFlags = 0;
                if (Environment != IntPtr.Zero) ctorFlags |= 0x400;
                var PI = new PROCESS_INFORMATION();
                WriteEventLog("Before create process");
                if (CreateProcessAsUser(userToken,
                    FileName, Args, IntPtr.Zero, IntPtr.Zero, false,
                    ctorFlags, Environment, null, ref SI, out PI))
                {
                    CloseHandle(PI.hProcess);
                    CloseHandle(PI.hThread);
                }
                else
                    return Marshal.GetLastWin32Error();
            }
            finally
            {
                WriteEventLog("Finally");
                if (userToken != IntPtr.Zero) CloseHandle(userToken);
                if (Environment != IntPtr.Zero) DestroyEnvironmentBlock(Environment);
            }
            WriteEventLog("Leave - Success");
            return 0;
        }
    }


Это я знакомился с сервисами в NET, поэтому не рассматривайте его как боевой.
"Нормальные герои всегда идут в обход!"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.