锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / C++API和类开源 / Windows访问控制模型的剖析安全描述符
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

Windows访问控制模型的剖析安全描述符


13. Dissecting the Security Descriptor剖析安全描述符

Q. How do you obtain the security descriptor for a folder?问:如何获取文件夹的安全描述符?

The question doesn't specify what specific information it wants to be returned in the security descriptor, so we will assume it wants the whole lot returned in the security descriptor (Control, SACL, DACL, Group, and Owner).

In order to read the SACL, you must first have the SeSecurityPrivilege enabled in your token (use the handy SetPrivilege() function from fig. 10 for this).

该问题并未在安全描述符中指定要返回的特定信息,因此我们假设它希望在安全描述符中返回整个批次(控件,SACL,DACL,组和所有者)。

为了读取SACL,必须首先SeSecurityPrivilege在令牌中启用(SetPrivilege()为此使用图10中的便捷功能)。

  1. Do not attempt to use this method if you are on Windows 2000 or later (detect the Windows version, and branch out to separate code instead), otherwise you will trash the security on the operating system. To obtain the security descriptor for a file, call the GetFileSecurity() API (or GetKernelObjectSecurity() if you already have a handle).
  2. If you have the file open, call GetSecurityInfo() on the opened file handle. Otherwise call GetNamedSecurityInfo() on the filename. Since we're only getting the security descriptor, we can set the other parameters to NULL. Don't forget to LocalFree() the security descriptor when you're done.
  3. The GetNamedSecurityInfo() API has been encapsulated into the global ATL function: AtlGetSecurityDescriptor(). It returns the information in a CSecurityDesc type for us. By default, AtlGetSecurityDescriptor() automatically enables the SeSecurityPrivilege for us, so there is no need to use SetPrivilege() here.
  4. 如果您使用的是Windows 2000或更高版本,请不要尝试使用此方法(检测Windows版本,然后分支到单独的代码中),否则会破坏操作系统的安全性。要获取文件的安全描述符,请调用GetFileSecurity()API(或者GetKernelObjectSecurity()如果您已经有一个句柄)。
  5. 如果您已打开文件,请调用GetSecurityInfo()打开的文件句柄。否则调用GetNamedSecurityInfo()文件名。由于仅获取安全描述符,因此可以将其他参数设置为NULL。完成后不要忘记LocalFree()安全描述符。
  6. GetNamedSecurityInfo()已封装到全局ATL函数中:AtlGetSecurityDescriptor()。CSecurityDesc为我们返回一种类型的信息。默认情况下,AtlGetSecurityDescriptor()会自动SeSecurityPrivilege为我们启用,因此无需在SetPrivilege()此处使用。
int GetFolderSecDesc(const CStringT< <TCHAR, 
       ATL::StrTraitATL< <TCHAR> > &FileName)
{
  ATL::CSecurityDesc OutSecDesc;
  ATL::AtlGetSecurityDescriptor(FileName, SE_FILE_OBJECT, &OutSecDesc);
  return 0;
}

Figure 15: Obtaining the security descriptor for a folder.

GetNamedSecurityInfo() can also be used to read security descriptors from registry keys, kernel objects, window stations, and other objects. For a complete list of objects supported by GetNamedSecurityInfo(), see section 17 or your help documentation for  SE_OBJECT_TYPE. If your object is not supported by GetNamedSecurityInfo(), then open a handle yourself (with READ_CONTROL access), and pass it to the GetSecurityInfo() function.

The returned security descriptor will be in self-relative form. If you are going to enumerate the security descriptor, it will be easier if the security descriptor was absolute.

GetNamedSecurityInfo()也可以用于从注册表项,内核对象,窗口站和其他对象中读取安全描述符。有关所支持的对象的完整列表GetNamedSecurityInfo(),请参阅第17节或SE_OBJECT_TYPE 的帮助文档。如果您的对象不受GetNamedSecurityInfo()的支持,请自己打开一个句柄(具有READ_CONTROL访问权限),然后将其传递给GetSecurityInfo()函数。

返回的安全描述符将为自相关形式。如果要枚举安全描述符,则如果安全描述符是绝对的,则将更加容易。

Q. Convert a self relative security descriptor to an absolute one.问:将自相关安全描述符转换为绝对描述符。

  1. You will have to call the MakeAbsoluteSD() API to make the security descriptor absolute. The MakeAbsoluteSD() function does not allocate the buffers for you, you must allocate them yourselves. There are five buffers you have to manage, just for one security descriptor! And if you have to pass the security descriptor back to the operating system (as will happen when we reach part 4 ), the chances of leaking memory become very likely. You could maintain five global variables to keep track of the buffers, or you can allocate one large block of memory, and with some creative pointer fix ups, set the other buffers to point inside this big buffer (this technique is described in the C FAQ ). Now with the buffer allocated, and your pointers pointing to big enough memory locations, the next call to MakeAbsoluteSD() should work.
  2. If your self-relative security descriptor is going to stay in scope throughout this task, then you can build the absolute security descriptor yourself. Using functions like GetSecurityDescriptorDacl(), GetSecurityDescriptorOwner() and friends will give you the pointers you need.
  3. ATL contains the CSecurityDesc::MakeAbsolute() method that makes converting security descriptors far easier. What's more, you no longer need to worry about managing buffers; ATL handles the buffers for you. Note that most of the reasons to convert a security descriptor aren't necessary with ATL. (The ATL security classes can handle absolute security descriptors as well as self relative security descriptors.)
  4. 您将必须调用MakeAbsoluteSD()以使安全描述符绝对。该MakeAbsoluteSD()函数不会为您分配缓冲区,您必须自行分配它们。您必须管理五个缓冲区,仅用于一个安全描述符!而且,如果您必须将安全描述符传递回操作系统(当我们到达第4部分时将发生这种情况),则很可能会发生内存泄漏的情况。您可以维护五个全局变量来跟踪缓冲区,或者可以分配一个大的内存块,并使用一些创造性的指针修复程序,将其他缓冲区设置为指向该大缓冲区内部(此技术在C FAQ中进行了描述)。现在已分配了缓冲区,并且您的指针指向足够大的内存位置,下一个调用MakeAbsoluteSD()应该可以工作。
  5. 如果您的自相关安全描述符将在整个任务中保持作用,那么您可以自己构建绝对安全描述符。使用功能,如GetSecurityDescriptorDacl(),GetSecurityDescriptorOwner()和类似会给你你需要的指针。
  6. ATL包含CSecurityDesc::MakeAbsolute()使安全描述符的转换变得更加容易的方法。而且,您不再需要担心缓冲区的管理。ATL为您处理缓冲区。请注意,转换ATL不需要大多数原因来转换安全描述符。(ATL安全类可以处理绝对安全描述符以及自身相对安全描述符。)
...  OutSecDesc.MakeAbsolute();  ...

Figure 16: Converting a self relative security descriptor to an absolute security descriptor.

It's much easier to do the reverse (i.e. convert an absolute security descriptor to a self relative one). The reason is because an absolute security descriptor has to maintain five buffers to work (or in our case, a heap of five pointers), whereas a self relative security descriptor only needs to maintain one buffer. The good news is that unless you need to work with method 1, converting security descriptors is rarely required.

You may have been asking why not allocate a buffer of the same size as the self-relative security descriptor, reinterpret_cast it to an absolute security descriptor, then convert the offset index into physical pointers. The problem is that you are assuming indexes that are of the same size as the pointers. This is not true on Win64, and attempting to do so will lead to errors (yes, Microsoft should have made the DWORD indexes in the self relative security descriptor size agnostic, but now we're stuck with that 17+ year old mistake).

进行相反操作要容易得多(即将绝对安全描述符转换为自相关描述符)。原因是因为绝对安全描述符必须维护五个缓冲区才能工作(或者在我们的示例中是五个指针的堆),而自相关安全描述符仅需要维护一个缓冲区。好消息是,除非您需要使用方法1,否则很少需要转换安全描述符。

您可能一直在问为什么不分配与自安全标识符相同大小的缓冲区,将其分配reinterpret_cast给绝对安全描述符,然后将偏移量索引转换为物理指针。问题是您假设索引的大小与指针的大小相同。在Win64上并非如此,尝试这样做会导致错误(是的,Microsoft应该使DWORD自我相对安全描述符大小中的索引不可知,但现在我们已经陷入了17年以上的错误)。

Q. You have been supplied with a security descriptor. You now need to print out the contents of the security descriptor.问:为您提供了一个安全描述符。现在,您需要打印出安全描述符的内容。

Although it's not mentioned, this question wants the security descriptor in either debugger form, or SDDL form.

  1. First of all, make sure the security descriptor is in absolute form (it will be easier to read that way). There are a set of functions that you can use to obtain the security descriptor parts. They are GetSecurityDescriptorLength(), GetSecurityDescriptorControl(), GetSecurityDescriptorOwner(), GetSecurityDescriptorGroup(), GetSecurityDescriptorDacl(), and GetSecurityDescriptorSacl(). These functions return the length, control bits, owner, group, DACL and SACL respectively (whether the security descriptor is self relative or absolute). With the group and owner obtained, you should now print out the SID in textual form. Printing out the Access Control lists will be covered later.
  2. You will have the benefit of SDDL in your case. Once you have the security descriptor, you can call ConvertSecurityDescriptorToStringSecurityDescriptor(). This will convert the security descriptor (absolute or self relative) into an SDDL string, which you can print out.
  3. ATL can convert a CSecurityDesc into an SDDL string using the CSecurityDesc::ToString().
  4. 尽管未提及,但此问题希望使用调试器形式或SDDL形式的安全描述符。

    1. 首先,请确保安全描述符采用绝对形式(这样更容易阅读)。您可以使用一组函数来获取安全描述符部分。它们是GetSecurityDescriptorLength(),GetSecurityDescriptorControl(),GetSecurityDescriptorOwner(),GetSecurityDescriptorGroup(),GetSecurityDescriptorDacl(),和GetSecurityDescriptorSacl()。这些函数分别返回长度,控制位,所有者,组,DACL和SACL(安全描述符是自相关的还是绝对的)。获得组和所有者后,您现在应该以文本形式打印出SID。打印出访问控制列表将在以后介绍。
    2. 在您的情况下,您将受益于SDDL。有了安全描述符后,就可以调用ConvertSecurityDescriptorToStringSecurityDescriptor()。这会将安全描述符(绝对或自相关)转换为SDDL字符串,您可以将其打印出来。
    3. ATL可以使用将ACSecurityDesc转换为SDDL字符串CSecurityDesc::ToString()。
...
ATL::CString pstr = _T("");
OutSecDesc.ToString(&pstr);
std::wcout << static_cast(pstr);
...

Figure 17: Printing out the contents of the security descriptor.

Now that you have the security descriptor presented in a uniform way (SDDL), you have reduced the task of parsing a security descriptor into a text processing task.现在,您已经以统一的方式(SDDL)展示了安全描述符,您已经减少了将安全描述符解析为文本处理任务的任务

友情链接
版权所有 Copyright(c)2004-2015 锐英源软件

公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768

地址:郑州市文化路47号院1号楼4层(47-1楼位于文化路和红专路十字路口东北角,郑州大学工学院招待所南边,工学院科技报告厅西边。)