我如何在.Net中操纵令牌特权?

问题描述 投票:6回答:2

我想使用C#确定将哪些特权分配给我的进程/线程令牌,并根据需要进行调整。例如,为了使我的程序重新启动计算机,它必须首先启用SeShutdownPrivilege特权。

如何从托管代码安全地完成此操作?

c# .net token privileges
2个回答
10
投票

这证明是不平凡的,因为没有内置的机制。不仅需要P / Invoke,而且还必须仔细编码,以确保不要通过启用特权然后立即禁用它们来“泄漏”特权(尽管在重新启动计算机时不是问题)。 >

有关描述的完整代码示例,请阅读MSDN杂志2005年3月发表的Mark Novak的文章[Manipulate Privileges in Managed Code Reliably, Securely, and Efficiently”。

这里是P / Invoke声明:

using System;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;

namespace PrivilegeClass
{
    [Flags]
    internal enum TokenAccessLevels 
    {
        AssignPrimary       = 0x00000001,
        Duplicate           = 0x00000002,
        Impersonate         = 0x00000004,
        Query               = 0x00000008,
        QuerySource         = 0x00000010,
        AdjustPrivileges    = 0x00000020,
        AdjustGroups        = 0x00000040,
        AdjustDefault       = 0x00000080,
        AdjustSessionId     = 0x00000100,

        Read                = 0x00020000 | Query,

        Write               = 0x00020000 | AdjustPrivileges | AdjustGroups | AdjustDefault,

        AllAccess           = 0x000F0000       |
            AssignPrimary    |
            Duplicate        |
            Impersonate      |
            Query            |
            QuerySource      |
            AdjustPrivileges |
            AdjustGroups     |
            AdjustDefault    |
            AdjustSessionId,

        MaximumAllowed      = 0x02000000
    }

    internal enum SecurityImpersonationLevel
    {
        Anonymous = 0,
        Identification = 1,
        Impersonation = 2,
        Delegation = 3,
    }

    internal enum TokenType
    {
        Primary = 1,
        Impersonation = 2,
    }

    internal sealed class NativeMethods
    {
        internal const uint SE_PRIVILEGE_DISABLED           = 0x00000000;
        internal const uint SE_PRIVILEGE_ENABLED            = 0x00000002;

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
        internal struct LUID 
        {
            internal uint LowPart;
            internal uint HighPart;
        }

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
        internal struct LUID_AND_ATTRIBUTES 
        {
            internal LUID Luid;
            internal uint Attributes;
        }

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
        internal struct TOKEN_PRIVILEGE 
        {
            internal uint                PrivilegeCount;
            internal LUID_AND_ATTRIBUTES Privilege;
        }

        internal const string ADVAPI32 = "advapi32.dll";
        internal const string KERNEL32 = "kernel32.dll";

        internal const int ERROR_SUCCESS = 0x0;
        internal const int ERROR_ACCESS_DENIED  = 0x5;
        internal const int ERROR_NOT_ENOUGH_MEMORY = 0x8;
        internal const int ERROR_NO_TOKEN = 0x3f0;
        internal const int ERROR_NOT_ALL_ASSIGNED = 0x514;
        internal const int ERROR_NO_SUCH_PRIVILEGE = 0x521;
        internal const int ERROR_CANT_OPEN_ANONYMOUS = 0x543;

        [DllImport(
             KERNEL32,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern bool CloseHandle(IntPtr handle);

        [DllImport(
             ADVAPI32,
             CharSet=CharSet.Unicode,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern bool AdjustTokenPrivileges (
            [In]     SafeTokenHandle       TokenHandle,
            [In]     bool                  DisableAllPrivileges,
            [In]     ref TOKEN_PRIVILEGE   NewState,
            [In]     uint                  BufferLength,
            [In,Out] ref TOKEN_PRIVILEGE   PreviousState,
            [In,Out] ref uint              ReturnLength);

        [DllImport(
             ADVAPI32,
             CharSet=CharSet.Auto,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern
        bool RevertToSelf();

        [DllImport(
             ADVAPI32,
             EntryPoint="LookupPrivilegeValueW",
             CharSet=CharSet.Auto,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern
        bool LookupPrivilegeValue (
            [In]     string             lpSystemName,
            [In]     string             lpName,
            [In,Out] ref LUID           Luid);

        [DllImport(
             KERNEL32,
             CharSet=CharSet.Auto,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern 
        IntPtr GetCurrentProcess();

        [DllImport(
             KERNEL32,
             CharSet=CharSet.Auto,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern 
            IntPtr GetCurrentThread ();

        [DllImport(
             ADVAPI32,
             CharSet=CharSet.Unicode,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern 
        bool OpenProcessToken (
            [In]     IntPtr              ProcessToken,
            [In]     TokenAccessLevels   DesiredAccess,
            [In,Out] ref SafeTokenHandle TokenHandle);

        [DllImport
             (ADVAPI32,
             CharSet=CharSet.Unicode,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern
        bool OpenThreadToken(
            [In]     IntPtr              ThreadToken,
            [In]     TokenAccessLevels   DesiredAccess,
            [In]     bool                OpenAsSelf,
            [In,Out] ref SafeTokenHandle TokenHandle);

        [DllImport
            (ADVAPI32,
             CharSet=CharSet.Unicode,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern
        bool DuplicateTokenEx(
            [In]    SafeTokenHandle     ExistingToken,
            [In]    TokenAccessLevels   DesiredAccess,
            [In]    IntPtr              TokenAttributes,
            [In]    SecurityImpersonationLevel  ImpersonationLevel,
            [In]    TokenType           TokenType,
            [In,Out] ref SafeTokenHandle NewToken);

        [DllImport
             (ADVAPI32,
             CharSet=CharSet.Unicode,
             SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal static extern
        bool SetThreadToken(
            [In]    IntPtr              Thread,
            [In]    SafeTokenHandle     Token);

        static NativeMethods()
        {
        }
    }
}

0
投票

这里是我用的。它基于Mark Novak的文章,但是对于不受信任的堆栈帧,CER或重入具有较少的偏执(因为我假设您不是在编写Internet Explorer或SQL Server加载项)。

© www.soinside.com 2019 - 2024. All rights reserved.