回复 12# jd19970829
是这样的,所有可继承的ACE 都将自动应用到子对象上,_SeTreeResetNamedSecurityInfo最终调用了AdvApi32.SetNamedSecurityInfo函数(只不过加上了递归遍历功能),看下这个函数的说明:
If you are setting the discretionary access control list (DACL) or system access control list (SACL) of an object, the system automatically propagates any inheritable access control entries (ACEs) to existing child objects, according to the rules of inheritance.
如果要递归替换ACL而不是添加,可以自己写个递归函数遍历整个目录树,每找到一个文件/文件夹,调用_SeSetFileSecurity设置它的安全权限。论坛中有遍历文件的源码。
LocalSecurityAuthority._SetFileSecurityOwner其实是调用了同一个库中的_SetFileSecurity,_SetFileSecurity和lsasecur._SeSetFileSecurity原型都一样。当初编写lsasecur.au3时,考虑到了效率方面的问题,便舍弃了_SeSetFileSecurityOwner函数,设置所有者也可以用_SeSetFileSecurity函数完成:
#include <lsasecur.au3>
; Enable RESTORE privilege for current thread.
Local $hToken = _SeOpenProcessToken(-1)
Local $aPriv[1][2] = [[$SE_RESTORE_PRIV, $SE_PRIV_ENABLED]]
_SeAdjustTokenPrivs($hToken, $aPriv)
_SeCloseHandle($hToken)
Local $pOwnerSid = _SeLookupAccountName("Everyone")
Local $pSecurDescr = _SeInitSecurityDescriptor()
_SeSetSecurityDescriptorOwner($pSecurDescr, $pOwnerSid)
If _SeSetFileSecurity("C:\1", $SE_INFO_OWNER, $pSecurDescr) Then
MsgBox(48, "OK", "Done.")
Else
MsgBox(48, "Error", _SeFormatMsg())
EndIf
_SeHeapFree($pOwnerSid)
_SeHeapFree($pSecurDescr)
或者另一种方法:
#include <lsasecur.au3>
; Enable RESTORE privilege for current thread.
Local $hToken = _SeOpenProcessToken(-1)
Local $aPriv[1][2] = [[$SE_RESTORE_PRIV, $SE_PRIV_ENABLED]]
_SeAdjustTokenPrivs($hToken, $aPriv)
_SeCloseHandle($hToken)
Local $pOwnerSid = _SeLookupAccountName("Everyone")
$fStatus = _SeSetNamedSecurityInfo("C:\1", $SE_FILE_OBJECT, $SE_INFO_OWNER, $pOwnerSid, 0, 0, 0)
If $fStatus Then
MsgBox(48, "OK", "Done.")
Else
MsgBox(48, "Error", _SeFormatMsg())
EndIf
_SeHeapFree($pOwnerSid)
必须为调用者开启RESTORE权限,否则只能设置所有者为 当前用户/用户组。
如果要递归设置所有者:
#include <lsasecur.au3>
Local $hToken = _SeOpenProcessToken(-1)
Local $aPriv[1][2] = [[$SE_RESTORE_PRIV, $SE_PRIV_ENABLED]]
_SeAdjustTokenPrivs($hToken, $aPriv)
_SeCloseHandle($hToken)
Local $pOwnerSid = _SeLookupAccountName("Everyone") ; Try to use another user account.
; Equal to _SeCreateWellKnownSid(1)
$fStatus = _SeTreeResetNamedSecurityInfo("C:\1", $SE_FILE_OBJECT, $SE_INFO_OWNER, $pOwnerSid, 0, 0, 0, _
"", $SE_TREE_SECUR_INVOKE_NEVER) ; Never track the progress.
If $fStatus Then
MsgBox(48, "OK", "Done.")
Else
MsgBox(48, "Error", _SeFormatMsg())
EndIf
新版的lsasecur舍弃了_SeSet*SecurityOwner和_SeSet*SecurityDacl函数,因为都可以调用_SeSet*Security函数完成一样的功能,只不过自己写有点麻烦,但是,_SeSet*Security*函数在内部要检查参数是否合法,效率也就因此降低了许多,尤其是当多个函数都要检查同一个参数时,所以舍弃了。但也同时考虑到了如果不执行参数检查,可能会引起程序非常严重的错误,比如非法的内存访问(SID、ACL、安全描述符 都是内存指针),所以加了一个修复异常的_SeRegisterExceptionHandler函数,具体参考lsasecur原帖。 |