Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# - AdjustTokenPrivileges not working on 32bit

I am trying to obtain a privilege in my .NET 4 C# application. This code works and the privilege is obtained successfully, but only on 64bit systems. When the same code is run on a 32bit system, the code fails at AdjustTokenPrivileges with this exception:

Invalid access to memory location. (Exception from HRESULT: 0x800703E6)

I've tried modifying the code to fix the issue, but nothing has been working and I am pretty stumped.

Any ideas on why this fails on 32bit systems? It fails on both Windows Vista and 7 32bit, so it is a 32bit specific problem.

Updated with correct code in 2022. The below code is now correct and can be used in your application.

The method:

public static void EnableDisablePrivilege(string PrivilegeName, bool EnableDisable)
{
    if (!LookupPrivilegeValue(null, PrivilegeName, out var luid)) throw new Exception($"EnableDisablePrivilege: LookupPrivilegeValue failed: {Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message}");

    if (!OpenProcessToken(Process.GetCurrentProcess().SafeHandle, TokenAccessLevels.AdjustPrivileges, out var tokenHandle)) throw new Exception($"EnableDisablePrivilege: OpenProcessToken failed: {Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message}");

    var tokenPrivileges = new TOKEN_PRIVILEGES { PrivilegeCount = 1, Privileges = new[] { new LUID_AND_ATTRIBUTES { LUID = luid, Attributes = (uint)(EnableDisable ? 2 : 4) } } };
    if (!AdjustTokenPrivileges(tokenHandle, false, ref tokenPrivileges, 0, IntPtr.Zero, out _))
    {
        tokenHandle.Dispose();
        throw new Exception($"EnableDisablePrivilege: AdjustTokenPrivileges failed: {Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message}");
    }
    else tokenHandle.Dispose();
}

Implementation:

EnableDisablePrivilege("SeManageVolumePrivilege", true);

PInvoke declarations:

[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
    private uint lowPart;
    private int highPart;

    public uint LowPart { get => lowPart; set => lowPart = value; }

    public int HighPart { get => highPart; set => highPart = value; }
}

[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES
{
    private LUID luid;
    private uint attributes;

    public LUID LUID { get => luid; set => luid = value; }

    public uint Attributes { get => attributes; set => attributes = value; }
}

[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
    private uint privilegeCount;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
    private LUID_AND_ATTRIBUTES[] privileges;

    public uint PrivilegeCount { get => privilegeCount; set => privilegeCount = value; }

    public LUID_AND_ATTRIBUTES[] Privileges { get => privileges; set => privileges = value; }
}

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool OpenProcessToken(SafeProcessHandle ProcessHandle, TokenAccessLevels DesiredAccess, out SafeAccessTokenHandle TokenHandle);

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool AdjustTokenPrivileges(SafeAccessTokenHandle TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint BufferLength, IntPtr PreviousState, out uint ReturnLength);

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
like image 551
Eaton Avatar asked Nov 28 '12 23:11

Eaton


1 Answers

Fixed, just had to put a ref before NewState:

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint Bufferlength, IntPtr PreviousState, IntPtr ReturnLength);
like image 95
Eaton Avatar answered Oct 16 '22 08:10

Eaton