我使用GetSecurityInfo
功能来获取我自己的进程自由访问控制列表(DACL):
PACL oldAcl;
Pointer se;
GetSecurityInfo(GetCurrentProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
null, null, ref oldAcl, nil, ref se);
然后我可以使用GetExplicitEntriesFromAcl
来破解ACL以获取其中访问控制条目(ACE)的列表:
UInt32 nCount;
EXPLICIT_ACCESS[] list;
GetExplicitEntriesFromAcl(oldAcl, ref nCount, ref list);
我可以查看我的流程中的三个条目列表:
STACKOVERFLOW \ ian(S-1-5-21-6198258843-697258998-2146844275-1109)[SidTypeUser]
NT AUTHORITY \ SYSTEM(S-1-5-18)[SidTypeWellKnownGroup]
我现在想要通过并更新该流程的DACL(当然我已经允许这样做,因为我有WRITE_DACL
- 因为我是业主,{{3 }})。
但我只想重新编写适用于" me" 的访问控制条目。
在这种情况下,碰巧有三个受托人:
受托人作为which means i implicitly have WRITE_DACL
对象呈现给我们(注意,并非所有受试者都有SID)。我从经验中知道我是其中两位受托人;但不是第三个。
是否有一项功能可用于将" me" 与 TRUSTEE
进行比较?
Boolean DoIMatchThisTrustee(TRUSTEE trustee)
{
}
没理由。我已经在自己的流程中删除了PROCESS_VM_READ
,PROCESS_VM_WRITE
和PROCESS_VM_OPERATION
。
答案 0 :(得分:1)
你真的希望检查自由访问控制列表(DACL),这是" me" - 因此启用了您的流程令牌成员。
要确定令牌中是否启用了SID,我们可以使用CheckTokenMembership
函数。
使用GetSecurityInfo
不是我认为的最佳选择,在这里更好地使用GetKernelObjectSecurity
。但是你可以检查和受托人是否愿意("注意,并非所有人都有SID" - 这是一般情况,但是如果 DACL 你将只获得{{1托管人)。代码可以是下一个:
TRUSTEE_IS_SID
答案 1 :(得分:0)
我认为没有任何功能可以比较或规范化TRUSTEE。
ACL中的ACE总是存储一个SID(据我所知),因此当您从ACL获取TRUSTEE时,可以安全地假设TRUSTEE将是TRUSTEE_IS_ * SID表单。
PSID GetSID(const TRUSTEE&t)
{
if (TRUSTEE_IS_SID == t.TrusteeForm) return (PSID) t.ptstrName;
if (TRUSTEE_IS_OBJECTS_AND_SID == t.TrusteeForm) return ((OBJECTS_AND_SID*)t.ptstrName)->pSid;
return NULL;
}
bool DoIMatchThisTrustee(TRUSTEE&t)
{
PSID tsid = GetSID(t);
PSID mysid = GetMySid(); // From process/thread token or somewhere else
return tsid && EqualSid(tsid, mysid);
}
如果您不想假设,那么您可以在字符串表单上使用LookupAccountName
来获取SID。
如果由于某种原因您不想查找任何字符串,您可以执行NT4样式并直接使用ACL。调用GetAce
枚举ACL并使用如下内容:
PSID GetAllowedSID(const ACE_HEADER&ah)
{
switch(ah.AceType)
{
case ACCESS_ALLOWED_ACE_TYPE: return (PSID) &((ACCESS_ALLOWED_ACE*)&ah)->SidStart;
case ACCESS_ALLOWED_CALLBACK_ACE_TYPE: return (PSID) &((ACCESS_ALLOWED_CALLBACK_ACE*)&ah)->SidStart;
case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: return (PSID) &((ACCESS_ALLOWED_CALLBACK_OBJECT_ACE*)&ah)->SidStart;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE: return (PSID) &((ACCESS_ALLOWED_OBJECT_ACE*)&ah)->SidStart;
default: return NULL;
}
}
如果您这样做是为了提高安全性,那么您可能希望以相反的方式做事,并且只允许" NT AUTHORITY \ SYSTEM"和#34; BUILTIN \管理员"这些权利。
登录会话是否是"你"是值得商榷但你不能比较完整的SID来找出,只有SECURITY_NT_AUTHORITY + SECURITY_LOGON_IDS_RID parts。
答案 2 :(得分:0)
RbMm的评论提醒我,我已经知道了我脑中某处的答案: CheckTokenMembeship
:
//Get the ACL on the process
PACL oldAcl;
Pointer se;
GetSecurityInfo(GetCurrentProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
null, null, ref oldAcl, nil, ref se); //allocates memory into se, which we must LocalFree later
//oldAcl is a pointer to inside the se blob
//Crack open the ACL, to feast on the entries inside
UInt32 nCount;
EXPLICIT_ACCESS[] list;
GetExplicitEntriesFromAcl(oldAcl, ref nCount, ref list); //allocates memory into list, which we must localFree later
//the flags i want to remove me from having
DWORD removeFlags = PROCESS_VM_READ || PROCESS_VM_WRITE || PROCESS_VM_OPERATION;
//Go through the list, looking for entries that are "me"
for (EXPLICIT_ACCESS ea in list)
{
if (ea.Trustee.TrusteeForm != TRUSTEE_IS_SID)
continue;
BOOL isMember;
CheckTokenMembership(0, PSID(ea.Trustee.ptstrName), out isMember);
if (!isMember)
continue;
//Remove the permissions
ea.grfAccessPermissions = ea.grfAccessPermissions && (!removeFlags);
aclUpdateNeeded = true;
}
//write the new DACL
SetEntriesInAcl(nCount, list, null, out newAcl); //allocates a new acl
SetSecurityInfo(GetCurrentProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
null, null, newAcl, null); //apply the new acl
LocalFree(list); //free the memory allocated by GetExplicitEntriesFromAcl
LocalFree(se); //free the memory allocated by GetSecurityInfo