2015-05-08 23 views
6

Mam trudny czas, aby uzyskać bardzo konkretny przypadek użycia do pracy. Omawiana aplikacja składa się z dwóch komponentów: usługi systemu Windows, która musi działać w uprzywilejowanym kontekście poza pulpitem (tj. Aby akceptować połączenia, gdy użytkownik jest zalogowany) i aplikacji klienta WinForm. Usługa akceptuje połączenia websocket, a jeśli żądanie połączenia się powiedzie, ma to na celu zalogowanie użytkownika interaktywnie (na pulpit) i odrodzenie procesu jako tego użytkownika z dostępem do pulpitu. Użyłem poniższych linków, i chociaż są w stanie podszyć się pod użytkownika, to nie logują użytkownika na pulpicie, tzn. Jeśli oglądam system za pomocą VNC, lub jeśli testuję go w moim lokalnym systemie, użytkownik nie jest zalogowany. Proces jest jednak odradzany jako użytkownik, ale oczywiście nie ma dostępu do komputera.Usługa administracyjna: zaloguj użytkownika na pulpit, odradzam proces, który może wchodzić w interakcje z komputerem stacjonarnym.

Czy ktoś ma próbkę kodu, która zaloguje użytkownika na pulpit?

linki i kod Próbowałem:

Using Process.Start() to start a process as a different user from within a Windows Service

How to use LogonUser properly to impersonate domain user from workgroup client publicznego

Launch a process under another user's credentials

https://social.msdn.microsoft.com/Forums/vstudio/en-US/9fb068b0-507b-4b6b-879a-b0fbe492ba92/c-start-program-with-different-user-credentials

Bieżący kod jest:

using Cassia; 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Diagnostics; 
using System.DirectoryServices; 
using System.Runtime.InteropServices; 
using System.Security; 
using System.Security.Permissions; 
using System.Security.Principal; 
using System.ServiceProcess; 

namespace program 
{ 
    public partial class service 
    { 
     #region Interop 

     [StructLayout(LayoutKind.Sequential)] 
     public struct LUID 
     { 
      public UInt32 LowPart; 
      public Int32 HighPart; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct LUID_AND_ATTRIBUTES 
     { 
      public LUID Luid; 
      public UInt32 Attributes; 
     } 

     public struct TOKEN_PRIVILEGES 
     { 
      public UInt32 PrivilegeCount; 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] 
      public LUID_AND_ATTRIBUTES[] Privileges; 
     } 

     enum TOKEN_INFORMATION_CLASS 
     { 
      TokenUser = 1, 
      TokenGroups, 
      TokenPrivileges, 
      TokenOwner, 
      TokenPrimaryGroup, 
      TokenDefaultDacl, 
      TokenSource, 
      TokenType, 
      TokenImpersonationLevel, 
      TokenStatistics, 
      TokenRestrictedSids, 
      TokenSessionId, 
      TokenGroupsAndPrivileges, 
      TokenSessionReference, 
      TokenSandBoxInert, 
      TokenAuditPolicy, 
      TokenOrigin, 
      TokenElevationType, 
      TokenLinkedToken, 
      TokenElevation, 
      TokenHasRestrictions, 
      TokenAccessInformation, 
      TokenVirtualizationAllowed, 
      TokenVirtualizationEnabled, 
      TokenIntegrityLevel, 
      TokenUIAccess, 
      TokenMandatoryPolicy, 
      TokenLogonSid, 
      MaxTokenInfoClass 
     } 

     [Flags] 
     enum CreationFlags : uint 
     { 
      CREATE_BREAKAWAY_FROM_JOB = 0x01000000, 
      CREATE_DEFAULT_ERROR_MODE = 0x04000000, 
      CREATE_NEW_CONSOLE = 0x00000010, 
      CREATE_NEW_PROCESS_GROUP = 0x00000200, 
      CREATE_NO_WINDOW = 0x08000000, 
      CREATE_PROTECTED_PROCESS = 0x00040000, 
      CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000, 
      CREATE_SEPARATE_WOW_VDM = 0x00001000, 
      CREATE_SUSPENDED = 0x00000004, 
      CREATE_UNICODE_ENVIRONMENT = 0x00000400, 
      DEBUG_ONLY_THIS_PROCESS = 0x00000002, 
      DEBUG_PROCESS = 0x00000001, 
      DETACHED_PROCESS = 0x00000008, 
      EXTENDED_STARTUPINFO_PRESENT = 0x00080000 
     } 

     public enum TOKEN_TYPE 
     { 
      TokenPrimary = 1, 
      TokenImpersonation 
     } 

     public enum SECURITY_IMPERSONATION_LEVEL 
     { 
      SecurityAnonymous, 
      SecurityIdentification, 
      SecurityImpersonation, 
      SecurityDelegation 
     } 

     [Flags] 
     enum LogonFlags 
     { 
      LOGON_NETCREDENTIALS_ONLY = 2, 
      LOGON_WITH_PROFILE = 1 
     } 

     enum LOGON_TYPE 
     { 
      LOGON32_LOGON_INTERACTIVE = 2, 
      LOGON32_LOGON_NETWORK, 
      LOGON32_LOGON_BATCH, 
      LOGON32_LOGON_SERVICE, 
      LOGON32_LOGON_UNLOCK = 7, 
      LOGON32_LOGON_NETWORK_CLEARTEXT, 
      LOGON32_LOGON_NEW_CREDENTIALS 
     } 

     enum LOGON_PROVIDER 
     { 
      LOGON32_PROVIDER_DEFAULT, 
      LOGON32_PROVIDER_WINNT35, 
      LOGON32_PROVIDER_WINNT40, 
      LOGON32_PROVIDER_WINNT50 
     } 

     struct SECURITY_ATTRIBUTES 
     { 
      public uint Length; 
      public IntPtr SecurityDescriptor; 
      public bool InheritHandle; 
     } 

     [Flags] 
     enum SECURITY_INFORMATION : uint 
     { 
      OWNER_SECURITY_INFORMATION = 0x00000001, 
      GROUP_SECURITY_INFORMATION = 0x00000002, 
      DACL_SECURITY_INFORMATION = 0x00000004, 
      SACL_SECURITY_INFORMATION = 0x00000008, 
      UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000, 
      UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000, 
      PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000, 
      PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000 
     } 

     [StructLayoutAttribute(LayoutKind.Sequential)] 
     struct SECURITY_DESCRIPTOR 
     { 
      public byte revision; 
      public byte size; 
      public short control; // public SECURITY_DESCRIPTOR_CONTROL control; 
      public IntPtr owner; 
      public IntPtr group; 
      public IntPtr sacl; 
      public IntPtr dacl; 
     } 

     struct STARTUPINFO 
     { 
      public uint cb; 
      [MarshalAs(UnmanagedType.LPTStr)] 
      public string Reserved; 
      [MarshalAs(UnmanagedType.LPTStr)] 
      public string Desktop; 
      [MarshalAs(UnmanagedType.LPTStr)] 
      public string Title; 
      public uint X; 
      public uint Y; 
      public uint XSize; 
      public uint YSize; 
      public uint XCountChars; 
      public uint YCountChars; 
      public uint FillAttribute; 
      public uint Flags; 
      public ushort ShowWindow; 
      public ushort Reserverd2; 
      public byte bReserverd2; 
      public IntPtr StdInput; 
      public IntPtr StdOutput; 
      public IntPtr StdError; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     struct PROCESS_INFORMATION 
     { 
      public IntPtr Process; 
      public IntPtr Thread; 
      public uint ProcessId; 
      public uint ThreadId; 
     } 

     [DllImport("advapi32.dll", SetLastError = true)] 
     static extern bool InitializeSecurityDescriptor(IntPtr pSecurityDescriptor, uint dwRevision); 
     const uint SECURITY_DESCRIPTOR_REVISION = 1; 

     [DllImport("advapi32.dll", SetLastError = true)] 
     static extern bool SetSecurityDescriptorDacl(ref SECURITY_DESCRIPTOR sd, bool daclPresent, IntPtr dacl, bool daclDefaulted); 

     [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     extern static bool DuplicateTokenEx(
      IntPtr hExistingToken, 
      uint dwDesiredAccess, 
      ref SECURITY_ATTRIBUTES lpTokenAttributes, 
      SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, 
      TOKEN_TYPE TokenType, 
      out IntPtr phNewToken); 

     [DllImport("advapi32.dll", SetLastError = true)] 
     public static extern bool LogonUser(
      string lpszUsername, 
      string lpszDomain, 
      string lpszPassword, 
      int dwLogonType, 
      int dwLogonProvider, 
      out IntPtr phToken 
      ); 

     [DllImport("advapi32.dll", SetLastError = true)] 
     static extern bool GetTokenInformation(
      IntPtr TokenHandle, 
      TOKEN_INFORMATION_CLASS TokenInformationClass, 
      IntPtr TokenInformation, 
      int TokenInformationLength, 
      out int ReturnLength 
      ); 

     [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     static extern bool CreateProcessAsUser(
      IntPtr Token, 
      [MarshalAs(UnmanagedType.LPTStr)] string ApplicationName, 
      [MarshalAs(UnmanagedType.LPTStr)] string CommandLine, 
      ref SECURITY_ATTRIBUTES ProcessAttributes, 
      ref SECURITY_ATTRIBUTES ThreadAttributes, 
      bool InheritHandles, 
      uint CreationFlags, 
      IntPtr Environment, 
      [MarshalAs(UnmanagedType.LPTStr)] string CurrentDirectory, 
      ref STARTUPINFO StartupInfo, 
      out PROCESS_INFORMATION ProcessInformation); 

     [DllImport("Kernel32.dll")] 
     extern static int CloseHandle(IntPtr handle); 

     [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] 
     internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen); 

     [DllImport("advapi32.dll", SetLastError = true)] 
     internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid); 

     [StructLayout(LayoutKind.Sequential, Pack = 1)] 
     internal struct TokPriv1Luid 
     { 
      public int Count; 
      public long Luid; 
      public int Attr; 
     } 

     internal const int SE_PRIVILEGE_ENABLED = 0x00000002; 
     internal const int TOKEN_QUERY = 0x00000008; 
     internal const int TOKEN_DUPLICATE = 0x0002; 
     internal const int TOKEN_ASSIGN_PRIMARY = 0x0001; 

     #endregion 

     public static bool LoginUser(string domain, string username, string password, string program, string workingDir) 
     { 
      IntPtr token = IntPtr.Zero; 
      IntPtr primaryToken = IntPtr.Zero; 

      try 
      { 
       bool result = LogonUser(username, domain, password, (int)LOGON_TYPE.LOGON32_LOGON_NETWORK, (int)LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out token); 
       if (!result) 
       { 
        int winError = Marshal.GetLastWin32Error(); 
        Console.WriteLine("LoginUser unable to login user " + username + ", error: " + winError); 
        return false; 
       } 

       SECURITY_ATTRIBUTES processAttributes = new SECURITY_ATTRIBUTES(); 
       SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR(); 
       IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(sd)); 
       Marshal.StructureToPtr(sd, ptr, false); 
       InitializeSecurityDescriptor(ptr, SECURITY_DESCRIPTOR_REVISION); 
       sd = (SECURITY_DESCRIPTOR)Marshal.PtrToStructure(ptr, typeof(SECURITY_DESCRIPTOR)); 

       result = SetSecurityDescriptorDacl(ref sd, true, IntPtr.Zero, false); 
       if (!result) 
       { 
        int winError = Marshal.GetLastWin32Error(); 
       } 

       primaryToken = new IntPtr(); 
       result = DuplicateTokenEx(token, 0, ref processAttributes, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out primaryToken); 
       if (!result) 
       { 
        int winError = Marshal.GetLastWin32Error(); 
       } 

       processAttributes.SecurityDescriptor = ptr; 
       processAttributes.Length = (uint)Marshal.SizeOf(sd); 
       processAttributes.InheritHandle = true; 

       SECURITY_ATTRIBUTES threadAttributes = new SECURITY_ATTRIBUTES(); 
       threadAttributes.SecurityDescriptor = IntPtr.Zero; 
       threadAttributes.Length = 0; 
       threadAttributes.InheritHandle = false; 

       bool inheritHandles = true; 
       IntPtr environment = IntPtr.Zero; 

       STARTUPINFO startupInfo = new STARTUPINFO(); 
       startupInfo.Desktop = ""; 

       PROCESS_INFORMATION processInformation; 

       result = CreateProcessAsUser(
        primaryToken, 
        program, 
        program, 
        ref processAttributes, 
        ref threadAttributes, 
        inheritHandles, 
        16, 
        environment, 
        workingDir, 
        ref startupInfo, 
        out processInformation); 

       if (!result) 
       { 
        int winError = Marshal.GetLastWin32Error(); 
        Console.WriteLine("LoginUser unable to create process as user " + username + ", error: " + winError); 
        return false; 
       } 

       return true; 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("LoginUser exception encountered: " + e.Message()); 
       return false; 
      } 
      finally 
      { 
       if (token != IntPtr.Zero) 
       { 
        int x = CloseHandle(token); 
        if (x == 0) 
         throw new Win32Exception(Marshal.GetLastWin32Error()); 
        x = CloseHandle(primaryToken); 
        if (x == 0) 
         throw new Win32Exception(Marshal.GetLastWin32Error()); 
       } 
      } 
     } 

     public static SecureString securePassword(string password) 
     { 
      if (string_null(password)) return null; 
      SecureString secure = new SecureString(); 
      foreach (char c in password) 
      { 
       secure.AppendChar(c); 
      } 
      return secure; 
     } 
    } 
} 

A moim celem jest, aby móc nazwać to po prostu jako:

if (!LoginUser("machinename", "username", "password", "c:\\path\\to\\program.exe", "c:\\path\\to")) 
{ 
    // error 
} 
else 
{ 
    // success, user is logged into desktop and app is launch 
    // as user with desktop access 
} 

Odpowiedz

3

miałem ten sam scenariusz przed i wszystko się komplikuje, więc po prostu stosować PSEXEC w połączeniu z Process.Start

Podobnie jak przy użyciu PSEXEC co jest wskazane na ich próbki wszystko co musisz zrobić, to coś takiego

Kopiuj lub zainstalować plik wykonywalny poprzez dorsza e lub ręcznie (tj. program.exe) do zdalnego systemu i wykonać go interaktywnie, działa pod Danny Glover rachunku:

psexec \\workstation64 -c program.exe -u YourUser -p YourPa55w0rd 

Teraz znasz swoje parametry można użyć Process.Start, aby go uruchomić. Tak będzie wyglądać następująco

using System.Diagnostics; 
... 
Process process = new Process(); 
process.StartInfo.FileName = "program.exe"; 
process.StartInfo.Arguments = "\\workstation64 -c program.exe -u YourUser -p YourPa55w0rd"; 
process.Start(); 
process.WaitForExit(); 

Przy okazji można dowiedzieć się więcej i pobrać PSEXEC tutaj http://ss64.com/nt/psexec.html

+0

Cześć Raymund, czy to faktycznie zaloguje użytkownika YourUser na pulpit i uruchomi aplikację? – joelc

+1

Nie będzie fizycznie, ale uruchomi aplikację na pulpicie/stacji roboczej, którą odsyłasz, jako wskazany przez ciebie użytkownik. Używałem tego specjalnie w naszym scenariuszu, w którym mieliśmy serwery w ponad 200 sklepach, gdzie musimy dystrybuować plik wykonywalny i uruchamiać go jako pewien użytkownik. – Raymund

+0

Dzięki, problem polega na tym, że aplikacja, którą muszę uruchomić w imieniu użytkownika korzysta z usług, które wymagają, aby konto miało dostęp do komputera, więc to nie zadziała. – joelc

0

znalazłem problemu na Elance.com i znalazłem ten link.

Miałem ten sam rodzaj problemu z jednym z moich projektów. To wymagało usługi systemu Windows, aby uruchomić terminal komunikatora terminala POS, który powinien być z interfejsem użytkownika z dostępem administratora. Próbowałem podszywania się pod winlogon.exe, aby uniknąć UAC, ale to nie pomogło.

Dla mojego problemu, który użyłem Zaplanowane zadania i stworzył moje zadanie przy użyciu C#. Możesz znaleźć bardzo dobrą bibliotekę tutaj http://taskscheduler.codeplex.com. Teraz na wymaganym połączeniu można uruchomić zadanie dynamicznie i masz nad nim pełną kontrolę.

Możesz tworzyć własne zadania/edytować/usuwać dynamicznie i uruchamiać aplikacje, unikając UAC.

0

Chcesz utworzyć nową interaktywną sesję. Niestety nie jest to możliwe. O ile rozumiem, chcesz uruchomić proces, a następnie zdalnie sterować maszyną za pomocą VNC. Może potrzebujesz tylko pulpitu zdalnego?

+0

Cześć Codeguard, technicznie możliwe, ponieważ wiele kiosków zbudowało swoich własnych dostawców uwierzytelniania, aby zrobić dokładnie to i zamierzam to zrobić w mojej własnej aplikacji. Z powodów, dla których nie mogę tutaj wejść, musi zostać zrobione programowo, nie pozwalając użytkownikowi na bezpośredni dostęp do ekranu logowania. – joelc