You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从文件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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 02:25:54