You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否提取Carbon模块中Get-CPrivileges相关代码到自定义PowerShell脚本?

提取Carbon Get-CPrivileges核心实现(无需完整模块)

以下是从Carbon模块中剥离的独立实现,直接调用Windows原生advapi32.dll的LSA(本地安全授权)API读取权限,完全避免使用SecEdit和临时文件,也不需要依赖Carbon的冗余模块:

完整可运行代码

Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;

public static class LsaPrivilegeHelper
{
    private const uint STATUS_SUCCESS = 0;
    private const uint STATUS_NO_MORE_ENTRIES = 0x8000001A;
    private const int POLICY_VIEW_LOCAL_INFORMATION = 0x00000001;

    [StructLayout(LayoutKind.Sequential)]
    private struct LSA_UNICODE_STRING
    {
        public ushort Length;
        public ushort MaximumLength;
        public IntPtr Buffer;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct LSA_OBJECT_ATTRIBUTES
    {
        public int Length;
        public IntPtr RootDirectory;
        public IntPtr ObjectName;
        public uint Attributes;
        public IntPtr SecurityDescriptor;
        public IntPtr SecurityQualityOfService;
    }

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern uint LsaOpenPolicy(
        ref LSA_UNICODE_STRING SystemName,
        ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
        int DesiredAccess,
        out IntPtr PolicyHandle);

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern uint LsaLookupNames2(
        IntPtr PolicyHandle,
        uint Flags,
        uint Count,
        ref LSA_UNICODE_STRING Names,
        out IntPtr ReferencedDomains,
        out IntPtr Sids);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern uint LsaEnumerateAccountRights(
        IntPtr PolicyHandle,
        IntPtr Sid,
        out IntPtr UserRights,
        out uint Count);

    [DllImport("advapi32.dll")]
    private static extern uint LsaNtStatusToWinError(uint Status);

    [DllImport("advapi32.dll")]
    private static extern uint LsaClose(IntPtr Handle);

    [DllImport("kernel32.dll")]
    private static extern void LocalFree(IntPtr Mem);

    private static LSA_UNICODE_STRING CreateUnicodeString(string value)
    {
        LSA_UNICODE_STRING str = new LSA_UNICODE_STRING();
        if (value != null)
        {
            str.Buffer = Marshal.StringToHGlobalUni(value);
            str.Length = (ushort)(value.Length * 2);
            str.MaximumLength = (ushort)(str.Length + 2);
        }
        return str;
    }

    private static void FreeUnicodeString(ref LSA_UNICODE_STRING str)
    {
        if (str.Buffer != IntPtr.Zero)
        {
            LocalFree(str.Buffer);
            str.Buffer = IntPtr.Zero;
        }
    }

    public static string[] GetUserPrivileges(string username)
    {
        IntPtr policyHandle = IntPtr.Zero;
        IntPtr sidPtr = IntPtr.Zero;
        IntPtr userRightsPtr = IntPtr.Zero;
        IntPtr referencedDomainsPtr = IntPtr.Zero;
        try
        {
            LSA_UNICODE_STRING systemName = new LSA_UNICODE_STRING();
            LSA_OBJECT_ATTRIBUTES objectAttributes = new LSA_OBJECT_ATTRIBUTES();
            objectAttributes.Length = Marshal.SizeOf(objectAttributes);

            uint status = LsaOpenPolicy(ref systemName, ref objectAttributes, POLICY_VIEW_LOCAL_INFORMATION, out policyHandle);
            if (status != STATUS_SUCCESS)
                throw new System.ComponentModel.Win32Exception((int)LsaNtStatusToWinError(status));

            LSA_UNICODE_STRING userName = CreateUnicodeString(username);
            try
            {
                status = LsaLookupNames2(policyHandle, 0, 1, ref userName, out referencedDomainsPtr, out sidPtr);
                if (status != STATUS_SUCCESS)
                    throw new System.ComponentModel.Win32Exception((int)LsaNtStatusToWinError(status));
            }
            finally
            {
                FreeUnicodeString(ref userName);
            }

            uint rightsCount;
            status = LsaEnumerateAccountRights(policyHandle, sidPtr, out userRightsPtr, out rightsCount);
            if (status != STATUS_SUCCESS && status != STATUS_NO_MORE_ENTRIES)
                throw new System.ComponentModel.Win32Exception((int)LsaNtStatusToWinError(status));

            string[] privileges = new string[rightsCount];
            for (uint i = 0; i < rightsCount; i++)
            {
                IntPtr rightPtr = Marshal.ReadIntPtr(userRightsPtr, (int)i * IntPtr.Size);
                LSA_UNICODE_STRING rightStr = Marshal.PtrToStructure<LSA_UNICODE_STRING>(rightPtr);
                privileges[i] = Marshal.PtrToStringUni(rightStr.Buffer);
            }

            return privileges;
        }
        finally
        {
            if (policyHandle != IntPtr.Zero)
                LsaClose(policyHandle);
            if (userRightsPtr != IntPtr.Zero)
                LocalFree(userRightsPtr);
            if (sidPtr != IntPtr.Zero)
                LocalFree(sidPtr);
            if (referencedDomainsPtr != IntPtr.Zero)
                LocalFree(referencedDomainsPtr);
        }
    }
}
"@

function Get-CPrivileges {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Username
    )

    try {
        $privileges = [LsaPrivilegeHelper]::GetUserPrivileges($Username)
        [PSCustomObject]@{
            Username  = $Username
            Privileges = $privileges
        }
    }
    catch {
        Write-Error "Failed to retrieve privileges for $Username : $_"
    }
}

使用说明

  1. 直接在PowerShell中运行上述代码,定义辅助类和函数
  2. 调用函数获取指定用户的权限,包括SeBatchLogonRight:
    # 获取本地账户权限
    Get-CPrivileges -Username "LocalAdmin"
    
    # 获取域账户权限
    Get-CPrivileges -Username "CORP\DomainUser"
    

关键说明

  • 完全依赖Windows原生advapi32.dll,无需额外DLL或第三方模块
  • 直接通过LSA API读取权限,不会生成任何临时文件,避免SecEdit的安全风险
  • 支持本地账户和域账户,返回所有已分配的权限名称(包括登录权限、特权等)

内容的提问来源于stack exchange,提问作者Dennis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 14:20:14