/// <summary> /// Get the information for all privileges on the process token /// specified. /// </summary> /// <param name="token">The user token to get the privilege information</param> /// <returns>Dictionary<String, PrivilegeAttributes> the info on all the privileges on the process token</String></returns> public static Dictionary <String, PrivilegeAttributes> GetAllPrivilegeInfo(SafeHandle token) { Dictionary <String, PrivilegeAttributes> info = new Dictionary <String, PrivilegeAttributes>(); IntPtr hToken = IntPtr.Zero; if (!Advapi32.OpenProcessToken(token, TokenAccessLevels.Query, out hToken)) { throw new Win32Exception("OpenProcessToken() failed"); } try { Advapi32.GetTokenInformation(hToken, TOKEN_PRIVILEGES, IntPtr.Zero, 0, out var tokenLength); Helpers.LUID_AND_ATTRIBUTES[] privileges; IntPtr privilegesPtr = Marshal.AllocHGlobal((int)tokenLength); try { if (!Advapi32.GetTokenInformation(hToken, TOKEN_PRIVILEGES, privilegesPtr, tokenLength, out tokenLength)) { throw new Win32Exception("GetTokenInformation() for TOKEN_PRIVILEGES failed"); } Helpers.TOKEN_PRIVILEGES privilegeInfo = Marshal.PtrToStructure <Helpers.TOKEN_PRIVILEGES>(privilegesPtr); privileges = new Helpers.LUID_AND_ATTRIBUTES[privilegeInfo.PrivilegeCount]; PtrToStructureArray(privileges, IntPtr.Add(privilegesPtr, Marshal.SizeOf(privilegeInfo.PrivilegeCount))); } finally { Marshal.FreeHGlobal(privilegesPtr); } info = privileges.ToDictionary(p => GetPrivilegeName(p.Luid), p => p.Attributes); } finally { Kernel32.CloseHandle(hToken); } return(info); }
private static Dictionary <string, bool?> AdjustTokenPrivileges(SafeHandle token, Helpers.LUID_AND_ATTRIBUTES[]?newState) { bool disableAllPrivileges = true; IntPtr newStatePtr = IntPtr.Zero; Helpers.LUID_AND_ATTRIBUTES[] oldStatePrivileges; if (newState != null) { 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(Helpers.TOKEN_PRIVILEGES)); int luidAttrSize = 0; if (newState.Length > 1) { luidAttrSize = Marshal.SizeOf(typeof(Helpers.LUID_AND_ATTRIBUTES)) * (newState.Length - 1); } int totalSize = tokenPrivilegesSize + luidAttrSize; byte[] newStateBytes = new byte[totalSize]; // get the first entry that includes the struct details Helpers.TOKEN_PRIVILEGES tokenPrivileges = new Helpers.TOKEN_PRIVILEGES() { PrivilegeCount = (UInt32)newState.Length, Privileges = new Helpers.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 = Marshal.AllocHGlobal(newStateBytes.Length); Marshal.Copy(newStateBytes, 0, newStatePtr, newStateBytes.Length); } try { IntPtr hToken = IntPtr.Zero; if (!Advapi32.OpenProcessToken(token, TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges, out hToken)) { throw new Win32Exception("OpenProcessToken() failed with Query and AdjustPrivileges"); } try { IntPtr oldStatePtr = Marshal.AllocHGlobal(0); if (!Advapi32.AdjustTokenPrivileges(hToken, disableAllPrivileges, newStatePtr, 0, oldStatePtr, out var returnLength)) { int errCode = Marshal.GetLastWin32Error(); if (errCode != (int)Win32ErrorCodes.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(errCode, "AdjustTokenPrivileges() failed to get old state size"); } } // resize the oldStatePtr based on the length returned from Windows Marshal.FreeHGlobal(oldStatePtr); oldStatePtr = Marshal.AllocHGlobal((int)returnLength); try { bool res = Advapi32.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 if (!res || errCode != (int)Win32ErrorCodes.ERROR_SUCCESS) { throw new Win32Exception(errCode, "AdjustTokenPrivileges() failed"); } // Marshal the oldStatePtr to the struct Helpers.TOKEN_PRIVILEGES oldState = Marshal.PtrToStructure <Helpers.TOKEN_PRIVILEGES>(oldStatePtr); oldStatePrivileges = new Helpers.LUID_AND_ATTRIBUTES[oldState.PrivilegeCount]; PtrToStructureArray(oldStatePrivileges, IntPtr.Add(oldStatePtr, Marshal.SizeOf(oldState.PrivilegeCount))); } finally { Marshal.FreeHGlobal(oldStatePtr); } } finally { Kernel32.CloseHandle(hToken); } } finally { if (newStatePtr != IntPtr.Zero) { Marshal.FreeHGlobal(newStatePtr); } } return(oldStatePrivileges.ToDictionary(p => GetPrivilegeName(p.Luid), p => (bool?)p.Attributes.HasFlag(PrivilegeAttributes.Enabled))); }