Windows安全描述符SECURITY_DESCRIPTOR阅读注释

安全对象Securable Object是拥有SD的Windows的对象。注:sd就是安全描述符 访问内核对象的时候 内核要先访问安全描述符 看是否准许访问 拥有安全描述符的内核对象就是安全对象
所有的被命名的Windows的对象都是安全对象。一些没有命名的对象是安全对象,如:进程和线程,也有安全描述符SD。安全对象Securable Object是拥有SD的Windows的对象。
在 Windows系统中,其是用一个安全描述符(Security Descriptors)的结构来保存其权限的设置信息,简称为SD,其在Windows SDK中的结构名是“SECURITY_DESCRIPTOR”,这是包括了安全设置信息的结构体。一个安全描述符包含以下信息
? 一个安全标识符(Security>访问控制链表(ACL)
一个
  ACL   是一个   ACE   链表。每个   ACL   中的   ACE   标示一个托管(注:就是用户,系统用户还是用户组还是别的用户)以及指定允许的访问权限、掩码或者其他功能标志位(注:掩码就是32位的2进制 通过它和存有访问权限的32位按位与运算才能得到自己的访问权限)。一个对象的安全描述符号包含两种类型的 ACL   ,一个是   DACL   ,一个是   SACL  

一个目录访问控制链表( DACL )标示允许或拒绝访问一个安全对象的托管。当一个进程尝试访问一个安全对象的时候,系统检查对象的 DACL 中的ACE(注:DACL就是ACE链表,一种数据结构,没一个节点存放着访问权限等信息,这种链表查找起来比数组快) 来决定是否赋予访问权限。如果对象没有 DACL ,系统赋予完全的访问权限,如果对象的 DACL 没有 ACE(注:此处的区别前面是没有DACL 这里是有DACL但是没有要访问的进程的ace,我是这么认为的 ),那么系统拒绝所有访问对象的尝试,因为 DACL 不允许任何访问权限。系统检查 ACE 序列直到找到一到多个 ACE ,或者直到任何请求的访问权限被否定。更多的信息参见: DACL 怎么样控制一个对象的。对于创建 DACL 的信息,见创建一个 DACL 。

一个系统访问控制链表( SACL )是管理员登录尝试访问一个安全对象(注:和DACL区别是前者是进程等的访问此处是网络中的用户发起对存放各种内核对象的Active Directory的访问,这个Active Directory类似于windows server 2003,一种域控制器,

目前办公网络有工作组模式和域模式  Active Directory 就是活动目录,在域中真正干活的就是这个,他把所有加入域的计算机的所有资源集合起来,并且在用户认证方面也集中管理,并且可以做到在同一个局域网内任何一个台计算机都可以使用你的账号登陆,并且登陆后都是相同的桌面。
)。每个 ACE 指定一个指定的托管尝试的访问类型,这个访问会导致系统产生一个安全事件日志( 注:Active Directory,的ace链表规定了哪些用户可以访问的权限,当访问失败或者成功Active Directory都可以产生一些日志记录这些成功失败的信息 )。一个 SACL 中的 ACE 能够产生访问尝试失败或成功的时候产生评估记录,在将来的 release 中( 注:类似于进程销毁后 访问内核对象计数器减一 ),一个 SACL 在一个未授权用户尝试访问一个对象的时候发出一个警告。更多 SACL 的信息参见 Audit Generation 和 SACL 访问权限。

不要尝试直接使用一个 ACL 来工作。为了确保 ACL 能够语义正确的,使用适当的函数来创建和操纵 ACL 。更多的信息参见:从 ACL 中取得信息和创建或修改一个 ACL 。

ACL   也提供访问控制微软的   Active Directory   目录服务对象。活动目录服务接口(   ADSI   )包括创建和修改   ACL(注:Active Directory可以设置和修改SACL中的ace链表)   内容的程序。更多信息参见:控制访问活动目录对象

访问控制实体(ACE
一个访问控制实体(
ACE )是 ACL 中的一个元素。一个 ACL 可能包含 0 到多个 ACE 。每个 ACE 通过一个指定的托管来控制或监视一个对象。更多关于添加、删除、改变 ACE ,见修改 ACL 对象。

Window Me/98/95:不支持访问控制

有6种类型的ACE,三种被所有的安全对象支持,其他类型是对象特定的ACE,由目录服务对象(注意:就是上文提到的Active Directory)支持。

所有ACE类型都包含下面访问控制信息:

1.  一个安全标示符号(SID)来标示ACE应用的托管

2.  一个访问掩码指定ACE控制的访问权限

3.  一个指示ACE类型的标志位(注意:就是上面提到的六种类型)

4.  一系列位标志决定是否子容器或对象可以继承ACE从基本对象到ACL附着的对象。(注意:Active Directory里可以设置子容器 子容器里可以创建很多网络连接的客户端的需要的或者相关的内核对象 这个子容器可能继承父容器Active Directory的ace属性)

下表列出了三个所有安全对象支持的ACE类型:

Type

Description

访问拒绝ACE

用在一个DACL中拒绝到一个托管的访问权限

访问允许ACE

用在一个DACL中允许到托管的访问权限

系统评估ACE

用在SACL中,当托管尝试检查指定访问权限时产生一个评估记录

对于对象指定的ACE,参见对象指定ACE。(注意:第三种是SACL 访问Active Directory的那个 会产生记录 上文说过的)

注意,系统警告ACE对象现在不支持。


托管

一个托管是一个用户帐户、组帐户或登录会话到一个ACE应用。每个ACL中的ACE都有一个SID来标示托管。用户帐户包含人使用的帐户或程序帐户(例如,Window服务用来登录到本地计算机的)。组帐户不能用来登录到计算机,但在ACE中非常有用,用来拒绝或允许一到多个用户帐户的访问权限。一个登录SID(注意:是登陆sid不是sid)表示当前的登录会话用来允许和拒绝访问权限,直到用户登出。

NT4.0和后来版本中访问控制函数使用TRUSTEE结构体来表示一个托管这个结构体能使你用一个字符串或一个SID来表示一个托管。如果你使用一个名字,从TRUSTEE结构创建ACE的函数执行SID缓冲区分配工作并且查询SID对应的帐户名称。有两个助手函数,BuildTrusteeWithSid和BuildTrusteeWithName,可以用SID或名字来初始化一个TRUSTEE结构。BuildTrusteeWithObjectsAndSid和BuildTrusteeWithObjectsAndName允许你使用一个对象指定的ACE信息来初始化一个TRUSTEE结构体。其他3个助手函数,GetTrusteeFrorm、GetTrusteeName和GetTrusteeType,返回TRUSTEE结构各成员的值。
Window XP/2000:TRUSTEE的ptstrName成员可以是一个指向OBJECTS_AND_NAME或OBJECTS_AND_SID结构体的指针。这些结构体说明对象指定ACE的信息,除了托管的名字和SID之外。这可以象SetEntriesInAcl和GetExplicitEntriesFromAcl这样的函数存储对象指定ACE的信息到EXPLICIT_ACCESS结构体的Trustee成员中。(注意:这几个函数就是修改或者添加已经存在的acl中的访问控制信息)

TRUSTEE结构体:
typedef struct _TRUSTEE {
  PTRUSTEE pMultipleTrustee;
  MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
  TRUSTEE_FORM TrusteeForm;
  TRUSTEE_TYPE TrusteeType;
  LPTSTR ptstrName;
} TRUSTEE, *PTRUSTEE;


访问权限和访问掩码

一个访问权限是一个标志位对应到一个特殊操作集合,这个集合表示线程可以在安全对象上执行的操作。例如:注册表键KEY_SET_VALUE访问权限,对应到线程在这个键下设置的值的能力。如果线程想在一个对象执行一个操作,但没有必要的访问权限,系统不执行操作。

一个访问掩码是一个32位的值,它对应到对象支持的访问权限。所有的Windows NT/2000/XP 安全对象使用一个Windows访问掩码格式,这个格式包含下面的访问权限位:

1.  通用访问权限

2.  标准访问权限

3.  SACL访问权限

4.  目录服务访问权限

当一个线程想打开一个对象的句柄,线程通常指定一个访问掩码来请求一系列的访问权限。例如,需要设置和查询注册表键的程序可以使用一个访问掩码来请求KEY_SET_VALUE和KEY_QUERY_VALUE访问权限来打开该键。

下面表显示了操作每种类型安全对象的信息:

对象类型

安全描述符号函数

NTFS上的文件或目录系统

GetNamedSecurityInfoSetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

命名管道和匿名管道

GetSecurityInfoSetSecurityInfo

控制台屏幕缓冲区

Not supported.

进程和线程

GetSecurityInfoSetSecurityInfo

文件映射对象

GetNamedSecurityInfoSetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Access tokens

SetKernelObjectSecurityGetKernelObjectSecurity

Windows管理对象 (windows工作站和桌面)

GetSecurityInfoSetSecurityInfo

注册表键

GetNamedSecurityInfoSetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Windows服务

GetNamedSecurityInfoSetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

本地和远程打印机

GetNamedSecurityInfoSetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

网络共享

GetNamedSecurityInfoSetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

进程间同步对象 (事件, mutexes, semaphores, and waitable timers)

GetNamedSecurityInfoSetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

作业对象

GetNamedSecurityInfoSetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo


通用访问权限

安全对象使用Windows 访问掩码格式,四个高位说明通用访问权限。每个安全对象类型映射到这些位到一系列标准和对象特殊访问权限。例如:一个Window文件对象映射GENERIC_READ位到READ_CONTROL和SYNCHRONIZE 标准访问权限和FILE_READ_DATA、FILE_READ_EA和FILE_READ_ATTRIBUTES对象指定访问权限。其他类型对象映射GENERIC_READ位到与类型对象适应的一些访问权限。

你可以在你打开一个对象句柄的时候使用通用访问权限来指定需要的访问类型;这通常比指定所有对应标准和特指权限要简单。

下表显示了通用访问权限定义的常量。

常量

解释

GENERIC_ALL

读、写和执行访问

GENERIC_EXECUTE

执行

GENERIC_READ

GENERIC_WRITE

应用程序定义的私有安全访问对象能使用通用访问权限。

安全描述符 (SD)

安全描述符包含了安全对象相关的安全信息。安全描述父由一个SECURITY_DESCRIPTOR结构体组成,它关联到一个安全对象。一个安全描述符包含下面的安全信息:

1.  拥有者或基本组对象的安全ID(SIDs)(注意:通过sid这个键值就可以找到acl)

2.  DACL指定特殊用户或组的允许或拒绝的访问权限

3.  SACL指定对象通用评估记录尝试的访问类型

4.  一个控制位集合,说明安全描述符的含义或它每个成员(注意:就是掩码)

程序不需要直接操作安全描述符的内容。Windows API提供设置和返回安全描述符号的函数。另外,有用来创建和初始化一个新对象安全描述符号的函数。

Windows NT 3.51和更早的版本,Windows ME/98/95:参见:低级访问控制。

工作在活动目录对象上安全描述符程序能使用Windows的安全函数或ADSI(活动目录服务接口)提供的安全接口。更多ADSI的信息参见:访问控制如何在活动目录中工作?


DACL是怎么控制访问对象的?

当一个线程想访问一个安全对象时候,系统要么允许访问,要拒绝访问。如果对象没有DACL,系统赋予访问权限,否则系统查找DACL中的该线程的ACE。每个对象DACL中的ACE指定托管的访问允许或拒绝的访问权限,它可以是一个用户帐户、组帐户或登录会话。

系统比较ACE中的托管和线程访问标记的托管标示。一个访问标记包含SID来说明用户和用户输入的组帐户。一个标记也包含一个登录SID,来表示当前的登录会话。在访问检查期间,系统忽略不可用的组SID。更多可用不可用信息以及拒绝SID,见访问标记中的SID属性。

通常,系统使用现成饿基本访问标记来请求访问。然而,如果现成正在扮演其他用户,系统使用现成的扮演标记。

系统家产序列中的每个ACE,直到下面的情况发生:

1.  一个显式拒绝任何与线程访问标记中列出托管不同的访问ACE出现

2.  线程访问标记中列出的一个或多个允许访问的ACE出现,这个标记显式赋予所有权限。

3.  所有的ACE都检查过,并且至少一个访问权限没有显式的允许,这种情况下暗示拒绝。

下图描述一个DACL对象允许访问一个线程而拒绝访问另一个线程。


对于线程A,系统读ACE1并且立即拒绝访问,因为访问拒绝ACE应用到线程访问标记中的用户。这种情况下,系统并没有检查ACE2和3。对于线程B,ACE1没有应用,因此系统处理ACE2,其允许写操作,并且ACE3允许读和执行操作。

因为系统在请求访问并显式允许或拒绝的时候停止检查,DACL中的ACE顺序非常重要。注意,如果ACE顺序与例子中的不同,系统可能分配访问权限给A。对于系统对象,操作系统定义一个首选的DACL中ACE的顺序。



创建一个DACL

创建适当的 DACL 是你程序开发中必要和重要的,因为一个 NULL DACL 允许所有用户所有访问权限,不要使用 NULL DACL 。

下面例子演示了如何正常创建一个 DACL 。例子,包含一个函数, CreateMyDACL ,用安全描述符定义语言( SDDL )来定义那些赋予的和拒绝的DACL 中的访问控制。为了提供对你程序对象的不同访问,根据你的需要来修改 CreateMyDACL 。

在例子中:

1.       main 函数传递一个 SECURITY_ATTRIBUTES 结构体的地址给 CreateMyDACL 函数

2.       CreateMyDACL 函数使用 SDDL 字符串来:

?        拒绝 guest 和匿名登录用户访问

?        允许授权用户的读 / 写 / 执行访问

?        允许管理员所有控制

3.       更多的 SDDL 字符串格式

4.       CreateMyDACL 函数调用 ConvertStringSecurityDescriptorToSecurityDescriptor 函数转换 SDDL 字符串为一个安全描述符。安全描述符号通过SECURITY_ATTRIBUTES 结构体的 lpSecurityDescriptor 成员来指定。 CreateMyDACL 发送 ConvertStringSecurityDescriptorToSecurityDescriptor 的返回值给 main 函数。

5.       main 函数完成使用 SECURITY_ATTRIBUTES 结构体时, main 函数释放 lpSecurityDescriptor 成员的内存,调用 LocalFree 函数来完成。

注意,成功编译 SDDL 函数,例如: ConvertStringSecurityDescriptorToSecurityDescriptor, 你必须定义 _WIN32_WINNT 常量为 0x0500 或更大。 SDDL在 Windows 2003 家族 ,Windows XP 和 2000 操作系统上可用。

#define _WIN32_WINNT 0x0500
 
#include <windows.h>
#include <sddl.h>
#include <stdio.h>
 
BOOL CreateMyDACL(SECURITY_ATTRIBUTES *);

void main()
{
     SECURITY_ATTRIBUTES  sa;
     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
     sa.bInheritHandle = FALSE;  
     // Call function to set the DACL. The DACL
     // is set in the SECURITY_ATTRIBUTES 
     // lpSecurityDescriptor member.
     if (!CreateMyDACL(&sa))
     {
         // Error encountered; generate message and exit.
         printf("Failed CreateMyDACL\n");
         exit(1);
     }

     // Use the updated SECURITY_ATTRIBUTES to specify
     // security attributes for securable objects.
     // This example uses security attributes during
     // creation of a new directory.
     if (0 == CreateDirectory(TEXT("C:\\MyFolder"), &sa))//创建一个内核对象 sa是安全描述符
     {
         // Error encountered; generate message and exit.
         printf("Failed CreateDirectory\n");
         exit(1);
     }

     // Free the memory allocated for the SECURITY_DESCRIPTOR.
     if (NULL != LocalFree(sa.lpSecurityDescriptor))
     {
         // Error encountered; generate message and exit.
         printf("Failed LocalFree\n");
         exit(1);
     }
}


// CreateMyDACL.
//    Create a security descriptor that contains the DACL you want.
//    This function uses SDDL to make Deny and Allow ACEs.
//
// Parameter:
//    SECURITY_ATTRIBUTES * pSA
//    Pointer to a SECURITY_ATTRIBUTES structure. It is the caller's
//    responsibility to properly initialize the structure and to free 
//    the structure's lpSecurityDescriptor member when the caller has
//    finished using it. To free the structure's lpSecurityDescriptor 
//    member, call the LocalFree function.
// 
// Return value:
//    FALSE if the address to the structure is NULL. 
//    Otherwise, this function returns the value from the
//    ConvertStringSecurityDescriptorToSecurityDescriptor function.
BOOL CreateMyDACL(SECURITY_ATTRIBUTES * pSA)
{
     // Define the SDDL for the DACL. This example sets 
     // the following access:
     //     Built-in guests are denied all access.
     //     Anonymous logon is denied all access.
     //     Authenticated users are allowed read/write/execute access.
     //     Administrators are allowed full control.
     // Modify these values as needed to generate the proper
     // DACL for your application. 
     TCHAR * szSD = TEXT("D:")       // Discretionary ACL
        TEXT("(D;OICI;GA;;BG)")     // Deny access to built-in guests  禁止guest用户
        TEXT("(D;OICI;GA;;;AN)")     // Deny access to anonymous logon 意思是禁止未经授权的用户
        TEXT("(A;OICI;GRGWGX;;;AU)") // Allow read/write/execute to authenticated users 认证用户准许
        TEXT("(A;OICI;GA;;;BA)");    // Allow full control to administrators

    if (NULL == pSA)
        return FALSE;
     return ConvertStringSecurityDescriptorToSecurityDescriptor(//吧上面的描述符字符串转换为安全描述符
                szSD,
                SDDL_REVISION_1,
                &(pSA->lpSecurityDescriptor),
                NULL);
}


可保安全对象 

一个安全对象有一个安全描述符。所有有名字的 Windows 对象都是安全的。有些没有名字的对象,例如:进程和线程对象也有安全描述符。对于大多数安全对象来说,你可以在创建对象的时候指定一个对象的安全描述符。例如:你能在 CreateFile 和 CreateProcess 函数中指定安全描述符。

另外, Windows 安全函数是你能够为操作系统创建的而不是 Windows 创建的安全对象得到和设置安全信息。 Windows 安全函数也提供支持私有使用安全描述符和程序定义对象。(类似于私有命名空间)更多关于私有安全对象信息参见客户服务器访问控制。 

每个安全对象定义它自己的一系列访问权限,并且它拥有的映射通用访问权限。更多关于指定和通用访问权限的信息,参见对象类型总览。

下表显示了函数来操作通用安全对象的安全信息:

对象类型

安全描述符函数

NTFS文件系统的文件和目录

GetNamedSecurityInfo SetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Named pipes

Anonymous pipes

GetSecurityInfo SetSecurityInfo

Processes

Threads

GetSecurityInfo SetSecurityInfo

File-mapping objects

GetNamedSecurityInfo SetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Access tokens

SetKernelObjectSecurity GetKernelObjectSecurity

Window-management objects ( window stations and desktops)

GetSecurityInfo SetSecurityInfo

Registry keys

GetNamedSecurityInfo SetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Windows services

GetNamedSecurityInfo SetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Local or remote printers

GetNamedSecurityInfo SetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Network shares

GetNamedSecurityInfo SetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Interprocess synchronization objects (events, mutexes, semaphores, and waitable timers)

GetNamedSecurityInfo SetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Job objects

GetNamedSecurityInfo SetNamedSecurityInfoGetSecurityInfo,SetSecurityInfo

Directory service objects

These objects are handled by Active Directory Objects. See Active Directory Service Interfaces.


登录会话

一个登录绘画从用户登录到计算机时候开始。所有登录会话中的进程有相同的基本访问标记。访问标记包含登录会话相关的安全上下文,包含用户的 SID和登录标示以及登录 SID 。

 

登录 SID 

一个安全标示符( SID )用来表示登录会话。你可以使用 DACL 中的登录 SID 来在登录会话过程中控制访问。登录 SID 只有在用户登出的时候无效。登录 SID 是计算机运行的时候唯一的。没有其他会话有系统的 SID 。然而,可能的登录 SID 集合在计算机启动的时候被复位。为了从访问标记中返回登录SID ,为 TokenGroups 调用 GetTokenInformation 函数。

 

访问标记 

一个访问标记包含登录会话的安全信息。系统在用户登录的时候创建一个安全标记,每个进程执行用户由于的标记副本。标记表示用户、用户组和用户权限。系统使用标记来控制访问安全对象和控制用户在本地计算机上执行各种系统相关操作。两种访问标记:私有的和伪装的。

 

伪装标记: (注意:上下这几个标记都是iacl的掩码的标志位 这个就是自己的标志位模拟别的进程的标志位  好让他访问自己的内核对象的时候  内核要先访问acl 两个一样的acl 也就访问了两个安全描述符 此时捕获到了那个进程的信息)

一个被创建来捕获客户进程安全信息、允许服务器在安全操作中伪装客户进程的访问标记。

 

主标记:

一个 Windows 内核创建的标记。可能分配给一个进程来表示默认的进程安全信息。




  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Windows 操作系统中,安全描述符Security Descriptor,简称 SD)是一种用于描述系统对象(如文件、文件夹、注册表项等)安全属性的数据结构。它包括了许多信息,如所有者、组、访问控制列表(Access Control List,简称 ACL)等。在使用 SD 时,需要先初始化一个 PSECURITY_DESCRIPTOR 结构体。 下面是一个 PSECURITY_DESCRIPTOR 结构体的定义: ```c typedef struct _SECURITY_DESCRIPTOR { UCHAR Revision; UCHAR Sbz1; SECURITY_DESCRIPTOR_CONTROL Control; PSID Owner; PSID Group; PACL Sacl; PACL Dacl; } SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR; ``` 其中,`Revision` 字段用于指定 SECURITY_DESCRIPTOR 结构体的版本号;`Control` 字段包含了一些标志位,例如是否启用了自相交的 ACL 等;`Owner` 和 `Group` 字段分别指定了对象的所有者和所属组;`Sacl` 和 `Dacl` 字段分别指定了系统访问控制列表和离散访问控制列表。 初始化一个 PSECURITY_DESCRIPTOR 结构体可以通过以下步骤: 1. 调用 `InitializeSecurityDescriptor` 函数初始化结构体: ```c PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); ``` `InitializeSecurityDescriptor` 函数会初始化一个空的 SECURITY_DESCRIPTOR 结构体,其中 `SECURITY_DESCRIPTOR_REVISION` 是版本号。 2. 指定所有者和所属组。可以使用 `AllocateAndInitializeSid` 函数创建一个新的 SID 对象,并将其分配给所有者和所属组: ```c PSID pSidOwner = NULL; PSID pSidGroup = NULL; SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY; if (!AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSidOwner) || !AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pSidGroup)) { LocalFree(pSD); return FALSE; } SetSecurityDescriptorOwner(pSD, pSidOwner, FALSE); SetSecurityDescriptorGroup(pSD, pSidGroup, FALSE); ``` 首先,使用 `AllocateAndInitializeSid` 函数创建了两个 SID,一个是管理员组的 SID,另一个是用户组的 SID。然后使用 `SetSecurityDescriptorOwner` 和 `SetSecurityDescriptorGroup` 分别将它们赋值给 SECURITY_DESCRIPTOR 结构体的 `Owner` 和 `Group` 字段。 3. 添加 ACL。可以使用 `InitializeAcl` 函数初始化 ACL,再使用 `AddAccessAllowedAce` 函数向 ACL 中添加 ACE: ```c PACL pAcl = NULL; EXPLICIT_ACCESS ea; DWORD dwRes = 0; if (AllocateAndInitializeSid(&sidAuth, 1, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS, 0, 0, 0, 0, 0, 0, &ea.Trustee.ptstrName)) { ea.grfAccessPermissions = FILE_GENERIC_READ | FILE_GENERIC_WRITE; ea.grfAccessMode = SET_ACCESS; ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; dwRes = SetEntriesInAcl(1, &ea, NULL, &pAcl); if (dwRes != ERROR_SUCCESS) { LocalFree(pSD); FreeSid(pSidOwner); FreeSid(pSidGroup); return FALSE; } SetSecurityDescriptorDacl(pSD, TRUE, pAcl, FALSE); FreeSid(ea.Trustee.ptstrName); } ``` 这里使用了一个 `EXPLICIT_ACCESS` 结构体来描述 ACE。`Trustee` 字段是一个 TRUSTEE 结构体,用于指定 ACE 的主体。这里将它设置为了访客组的 SID。`grfAccessPermissions` 字段指定了 ACE 的访问权限,这里设置了读写权限。`grfAccessMode` 字段指定了 ACL 的修改方式,这里设置为了 SET_ACCESS,表示覆盖原有 ACE。`grfInheritance` 字段指定了 ACE 是否应该被继承到子对象。最后,使用 `SetEntriesInAcl` 函数将 ACE 添加到 ACL 中,然后使用 `SetSecurityDescriptorDacl` 函数将 ACL 赋值给 SECURITY_DESCRIPTOR 结构体的 `Dacl` 字段。 4. 释放资源。完成后需要释放先前分配的资源: ```c LocalFree(pSD); FreeSid(pSidOwner); FreeSid(pSidGroup); ``` 这里使用了 `LocalFree` 函数释放 SECURITY_DESCRIPTOR 对象,和 `FreeSid` 函数释放所有者、所属组和 ACE 的 SID。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值