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

如何读取NT安全描述符?含重复权限识别需求

解析Windows NT安全描述符并识别等效重复项

首先明确:你提到的「NT Security Descriptor」完全是Windows标准的安全描述符格式,这个十六进制字符串是安全描述符的二进制序列化结果,符合Win32 API定义的SECURITY_DESCRIPTOR结构规范。

一、读取并解析安全描述符(提取SID等信息)

你可以通过Windows原生API或.NET/PowerShell工具直接解析这个十六进制字符串,以下是两种实用方法:

1. C#/.NET 代码解析

将十六进制字符串转换为字节数组后,用System.Security.AccessControl.SecurityDescriptor类解析,可直接提取所有者、组、权限项(ACE)及对应SID:

using System;
using System.Security.AccessControl;
using System.Security.Principal;

public static void ParseSecurityDescriptor(string hexStr)
{
    // 去除开头的0x前缀(如果有的话)
    if (hexStr.StartsWith("0x"))
        hexStr = hexStr.Substring(2);
    
    // 十六进制转字节数组
    byte[] sdBytes = Convert.FromHexString(hexStr);
    SecurityDescriptor sd = new SecurityDescriptor(sdBytes, 0);

    // 提取所有者SID
    SecurityIdentifier ownerSid = sd.Owner;
    Console.WriteLine($"所有者SID: {ownerSid.Value}");

    // 提取组SID
    SecurityIdentifier groupSid = sd.Group;
    Console.WriteLine($"组SID: {groupSid.Value}");

    // 解析DACL(自主访问控制列表)中的ACE项
    if (sd.DiscretionaryAcl != null)
    {
        Console.WriteLine("DACL权限项:");
        foreach (GenericAce ace in sd.DiscretionaryAcl)
        {
            if (ace is GenericAccessRule accessRule)
            {
                Console.WriteLine($"- SID: {accessRule.IdentityReference.Value}, 权限掩码: 0x{accessRule.AccessMask:X}, 类型: {accessRule.AccessControlType}");
            }
        }
    }
}

调用时传入你的示例十六进制字符串,就能输出其中的SID、权限掩码等关键信息。

2. PowerShell 快速解析

用PowerShell将十六进制转字节数组后,通过.NET类解析:

$hexStr = "0x04000000001C00000000000000000000000000000000000105000000000005150000006A5B007F2501AD5CA912B91E16E400000100000000001C000000000003310F00010500000000000515000000F4680D03A5124B6B881C6A372E290000"
$hexStr = $hexStr -replace '^0x', ''
$sdBytes = [System.Convert]::FromHexString($hexStr)
$sd = New-Object System.Security.AccessControl.SecurityDescriptor($sdBytes, 0)

# 输出所有者和组SID
Write-Host "所有者SID: $($sd.Owner.Value)"
Write-Host "组SID: $($sd.Group.Value)"

# 输出DACL中的ACE
if ($sd.DiscretionaryAcl) {
    Write-Host "DACL权限项:"
    foreach ($ace in $sd.DiscretionaryAcl) {
        if ($ace -is [System.Security.AccessControl.GenericAccessRule]) {
            Write-Host "- SID: $($ace.IdentityReference.Value), 权限掩码: 0x$($ace.AccessMask.ToString('X')), 类型: $($ace.AccessControlType)"
        }
    }
}

二、识别等效但二进制不同的重复权限项

由于安全描述符的二进制序列化可能存在非语义差异(比如ACE的顺序、冗余填充字节),直接比较二进制字符串会误判,需要基于语义等效来识别重复项,推荐两种方案:

1. 生成标准化语义哈希(适合批量处理)

解析每个安全描述符的核心语义信息,标准化后生成哈希值,哈希相同即为等效项:

  • 提取信息:所有者SID、组SID、DACL中所有ACE的SID、AccessMask、AceType、AceFlags
  • 标准化步骤:将ACE按SID和AccessMask排序(消除顺序差异),把所有信息拼接成字符串或序列化为固定格式的字节数组
  • 计算哈希:用SHA256等哈希算法生成哈希值,相同哈希的安全描述符即为等效重复项

示例C#代码片段(生成标准化哈希):

using System.Security.Cryptography;
using System.Text;
using System.Linq;

public static string GenerateSdSignature(SecurityDescriptor sd)
{
    StringBuilder sb = new StringBuilder();
    // 添加所有者和组SID
    sb.AppendLine(sd.Owner.Value);
    sb.AppendLine(sd.Group.Value);

    // 提取并排序ACE项
    if (sd.DiscretionaryAcl != null)
    {
        var sortedAces = sd.DiscretionaryAcl
            .OfType<GenericAccessRule>()
            .OrderBy(ace => ace.IdentityReference.Value)
            .ThenBy(ace => ace.AccessMask)
            .ThenBy(ace => ace.AccessControlType);
        
        foreach (var ace in sortedAces)
        {
            sb.AppendLine($"{ace.IdentityReference.Value}|{ace.AccessMask}|{ace.AccessControlType}|{ace.AceFlags}");
        }
    }

    // 生成哈希
    using (var sha256 = SHA256.Create())
    {
        byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString()));
        return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
    }
}

对数千条安全描述符批量生成签名后,按签名分组即可找出所有等效重复项。

2. 用Windows API直接比较语义等效

Windows提供EqualSecurityDescriptor API,可直接判断两个安全描述符是否语义等效(忽略二进制序列化的非必要差异)。在C#中可通过P/Invoke调用:

using System.Runtime.InteropServices;

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EqualSecurityDescriptor(
    IntPtr pSecurityDescriptor1,
    IntPtr pSecurityDescriptor2);

// 使用示例:比较两个安全描述符
public static bool AreSdEquivalent(SecurityDescriptor sd1, SecurityDescriptor sd2)
{
    return EqualSecurityDescriptor(sd1.GetSecurityDescriptorBinaryForm(), sd2.GetSecurityDescriptorBinaryForm());
}

这种方法最准确,但两两比较数千条数据效率较低,适合小批量验证,或结合哈希分组后再做精确验证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 00:57:17