GetAce() 返回无法识别的受托者 (SID)
GetAce() returning unrecognizable Trustee (SID)
我正在继续寻找圣杯 - 或者,实际上,只是编写一些 C++ 代码,对文件进行一些非常基本的 ACL 修改。而且,我继续用各种挑战来撞墙。最近的一个是 GetAce()
函数返回的“受托人”似乎不是可识别的受托人,即使我确切地知道它应该是什么。
在较高级别上,我目前正在尝试删除特定文件上的显式 ACE,该文件拒绝访问众所周知的 Everyone 组。有趣的是,如果我使用 GetExplicitEntriesFromAcl()
而不是 GetAce()
,我将能够获得可识别的 SID,并且它可以与使用 EqualSid()
的 Everyone SID 进行正确比较;但是,我不知道如何从 GetExplicitEntriesFromAcl()
获取信息,然后使用它从 ACL 中完全删除 ACE,因为那时我没有获得 ACE 的绝对索引,并且没有似乎不是 RemoveExplicitEntriesFromAcl()
类型的函数。
下面是使用 GetAce()
的当前代码,但我愿意听取有关如何可靠地定位和删除 Everyone 组的 DENY ACE 的其他建议。
BOOL removeAce(LPTSTR filePath) {
PACL existingAcl;
PSECURITY_DESCRIPTOR securityDescriptor;
PSID everyoneSid;
// Get PSID for well-known "Everyone" group
SID_IDENTIFIER_AUTHORITY sidAuthority = SECURITY_WORLD_SID_AUTHORITY;
if (!AllocateAndInitializeSid(&sidAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid))
return false;
// Make sure we really have a file path
if (filePath == NULL || wcscmp(filePath, L"") == 0)
return false;
// Retrieve the ACL for the file, or bail out.
if (GetNamedSecurityInfo(filePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &existingAcl, NULL, &securityDescriptor) != ERROR_SUCCESS)
return false;
EXPLICIT_ACCESS* aclEntries;
ULONG numEntries = existingAcl->AceCount;
// Loop through all ACEs
for (DWORD i = 0; i < numEntries; i++) {
// Going to cast as a ACCESS_DENIED_ACE entry.
ACCESS_DENIED_ACE* entry;
// Try to get the ACE at current index, or continue to next one.
if (!GetAce(existingAcl, i, (LPVOID*) &entry))
continue;
// We're only interested in DENY entries.
if (entry->Header.AceType != ACCESS_DENIED_ACE_TYPE)
continue;
// Cast a couple of things to make it easier below
PSID thisSid = (PSID)entry->SidStart;
EXPLICIT_ACCESS* eaEntry = (EXPLICIT_ACCESS*)entry;
/* This is where I start to have problems - I put this code
* in strictly for debug purposes, and it always hits the
* default case, indicating that the TrusteeForm is either
* some unknown type, or I'm doing something insanely
* wrong and pointing to the wrong block of memory
* somewhere.
*/
switch (thisEntry->Trustee.TrusteeForm) {
case TRUSTEE_IS_SID:
OutputDebugString(L"We have a SID.\n");
break;
case TRUSTEE_IS_NAME:
OutputDebugString(L"We have a name.\n");
break;
case TRUSTEE_IS_OBJECTS_AND_SID:
OutputDebugString(L"We have objects and a SID.\n");
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
OutputDebugString(L"We have objects and a name.\n");
break;
default:
OutputDebugString(L"We have an alien Trustee type.\n");
}
/* This is the ultimate goal - being able to match the Trustee
* of the current ACE being evaluated with the Everyone SID, but
* this if statement never evaluates to True, and, so far, it
* seems to be because the TrusteeForm isn't recognized as a SID
* - or anything else for that matter.
*/
if (eaEntry->Trustee.TrusteeForm == TRUSTEE_IS_SID
&& EqualSid((PSID)entry->SidStart, everyoneSid))
OutputDebugString(L"This is our EVERYONE entry.\n");
}
return true;
}
SidStart
不是指向 SID 的指针;它是 SID 的前 4 个字节。您需要像这样访问它:
PSID thisSid = (PSID)&(entry->SidStart);
我正在继续寻找圣杯 - 或者,实际上,只是编写一些 C++ 代码,对文件进行一些非常基本的 ACL 修改。而且,我继续用各种挑战来撞墙。最近的一个是 GetAce()
函数返回的“受托人”似乎不是可识别的受托人,即使我确切地知道它应该是什么。
在较高级别上,我目前正在尝试删除特定文件上的显式 ACE,该文件拒绝访问众所周知的 Everyone 组。有趣的是,如果我使用 GetExplicitEntriesFromAcl()
而不是 GetAce()
,我将能够获得可识别的 SID,并且它可以与使用 EqualSid()
的 Everyone SID 进行正确比较;但是,我不知道如何从 GetExplicitEntriesFromAcl()
获取信息,然后使用它从 ACL 中完全删除 ACE,因为那时我没有获得 ACE 的绝对索引,并且没有似乎不是 RemoveExplicitEntriesFromAcl()
类型的函数。
下面是使用 GetAce()
的当前代码,但我愿意听取有关如何可靠地定位和删除 Everyone 组的 DENY ACE 的其他建议。
BOOL removeAce(LPTSTR filePath) {
PACL existingAcl;
PSECURITY_DESCRIPTOR securityDescriptor;
PSID everyoneSid;
// Get PSID for well-known "Everyone" group
SID_IDENTIFIER_AUTHORITY sidAuthority = SECURITY_WORLD_SID_AUTHORITY;
if (!AllocateAndInitializeSid(&sidAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid))
return false;
// Make sure we really have a file path
if (filePath == NULL || wcscmp(filePath, L"") == 0)
return false;
// Retrieve the ACL for the file, or bail out.
if (GetNamedSecurityInfo(filePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &existingAcl, NULL, &securityDescriptor) != ERROR_SUCCESS)
return false;
EXPLICIT_ACCESS* aclEntries;
ULONG numEntries = existingAcl->AceCount;
// Loop through all ACEs
for (DWORD i = 0; i < numEntries; i++) {
// Going to cast as a ACCESS_DENIED_ACE entry.
ACCESS_DENIED_ACE* entry;
// Try to get the ACE at current index, or continue to next one.
if (!GetAce(existingAcl, i, (LPVOID*) &entry))
continue;
// We're only interested in DENY entries.
if (entry->Header.AceType != ACCESS_DENIED_ACE_TYPE)
continue;
// Cast a couple of things to make it easier below
PSID thisSid = (PSID)entry->SidStart;
EXPLICIT_ACCESS* eaEntry = (EXPLICIT_ACCESS*)entry;
/* This is where I start to have problems - I put this code
* in strictly for debug purposes, and it always hits the
* default case, indicating that the TrusteeForm is either
* some unknown type, or I'm doing something insanely
* wrong and pointing to the wrong block of memory
* somewhere.
*/
switch (thisEntry->Trustee.TrusteeForm) {
case TRUSTEE_IS_SID:
OutputDebugString(L"We have a SID.\n");
break;
case TRUSTEE_IS_NAME:
OutputDebugString(L"We have a name.\n");
break;
case TRUSTEE_IS_OBJECTS_AND_SID:
OutputDebugString(L"We have objects and a SID.\n");
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
OutputDebugString(L"We have objects and a name.\n");
break;
default:
OutputDebugString(L"We have an alien Trustee type.\n");
}
/* This is the ultimate goal - being able to match the Trustee
* of the current ACE being evaluated with the Everyone SID, but
* this if statement never evaluates to True, and, so far, it
* seems to be because the TrusteeForm isn't recognized as a SID
* - or anything else for that matter.
*/
if (eaEntry->Trustee.TrusteeForm == TRUSTEE_IS_SID
&& EqualSid((PSID)entry->SidStart, everyoneSid))
OutputDebugString(L"This is our EVERYONE entry.\n");
}
return true;
}
SidStart
不是指向 SID 的指针;它是 SID 的前 4 个字节。您需要像这样访问它:
PSID thisSid = (PSID)&(entry->SidStart);