/// <summary> /// Get's the status of all the privileges on the token specified /// </summary> /// <param name="token">The process token to get the privilege status on</param> /// <returns>Dictionary where the key is the privilege constant and the value is the PrivilegeAttributes flags</returns> public static Dictionary <String, PrivilegeAttributes> GetAllPrivilegeInfo(SafeHandle token) { SafeNativeHandle hToken = null; if (!NativeMethods.OpenProcessToken(token, TokenAccessLevels.Query, out hToken)) { throw new Win32Exception("OpenProcessToken() failed"); } using (hToken) { UInt32 tokenLength = 0; NativeMethods.GetTokenInformation(hToken, TOKEN_PRIVILEGES, new SafeMemoryBuffer(0), 0, out tokenLength); NativeHelpers.LUID_AND_ATTRIBUTES[] privileges; using (SafeMemoryBuffer privilegesPtr = new SafeMemoryBuffer((int)tokenLength)) { if (!NativeMethods.GetTokenInformation(hToken, TOKEN_PRIVILEGES, privilegesPtr, tokenLength, out tokenLength)) { throw new Win32Exception("GetTokenInformation() for TOKEN_PRIVILEGES failed"); } NativeHelpers.TOKEN_PRIVILEGES privilegeInfo = (NativeHelpers.TOKEN_PRIVILEGES)Marshal.PtrToStructure( privilegesPtr.DangerousGetHandle(), typeof(NativeHelpers.TOKEN_PRIVILEGES)); privileges = new NativeHelpers.LUID_AND_ATTRIBUTES[privilegeInfo.PrivilegeCount]; PtrToStructureArray(privileges, IntPtr.Add(privilegesPtr.DangerousGetHandle(), Marshal.SizeOf(privilegeInfo.PrivilegeCount))); } return(privileges.ToDictionary(p => GetPrivilegeName(p.Luid), p => p.Attributes)); } }
/// <summary> /// Do a bulk set of multiple privileges /// </summary> /// <param name="token">The process token to use when setting the privilege state</param> /// <param name="state">A dictionary that contains the privileges to set, the key is the constant name and the value can be; /// true - enable the privilege /// false - disable the privilege /// null - remove the privilege (this cannot be reversed) /// </param> /// <param name="strict">When true, will fail if one privilege failed to be set, otherwise it will silently continue</param> /// <returns>The previous state that can be passed to SetTokenPrivileges to revert the action</returns> public static Dictionary <string, bool?> SetTokenPrivileges(SafeHandle token, IDictionary state, bool strict = true) { NativeHelpers.LUID_AND_ATTRIBUTES[] privilegeAttr = new NativeHelpers.LUID_AND_ATTRIBUTES[state.Count]; int i = 0; foreach (DictionaryEntry entry in state) { string key = (string)entry.Key; NativeHelpers.LUID luid; if (!NativeMethods.LookupPrivilegeValue(null, key, out luid)) { throw new Win32Exception(String.Format("LookupPrivilegeValue({0}) failed", key)); } PrivilegeAttributes attributes; switch ((bool?)entry.Value) { case true: attributes = PrivilegeAttributes.Enabled; break; case false: attributes = PrivilegeAttributes.Disabled; break; default: attributes = PrivilegeAttributes.Removed; break; } privilegeAttr[i].Luid = luid; privilegeAttr[i].Attributes = attributes; i++; } return(AdjustTokenPrivileges(token, privilegeAttr, strict)); }
private static Dictionary <string, bool?> AdjustTokenPrivileges(SafeHandle token, NativeHelpers.LUID_AND_ATTRIBUTES[] newState, bool strict) { bool disableAllPrivileges; SafeMemoryBuffer newStatePtr; NativeHelpers.LUID_AND_ATTRIBUTES[] oldStatePrivileges; UInt32 returnLength; if (newState == null) { disableAllPrivileges = true; newStatePtr = new SafeMemoryBuffer(0); } else { disableAllPrivileges = false; // Need to manually marshal the bytes requires for newState as the constant size // of LUID_AND_ATTRIBUTES is set to 1 and can't be overridden at runtime, TOKEN_PRIVILEGES // always contains at least 1 entry so we need to calculate the extra size if there are // nore than 1 LUID_AND_ATTRIBUTES entry int tokenPrivilegesSize = Marshal.SizeOf(typeof(NativeHelpers.TOKEN_PRIVILEGES)); int luidAttrSize = 0; if (newState.Length > 1) { luidAttrSize = Marshal.SizeOf(typeof(NativeHelpers.LUID_AND_ATTRIBUTES)) * (newState.Length - 1); } int totalSize = tokenPrivilegesSize + luidAttrSize; byte[] newStateBytes = new byte[totalSize]; // get the first entry that includes the struct details NativeHelpers.TOKEN_PRIVILEGES tokenPrivileges = new NativeHelpers.TOKEN_PRIVILEGES() { PrivilegeCount = (UInt32)newState.Length, Privileges = new NativeHelpers.LUID_AND_ATTRIBUTES[1], }; if (newState.Length > 0) { tokenPrivileges.Privileges[0] = newState[0]; } int offset = StructureToBytes(tokenPrivileges, newStateBytes, 0); // copy the remaining LUID_AND_ATTRIBUTES (if any) for (int i = 1; i < newState.Length; i++) { offset += StructureToBytes(newState[i], newStateBytes, offset); } // finally create the pointer to the byte array we just created newStatePtr = new SafeMemoryBuffer(newStateBytes.Length); Marshal.Copy(newStateBytes, 0, newStatePtr.DangerousGetHandle(), newStateBytes.Length); } using (newStatePtr) { SafeNativeHandle hToken; if (!NativeMethods.OpenProcessToken(token, TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges, out hToken)) { throw new Win32Exception("OpenProcessToken() failed with Query and AdjustPrivileges"); } using (hToken) { if (!NativeMethods.AdjustTokenPrivileges(hToken, disableAllPrivileges, newStatePtr, 0, new SafeMemoryBuffer(0), out returnLength)) { int errCode = Marshal.GetLastWin32Error(); if (errCode != 122) // ERROR_INSUFFICIENT_BUFFER { throw new Win32Exception(errCode, "AdjustTokenPrivileges() failed to get old state size"); } } using (SafeMemoryBuffer oldStatePtr = new SafeMemoryBuffer((int)returnLength)) { bool res = NativeMethods.AdjustTokenPrivileges(hToken, disableAllPrivileges, newStatePtr, returnLength, oldStatePtr, out returnLength); int errCode = Marshal.GetLastWin32Error(); // even when res == true, ERROR_NOT_ALL_ASSIGNED may be set as the last error code // fail if we are running with strict, otherwise ignore those privileges if (!res || ((strict && errCode != 0) || (!strict && !(errCode == 0 || errCode == 0x00000514)))) { throw new Win32Exception(errCode, "AdjustTokenPrivileges() failed"); } // Marshal the oldStatePtr to the struct NativeHelpers.TOKEN_PRIVILEGES oldState = (NativeHelpers.TOKEN_PRIVILEGES)Marshal.PtrToStructure( oldStatePtr.DangerousGetHandle(), typeof(NativeHelpers.TOKEN_PRIVILEGES)); oldStatePrivileges = new NativeHelpers.LUID_AND_ATTRIBUTES[oldState.PrivilegeCount]; PtrToStructureArray(oldStatePrivileges, IntPtr.Add(oldStatePtr.DangerousGetHandle(), Marshal.SizeOf(oldState.PrivilegeCount))); } } } return(oldStatePrivileges.ToDictionary(p => GetPrivilegeName(p.Luid), p => (bool?)p.Attributes.HasFlag(PrivilegeAttributes.Enabled))); }