public static void AdjustToken() { const uint TOKEN_ADJUST_PRIVILEGES = 0x20; const uint TOKEN_QUERY = 0x8; const int SE_PRIVILEGE_ENABLED = 0x2; const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege"; if (Environment.OSVersion.Platform != PlatformID.Win32NT) { return; } IntPtr procHandle = NativeMethod.GetCurrentProcess(); //トークンを取得する IntPtr tokenHandle; NativeMethod.OpenProcessToken(procHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out tokenHandle); //LUIDを取得する TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES(); tp.Attributes = SE_PRIVILEGE_ENABLED; tp.PrivilegeCount = 1; NativeMethod.LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, out tp.Luid); //特権を有効にする NativeMethod.AdjustTokenPrivileges( tokenHandle, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); //閉じる NativeMethod.CloseHandle(tokenHandle); }
private Impersonation(string username, string domain, string password, LogonType logonType, BuiltinUser builtinUser) { switch (builtinUser) { case BuiltinUser.None: if (string.IsNullOrEmpty(username)) { return; } break; case BuiltinUser.LocalService: username = "******"; break; case BuiltinUser.NetworkService: username = "******"; break; } IntPtr userToken = IntPtr.Zero; IntPtr userTokenDuplication = IntPtr.Zero; // Logon with user and get token. bool loggedOn = NativeMethod.LogonUser(username, domain, password, logonType, LogonProvider.Default, out userToken); if (loggedOn) { try { // Create a duplication of the usertoken, this is a solution // for the known bug that is published under KB article Q319615. if (NativeMethod.DuplicateToken(userToken, 2, ref userTokenDuplication)) { // Create windows identity from the token and impersonate the user. WindowsIdentity identity = new WindowsIdentity(userTokenDuplication); _impersonationContext = identity.Impersonate(); } //else //{ // // Token duplication failed! // // Use the default ctor overload // // that will use Mashal.GetLastWin32Error(); // // to create the exceptions details. // throw new Win32Exception(); //} } finally { // Close usertoken handle duplication when created. if (!userTokenDuplication.Equals(IntPtr.Zero)) { // Closes the handle of the user. NativeMethod.CloseHandle(userTokenDuplication); userTokenDuplication = IntPtr.Zero; } // Close usertoken handle when created. if (!userToken.Equals(IntPtr.Zero)) { // Closes the handle of the user. NativeMethod.CloseHandle(userToken); userToken = IntPtr.Zero; } } } //else //{ // // Logon failed! // // Use the default ctor overload that // // will use Mashal.GetLastWin32Error(); // // to create the exceptions details. // throw new Win32Exception(); //} }
/// <summary> /// The function launches an application at low integrity level. /// </summary> /// <param name="commandLine"> /// The command line to be executed. The maximum length of this string is 32K /// characters. /// </param> /// <param name="selectedIntegrityLevel"> /// Numeric representation of integrity level with which process has to be started /// </param> /// <remarks> /// To start a low-integrity process, /// 1) Duplicate the handle of the current process, which is at medium /// integrity level. /// 2) Use SetTokenInformation to set the integrity level in the access token /// to Low. /// 3) Use CreateProcessAsUser to create a new process using the handle to /// the low integrity access token. /// </remarks> public static void CreateSpecificIntegrityProcess(string commandLine, int selectedIntegrityLevel) { SafeTokenHandle hToken = null; SafeTokenHandle hNewToken = null; IntPtr pIntegritySid = IntPtr.Zero; int cbTokenInfo = 0; IntPtr pTokenInfo = IntPtr.Zero; STARTUPINFO si = new STARTUPINFO(); PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); try { // Open the primary access token of the process. if (!NativeMethod.OpenProcessToken(Process.GetCurrentProcess().Handle, NativeMethod.TOKEN_DUPLICATE | NativeMethod.TOKEN_ADJUST_DEFAULT | NativeMethod.TOKEN_QUERY | NativeMethod.TOKEN_ASSIGN_PRIMARY, out hToken)) { throw new Win32Exception(); } // Duplicate the primary token of the current process. if (!NativeMethod.DuplicateTokenEx(hToken, 0, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenPrimary, out hNewToken)) { throw new Win32Exception(); } // Create the low integrity SID. if (!NativeMethod.AllocateAndInitializeSid( ref NativeMethod.SECURITY_MANDATORY_LABEL_AUTHORITY, 1, selectedIntegrityLevel, 0, 0, 0, 0, 0, 0, 0, out pIntegritySid)) { throw new Win32Exception(); } TOKEN_MANDATORY_LABEL tml; tml.Label.Attributes = NativeMethod.SE_GROUP_INTEGRITY; tml.Label.Sid = pIntegritySid; // Marshal the TOKEN_MANDATORY_LABEL struct to the native memory. cbTokenInfo = Marshal.SizeOf(tml); pTokenInfo = Marshal.AllocHGlobal(cbTokenInfo); Marshal.StructureToPtr(tml, pTokenInfo, false); // Set the integrity level in the access token to low. if (!NativeMethod.SetTokenInformation(hNewToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenInfo, cbTokenInfo + NativeMethod.GetLengthSid(pIntegritySid))) { throw new Win32Exception(); } // Create the new process at the Low integrity level. si.cb = Marshal.SizeOf(si); if (!NativeMethod.CreateProcessAsUser(hNewToken, null, commandLine, IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref si, out pi)) { throw new Win32Exception(); } } finally { // Centralized cleanup for all allocated resources. if (hToken != null) { hToken.Close(); hToken = null; } if (hNewToken != null) { hNewToken.Close(); hNewToken = null; } if (pIntegritySid != IntPtr.Zero) { NativeMethod.FreeSid(pIntegritySid); pIntegritySid = IntPtr.Zero; } if (pTokenInfo != IntPtr.Zero) { Marshal.FreeHGlobal(pTokenInfo); pTokenInfo = IntPtr.Zero; cbTokenInfo = 0; } if (pi.hProcess != IntPtr.Zero) { NativeMethod.CloseHandle(pi.hProcess); pi.hProcess = IntPtr.Zero; } if (pi.hThread != IntPtr.Zero) { NativeMethod.CloseHandle(pi.hThread); pi.hThread = IntPtr.Zero; } } }