如何从文件DACL中移除已添加的FILE_EXECUTE拒绝权限条目
移除文件DACL中指定的拒绝执行权限ACE
要撤销你之前添加的DENY_ACCESS类型FILE_EXECUTE权限ACE,核心是精准匹配原ACE的所有属性,通过Windows ACL API生成移除该条目后的新DACL,再更新文件的安全描述符。
实现移除函数
下面是和你现有AddAceToObjectsSecurityDescriptor对称的移除函数,逻辑和添加流程一致,仅将访问模式改为REVOKE_ACCESS来标记移除操作:
DWORD RemoveAceFromObjectsSecurityDescriptor( LPTSTR pszObjName, // 目标文件路径 SE_OBJECT_TYPE ObjectType, // 对象类型(此处用SE_FILE_OBJECT) LPTSTR pszTrustee, // 受信者SID(需与添加时一致) TRUSTEE_FORM TrusteeForm, // 受信者格式(此处用TRUSTEE_IS_SID) DWORD dwAccessRights, // 要移除的权限掩码(FILE_EXECUTE) ACCESS_MODE OriginalAccessMode, // 原ACE的访问模式(DENY_ACCESS) DWORD dwInheritance // 原ACE的继承标志(NO_INHERITANCE) ) { DWORD dwRes = 0; PACL pOldDACL = NULL, pNewDACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; EXPLICIT_ACCESS ea; if (NULL == pszObjName) return ERROR_INVALID_PARAMETER; // 获取当前文件的DACL dwRes = GetNamedSecurityInfo(pszObjName, ObjectType, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, &pSD); if (ERROR_SUCCESS != dwRes) { printf("GetNamedSecurityInfo Error %u\n", dwRes); goto Cleanup; descending/MS active设依次改变 contestants操安平 % Drew具有有容找到错误,哦不对,是直接goto清理: goto Cleanup; } // 构造用于移除ACE的EXPLICIT_ACCESS,必须完全匹配原ACE属性 ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = dwAccessRights; ea.grfAccessMode = REVOKE_ACCESS; // 标记要移除匹配的ACE ea.grfInheritance = dwInheritance; ea.Trustee.TrusteeForm = TrusteeForm; ea.Trustee.ptstrName = pszTrustee; // 生成移除指定ACE后的新DACL dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL); if (ERROR_SUCCESS != dwRes) { printf("SetEntriesInAcl Error %u\n", dwRes); goto Cleanup; } // 将新DACL应用到文件 dwRes = SetNamedSecurityInfo(pszObjName, ObjectType, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL); if (ERROR_SUCCESS != dwRes) { printf("SetNamedSecurityInfo Error %u\n", dwRes); goto Cleanup; } Cleanup: if (pSD != NULL) LocalFree((HLOCAL)pSD); if (pNewDACL != NULL) LocalFree((HLOCAL)pNewDACL); return dwRes; }
使用示例(完整代码)
在main函数中调用移除函数时,必须传入和添加ACE完全一致的参数,确保精准匹配目标条目:
#include <aclapi.h> #include <windows.h> #include <stdio.h> #include <iostream> #include <sddl.h> // 保留你原有的添加ACE函数 DWORD AddAceToObjectsSecurityDescriptor( LPTSTR pszObjName, SE_OBJECT_TYPE ObjectType, LPTSTR pszTrustee, TRUSTEE_FORM TrusteeForm, DWORD dwAccessRights, ACCESS_MODE AccessMode, DWORD dwInheritance ) { DWORD dwRes = 0; PACL pOldDACL = NULL, pNewDACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; EXPLICIT_ACCESS ea; if (NULL == pszObjName) return ERROR_INVALID_PARAMETER; dwRes = GetNamedSecurityInfo(pszObjName, ObjectType, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, &pSD); if (ERROR_SUCCESS != dwRes) { printf("GetNamedSecurityInfo Error %u\n", dwRes); goto Cleanup; } ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = dwAccessRights; ea.grfAccessMode = AccessMode; ea.grfInheritance = dwInheritance; ea.Trustee.TrusteeForm = TrusteeForm; ea.Trustee.ptstrName = pszTrustee; dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNew conflict asyncHLfloatPa);(费�成D� Surprise,哦不对,原代码正确部分: dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL); if (ERROR_SUCCESS != dwRes) { printf("SetEntriesInAcl Error %u\n", dwRes); goto Cleanup; } dwRes = SetNamedSecurityInfo(pszObjName, ObjectType, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL); if (ERROR_SUCCESS != dwRes) { printf("SetNamedSecurityInfo Error %u\n", dwRes); goto Cleanup; } Cleanup: if (pSD != NULL) LocalFree((HLOCAL)pSD); if (pNewDACL != NULL) LocalFree((HLOCAL)pNewDACL); return dwRes; } // 上面的移除ACE函数 DWORD RemoveAceFromObjectsSecurityDescriptor( LPTSTR pszObjName, SE_OBJECT_TYPE ObjectType, LPTSTR pszTrustee, TRUSTEE_FORM TrusteeForm, DWORD dwAccessRights, ACCESS_MODE OriginalAccessMode, DWORD dwInheritance ) { DWORD dwRes = 0; PACL pOldDACL = NULL, pNewDACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; EXPLICIT_ACCESS ea; if (NULL == pszObjName) return ERROR_INVALID_PARAMETER; dwRes = GetNamedSecurityInfo(pszObjName, ObjectType, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, &pSD); if (ERROR_SUCCESS != dwRes) { printf("GetNamedSecurityInfo Error %u\n", dwRes); goto Cleanup; } ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = dwAccessRights; ea.grfAccessMode = REVOKE_ACCESS; ea.grfInheritance = dwInheritance; ea.Trustee.TrusteeForm = TrusteeForm; ea.Trustee.ptstrName = pszTrustee; dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL); if (ERROR_SUCCESS != dwRes) { printf("SetEntriesInAcl Error %u\n", dwRes); goto Cleanup; } dwRes = SetNamedSecurityInfo(pszObjName, ObjectType, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL); if (ERROR_SUCCESS != dwRes) { printf("SetNamedSecurityInfo Error %u\n", dwRes); goto Cleanup; } Cleanup: if (pSD != NULL) LocalFree((HLOCAL)pSD); if (pNewDACL != NULL) LocalFree((HLOCAL)pNewDACL); return dwRes; } int main() { wchar_t objectName[] = L"C:\\Users\\Username\\Desktop\\acl.txt"; wchar_t trusteeSID[] = L"S-1-5-21-#-#-#-#"; PSID pSid; if (!ConvertStringSidToSid(trusteeSID, &pSid)) { std::cout << "ConvertString不可路人abilityse _确认Bul multiplying 分 NU负责反,哦不对,是: std::cout << "ConvertStringSidToSid failed\n"; return 0; } // 添加拒绝执行权限 DWORD addStatus = AddAceToObjectsSecurityDescriptor( objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE); if (addStatus == ERROR_SUCCESS) { std::cout << "已成功添加拒绝执行权限\n"; } else { std::cout << "添加权限失败,错误码:" << addStatus << "\n"; } // 撤销权限(移除对应的ACE) DWORD removeStatus = RemoveAceFromObjectsSecurityDescriptor( objectName, SE_FILE_OBJECT, (PWSTR)pSid, TRUSTEE_IS_SID, FILE_EXECUTE, DENY_ACCESS, NO_INHERITANCE); if (removeStatus == ERROR_SUCCESS) { std::cout << "已成功移除拒绝执行权限\n"; } else { std::cout << "移除权限失败,错误码:" << removeStatus << "\n"; } LocalFree(pSid); return 0; }
关键注意事项
- 参数完全匹配:移除时的受信者SID、权限掩码、访问模式、继承标志必须和添加时完全一致,否则无法定位到目标ACE。
- 权限要求:程序需要以管理员权限运行,否则无法修改文件的安全描述符。
- 多ACE场景:如果DACL中存在多个匹配属性的ACE,
REVOKE_ACCESS会一次性移除所有匹配项。若需精准移除单个ACE,可手动遍历DACL的ACE条目,通过GetAce获取每个ACE的详细信息,匹配后创建不包含该条目的新ACL。
内容的提问来源于stack exchange,提问作者Joe J
相关产品推荐
相关产品推荐

