修改 Windows 文件访问权限的多种方法

这篇具有很好参考价值的文章主要介绍了修改 Windows 文件访问权限的多种方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

提示:本文修改后包含编程方法以及附注的工具方法,传统的资源管理器交互方法等等。

由于文件是安全对象,因此访问它们受访问控制模型控制,该模型控制对 Windows 中所有其他安全对象的访问。 

更改文件或目录对象的安全描述符,需要调用 SetNamedSecurityInfo 或 SetSecurityInfo 等函数。

ACLAccess Control List,用来表示用户(组)权限的列表,包括 DACL 和 SACL
ACEAccess Control Entry,ACL 中的元素;
DACLDiscretionary Access Control List,用来表示安全对象权限的列表;
SACLSystem Access Control List,用来记录对安全对象访问的日志。

关于这几个概念已经有很多资料解释,这里就不详细展开了。(以下仅介绍通过 Win32API 修改文件安全属性的一些内容)。

本文以 SetNamedSecurityInfo 函数为例,简单讲解如何通过编程修改指定文件的 ACL 主体和添加 ACE 条目。后文修改的文件比较特殊,它们受到本地内置安全主体 TrustedInstaller 的完全控制保护,本文旨在通过相关 API 实现修改这类文件的完全控制权限。有关内置安全主体 TrustedInstaller 的信息,需要具有一定的知识基础,限于篇幅原因这里不详细展开。


一、编程实现方法阐述

1.1 修改 ACL 的所有者

SetNamedSecurityInfo 函数用于在指定对象的安全描述符(ACL)中设置指定的安全信息。 调用方按名称标识对象。

这里的按名称标识对象,表示设置安全信息时候,目标对象名是字符串格式,且对于不同对象类型的字符串格式,可以参阅说明:SE_OBJECT_TYPE。我们这里要修改NTFS文件系统中指定文件的安全属性,按照标准需要填写文件绝对路径的宽字符串,其中路径以反斜杠 (" / ") 或者双斜杠 (" \\ ") 给出,并且要以 NULL 结尾。

下面给出该函数的参数:

DWORD SetNamedSecurityInfoW(
  [in]           LPWSTR               pObjectName,
  [in]           SE_OBJECT_TYPE       ObjectType,
  [in]           SECURITY_INFORMATION SecurityInfo,
  [in, optional] PSID                 psidOwner,
  [in, optional] PSID                 psidGroup,
  [in, optional] PACL                 pDacl,
  [in, optional] PACL                 pSacl
);

这些参数的定义是:

pObjectName 指定目标对象的名称;
ObjectType 指示 pObjectName 的类型,如果修改 NTFS 文件则填写为 SE_FILE_OBJECT;
SecurityInfo 指示要设置的安全信息的类型;
psidOwner 指向标识对象所有者的 SID 结构的指针;
psidGroup 指向标识对象主组的 SID 的指针;
pDacl 指向 对象的新 DACL 的指针;
pSacl 指向 对象的新 SACL 的指针。

其中,如果 SecurityInfo 填写为 OWNER_SECURITY_INFORMATION 表明对安全主体的操作(也就是控制列表所有者);如果填写为 DACL_SECURITY_INFORMATION 则表明对安全对象(ACE)的权限的操作。这里需要注意:如果调用方令牌对应的账户标识符(SID)不是文件安全主体指向的账户标识符,则对安全对象权限的操作会被拒绝

修改文件安全属性需要进程的令牌具有一定的访问控制权限,这里我们需要获取两个权限 SE_SECURITY_NAME 和 SE_TAKE_OWNERSHIP_NAME 。这两个权限可以通过 AdjustTokenPrivileges 函数获得,而赋予新的令牌则需要调用方线程具有管理员权限。所以进程需要以提升的令牌启动才能正确获取权限

从零开始的项目都是不容易的,有一个参考最好不过了。这里我们可以参考资源管理器的功能实现文件安全属性的修改,下面的图片展示了通过资源管理器查看的目标文件的安全属性页面信息:

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具
目标文件的安全属性信息页

通过观察,我们可以发现,当前的所有者为 TrustedInstaller 并且只有它具有完全控制权限,其他安全对象只具有读取和执行的权限。此外我们还发现,对于该文件权限修改的按钮都是灰色或者具有盾牌图标。我们将其与用户具有完全访问控制权的文件安全信息进行对比,就可以发现所有者信息起到了至关重要的作用,调用方必须为文件的安全主体或者权限比安全主体高,否则不能修改安全属性表。所以当正确获取权限后,我们首先需要修改文件的安全主体(所有者)。

首先我们简述一下通过资源管理器进行修改的步骤:

Step 1: 首先选中要修改的文件(夹),打开右键菜单,在菜单中找到“属性”项目,点击打开属性对话框;

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

Step 2: 在属性对话框中选中“安全”选项卡,右下角点击“高级(安全设置)”按钮;

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

Step 3: 可以看到该页面包含两个主要部分:1)所有者;2)成员及其权限

并且后面都有带有盾牌的“更改”按钮,再结合说明文档可知,如果当前进程代表的账户权限低于所有者所具有的权限,则低权限进程不具有修改高权限进程的权限能力;

这里我们需要先修改所有者,点击最上面的TrustedInstaller字样后面的更改按钮,此时可能弹出UAC对话框提示用户需要提升权限,也可能没有提示直接提升(取决于计算机配置的UAC警告级别)

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

Step 4: 此时会弹出选择所有者的对话框,点击“高级”按钮展开这个编辑器窗口:

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

Step 5: 在高级窗口中点击立即查找,在查找的列表中找到当前登陆用户的用户名,然后点击确定,或者选择everyone(字面意思,代表任何用户)。

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

Step 6: 逐级确定并应用,可以发现所有者被成功更改:

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

最后一步点击“应用”,然后再点击确定,应用更改,随后重新打开高级安全设置页面,选择要修改权限的成员,并发现编辑区域按钮被点亮,点击“添加/编辑”:

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

随后,在打开的窗口中,先点击蓝色字“选择主体”,类似于修改所有者的操作完成权限配置,并点击确定,最后点击应用即可完成整个修改操作:

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

最后,补充一下修改完成后改回TrustedInstaller的方法:在更改所有者时候,直接输入 NT SERVICE\TrustedInstaller 需要注意不能有拼写错误!然后其他步骤不变。

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具

我们通过设置 SetNamedSecurityInfo 函数的 SecurityInfo 参数为 OWNER_SECURITY_INFORMATION 并指定 psidOwner 为指向新所有者的安全描述符 (SID) 结构的指针。

SID 就相当于所有者的身份证,那么我们如何获取到所需要的 SID 呢?

LookupAccountName 函数可供获取指定用户名对应的 SID 。

其参数如下:

BOOL LookupAccountNameW(
  [in, optional]  LPCWSTR       lpSystemName,
  [in]            LPCWSTR       lpAccountName,
  [out, optional] PSID          Sid,
  [in, out]       LPDWORD       cbSid,
  [out, optional] LPWSTR        ReferencedDomainName,
  [in, out]       LPDWORD       cchReferencedDomainName,
  [out]           PSID_NAME_USE peUse
);

其中,lpAccountName 指向指定帐户名称的以 NULL 结尾的字符串的指针。这里的本地账户名称可以通过输入已知的字符串如 "Administrators" 。注:采用 domain_name\user_name 格式的完全限定字符串来确保 LookupAccountName 函数在所需域中查找帐户,但本文不谈及域内操作,只谈本地操作。

关于账户名称的获取,有多种方法,如 GetUserName 可以获得创建当前调用线程所在帐户名称的字符串,环境变量函数 GetEnvironmentVariable 通过设置 lpName 参数为"USERNAME"可以获得当前所在帐户名称的字符串;使用 Windows Terminal Session API 获取当前会话对应的账户名称字符串,等等。这里通过 WTSQuerySessionInformation 函数并指定相关参数设置以获取当前登录账户的名称:

WTSQuerySessionInformationW(
        WTS_CURRENT_SERVER_HANDLE, 
        WTS_CURRENT_SESSION, 
        WTS_INFO_CLASS::WTSUserName, 
        &userName, 
        &nameSize);

然后将得到的字符串传递给 LookupAccountName 函数,获取对应的 SID 。

随后,调用 SetNamedSecurityInfo 并设置 pObjectNameObjectTypeSecurityInfo psidOwner 参数即可修改目标对象的所有者。

1.2 修改访问控制对象 (ACE) 信息

本文以在原有DACL表上添加新的对象权限为例进行讲解。有关于覆盖、删除、复制的方法需要自行调试。

一种通用的更新方法就是先获取到原始的DACL表,然后将其与要添加的内容合并为一张新的表。最后将新的表更新到文件对应的表上。

整个过程我们需要这几个步骤:

Step1: 调用 GetNamedSecurityInfo 并设置 DACL_SECURITY_INFORMATION 类型,获取旧的DACL表;

Step2: 调用 BuildExplicitAccessWithName 用于构建一个 ACE,包含需要的权限;

Step3: 调用 SetEntriesInAcl 合并 ACE 到 旧的DACL,返回合并后的新的 DACL;

Step4: 调用 SetNamedSecurityInfo 绑定新的 DACL 到文件对象。

一个典型的示例代码如下,其中 Step2 也可以直接为结构体成员赋值:

DWORD AddAceToObjectsSecurityDescriptor(
    LPTSTR pszObjName,          // name of object
    SE_OBJECT_TYPE ObjectType,  // type of object
    LPWSTR pszTrustee,          // trustee for new ACE
    TRUSTEE_FORM TrusteeForm,   // format of trustee structure
    DWORD dwAccessRights,       // access mask for new ACE
    ACCESS_MODE AccessMode,     // type of ACE
    DWORD dwInheritance         // inheritance flags for new ACE
)
{
    DWORD dwRes = 0;
    PACL pOldDACL = NULL, pNewDACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea = {};

    if (NULL == pszObjName)
        return ERROR_INVALID_PARAMETER;
    printf("|*|:为用户 %ws 获取文件:%ws 的访问权限。\n", pszTrustee, pszObjName);
    // Get a pointer to the existing DACL.

    dwRes = GetNamedSecurityInfoW(pszObjName, ObjectType,
        DACL_SECURITY_INFORMATION,
        NULL, NULL, &pOldDACL, NULL, &pSD);
    if (ERROR_SUCCESS != dwRes) {
        printf("GetNamedSecurityInfo Error %u\n", dwRes);
        goto Cleanup;
    }

    // Initialize an EXPLICIT_ACCESS structure for the new ACE. 

    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    //ea.grfAccessPermissions = dwAccessRights;
    //ea.grfAccessMode = AccessMode;
    //ea.grfInheritance = dwInheritance;
    //ea.Trustee.TrusteeForm = TrusteeForm;
    //ea.Trustee.ptstrName = pszTrustee;
    // 生成指定用户帐户的访问控制信息(这里指定赋予全部的访问权限)

    BuildExplicitAccessWithNameW(&ea, pszTrustee, dwAccessRights, AccessMode, dwInheritance);
    // Create a new ACL that merges the new ACE
    // into the existing DACL.

    dwRes = SetEntriesInAclW(1, &ea, pOldDACL, &pNewDACL);
    if (ERROR_SUCCESS != dwRes) {
        printf("SetEntriesInAcl Error %u\n", dwRes);
        goto Cleanup;
    }

    // Attach the new ACL as the object's DACL.

    dwRes = SetNamedSecurityInfoW(pszObjName, ObjectType,
        DACL_SECURITY_INFORMATION,
        NULL, NULL, pNewDACL, NULL);
    if (ERROR_SUCCESS != dwRes) {
        printf("SetNamedSecurityInfo Error %u\n", dwRes);
        goto Cleanup;
    }
    else {
        printf("成功:已经为用户 %ws 获取文件:%ws 的访问权限。\n", pszTrustee, pszObjName);
        return dwRes;
    }

Cleanup:

    if (pSD != NULL)
        LocalFree((HLOCAL)pSD);
    if (pNewDACL != NULL)
        LocalFree((HLOCAL)pNewDACL);

    std::cout << "|*|:操作失败! " << std::endl;
    return -1;
}

通过以上方法即可对指定路径文件进行安全访问权限的修改。

二、完整编程代码

2.1 完整代码

下面是按照上文思路编写的简单实现代码,需要将编译好的程序在提升的命令行中执行,命令行参数为 TestFile.exe <文件路径> 。(编译环境:Visual Studio C++)

#include <iostream>
#include <stdio.h>
#include <aclapi.h>
#include <windows.h>
#include <tchar.h>
#include <stdlib.h>
#include <aclapi.h>
#include <wtsapi32.h>

#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "Wtsapi32.lib")

#define MAX_NAME 260

BOOL SetPrivilege(
    HANDLE hToken,          // access token handle
    LPCWSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
)
{
    TOKEN_PRIVILEGES tp;
    LUID luid;

    if (!LookupPrivilegeValueW(
        NULL,            // lookup privilege on local system
        lpszPrivilege,   // privilege to lookup 
        &luid))        // receives LUID of privilege
    {
        printf("LookupPrivilegeValue error: %u\n", GetLastError());
        return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.

    if (!AdjustTokenPrivileges(
        hToken,
        FALSE,
        &tp,
        sizeof(TOKEN_PRIVILEGES),
        (PTOKEN_PRIVILEGES)NULL,
        (PDWORD)NULL))
    {
        printf("AdjustTokenPrivileges error: %u\n", GetLastError());
        return FALSE;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)

    {
        printf("The token does not have the specified privilege. \n");
        return FALSE;
    }

    return TRUE;
}

BOOL SeTakeOwnershipToken()
{

    printf("|*|操作:获取相关权限。该特权可以修改目标文件的 Ownership。\n");
    HANDLE hToken;
    BOOL bRet = OpenProcessToken(
        GetCurrentProcess(),    // 进程句柄(当前进程)
        TOKEN_ALL_ACCESS,    // 全权访问令牌
        &hToken    // 返回的参数 进程令牌句柄 (就是AdjustTokenPrivileges的第一个参数)
    ); // 获取进程的令牌句柄
    if (bRet != TRUE) {
        printf("获取令牌句柄失败!\nPlease wait...\n");
        return FALSE;
    }
    // 提升权限
    BOOL set_SECURITY = SetPrivilege(hToken, SE_SECURITY_NAME, TRUE);
    if (!set_SECURITY || GetLastError() != ERROR_SUCCESS)
    {
        printf("提升SECURITY权限失败 Error: %u\n|*|:操作失败!\nPlease wait...\n", GetLastError());
        Sleep(5000);
        return FALSE;
    }
    // 提升获得所有者权限
    BOOL set_OWNER = SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE);
    if (!set_OWNER || GetLastError() != ERROR_SUCCESS)
    {
        printf("提升TAKE OWNERSHIP权限失败 Error: %u\n|*|:操作失败!\nPlease wait...\n", GetLastError());
        Sleep(5000);
        return FALSE;
    }
    printf("提升权限成功! \n");
    return TRUE;
}


BOOL ChangeTrusteeViaObjectsSecurity(
    LPTSTR pszObjName,          // name of object
    LPTSTR pszTrustee,          // trustee for new ACE
    SE_OBJECT_TYPE ObjectType,  // type of object. value :SE_FILE_OBJECT, /* 注册表为:SE_REGISTRY_KEY */
    SECURITY_INFORMATION  SecurityInfo  // Security Operational Information. value:OWNER_SECURITY_INFORMATION

)
{
    DWORD dwRes = 0;
    // LookupAccountName函数所需要的变量
    wchar_t* userName = nullptr;
    wchar_t sid[MAX_NAME]{ L'\0' };
    DWORD nameSize = 0;

    WTSQuerySessionInformationW(
        WTS_CURRENT_SERVER_HANDLE, 
        WTS_CURRENT_SESSION, 
        WTS_INFO_CLASS::WTSUserName, 
        &userName, 
        &nameSize);

    wchar_t userSID[MAX_NAME]{ L'\0' };
    wchar_t userDomain[MAX_NAME]{ L'\0' };
    DWORD sidSize = sizeof(userSID);
    DWORD signSidSize = sizeof(userSID);
    DWORD domainSize = sizeof(userDomain) / sizeof(WCHAR);


    SID_NAME_USE snu;
    dwRes = LookupAccountNameW(NULL,
        userName,
        userSID,
        &sidSize,
        userDomain,
        &domainSize,
        &snu);
    WTSFreeMemory(userName);
    //获取用户名SID
    if (ERROR_SUCCESS != dwRes)// 调用成功返回值为0
    {
        PSID_IDENTIFIER_AUTHORITY psia = GetSidIdentifierAuthority(userSID);
        signSidSize = swprintf_s(sid, sizeof(sid)/sizeof(wchar_t), L"S-%lu-", SID_REVISION);
        signSidSize = (signSidSize + swprintf_s(sid + wcslen(sid), sizeof(sid), L"%-lu", psia->Value[5]));


        int i = 0;
        int subAuthorities = *GetSidSubAuthorityCount(userSID);


        for (i = 0; i < subAuthorities; i++)
        {
            signSidSize += swprintf_s(sid + signSidSize, sizeof(sid), L"-%lu", *GetSidSubAuthority(userSID, i));
        }
        printf("Account SID: %ws\n", sid);
        // 更改所有者
        if (!SetNamedSecurityInfoW
        (pszObjName,
            ObjectType, /* 注册表为:SE_REGISTRY_KEY */
            SecurityInfo, /* 更改所有者 */
            &userSID, /* 需要更改所有者的SID */
            NULL, NULL, NULL))
        {
            printf("成功更改所有者! \n");
            return TRUE;
        }
        else {
            printf("Security Info:OWNER_SECURITY_INFORMATION.\nSetNamedSecurityInfo Error %u\nPlease wait...\n", dwRes);
            Sleep(5000);
        }
    }
    else {
        printf("LookupAccountName Error %u\nPlease wait...\n", dwRes);
        Sleep(5000);
    }
    return FALSE;
}


DWORD AddAceToObjectsSecurityDescriptor(
    LPTSTR pszObjName,          // name of object
    SE_OBJECT_TYPE ObjectType,  // type of object
    LPWSTR pszTrustee,          // trustee for new ACE
    TRUSTEE_FORM TrusteeForm,   // format of trustee structure
    DWORD dwAccessRights,       // access mask for new ACE
    ACCESS_MODE AccessMode,     // type of ACE
    DWORD dwInheritance         // inheritance flags for new ACE
)
{
    DWORD dwRes = 0;
    PACL pOldDACL = NULL, pNewDACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea = {};

    if (NULL == pszObjName)
        return ERROR_INVALID_PARAMETER;
    printf("|*|:为用户 %ws 获取文件:%ws 的访问权限。\n", pszTrustee, pszObjName);
    // Get a pointer to the existing DACL.

    dwRes = GetNamedSecurityInfoW(pszObjName, ObjectType,
        DACL_SECURITY_INFORMATION,
        NULL, NULL, &pOldDACL, NULL, &pSD);
    if (ERROR_SUCCESS != dwRes) {
        printf("GetNamedSecurityInfo Error %u\n", dwRes);
        goto Cleanup;
    }

    // Initialize an EXPLICIT_ACCESS structure for the new ACE. 

    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    //ea.grfAccessPermissions = dwAccessRights;
    //ea.grfAccessMode = AccessMode;
    //ea.grfInheritance = dwInheritance;
    //ea.Trustee.TrusteeForm = TrusteeForm;
    //ea.Trustee.ptstrName = pszTrustee;
    // 生成指定用户帐户的访问控制信息(这里指定赋予全部的访问权限)

    BuildExplicitAccessWithNameW(&ea, pszTrustee, dwAccessRights, AccessMode, dwInheritance);
    // Create a new ACL that merges the new ACE
    // into the existing DACL.

    dwRes = SetEntriesInAclW(1, &ea, pOldDACL, &pNewDACL);
    if (ERROR_SUCCESS != dwRes) {
        printf("SetEntriesInAcl Error %u\n", dwRes);
        goto Cleanup;
    }

    // Attach the new ACL as the object's DACL.

    dwRes = SetNamedSecurityInfoW(pszObjName, ObjectType,
        DACL_SECURITY_INFORMATION,
        NULL, NULL, pNewDACL, NULL);
    if (ERROR_SUCCESS != dwRes) {
        printf("SetNamedSecurityInfo Error %u\n", dwRes);
        goto Cleanup;
    }
    else {
        printf("成功:已经为用户 %ws 获取文件:%ws 的访问权限。\n", pszTrustee, pszObjName);
        return dwRes;
    }

Cleanup:

    if (pSD != NULL)
        LocalFree((HLOCAL)pSD);
    if (pNewDACL != NULL)
        LocalFree((HLOCAL)pNewDACL);

    std::cout << "|*|:操作失败! " << std::endl;
    return -1;
}



int wmain(int argc, wchar_t* argv[])
{
    setlocale(LC_CTYPE, "CHS");//让wprintf()支持中文
    if (argc != 2)
    {
        std::cout << "Invalid Parameters!" << std::endl;
        return 0;
    }

    wchar_t* path = argv[1];
    wchar_t* pszObjName = path;

    // 获取当前用户名
    wchar_t* currentUser = nullptr;
    DWORD dwSize_currentUser = 0;

    WTSQuerySessionInformationW(
        WTS_CURRENT_SERVER_HANDLE, 
        WTS_CURRENT_SESSION,
        WTS_INFO_CLASS::WTSUserName,
        &currentUser,
        &dwSize_currentUser);

    if (!SeTakeOwnershipToken()) {
        std::cout << "|*|:在未获得SE_TAKE_OWNERSHIP_NAME特权时,继续更改文件所有者可能失败! " << std::endl;
    }

    // 更改ACL下的安全主体,以获得ACE控制权
    if (ChangeTrusteeViaObjectsSecurity(pszObjName,
        currentUser, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION))
    {
        // 覆盖ACL以获得完全控制的访问权限
        if (AddAceToObjectsSecurityDescriptor(pszObjName,
            SE_FILE_OBJECT,
            currentUser,
            TRUSTEE_IS_OBJECTS_AND_SID,
            GENERIC_ALL,
            GRANT_ACCESS,
            SUB_CONTAINERS_AND_OBJECTS_INHERIT) == -1)
        {
            std::cout << "ACE操作已执行。" << std::endl;
        }
    }
    else {
        std::cout << "无法更改ACL下的安全主体,继续更改ACE控制权可能会失败。" << std::endl;
        // 覆盖ACL以获得完全控制的访问权限
        if (AddAceToObjectsSecurityDescriptor(pszObjName,
            SE_FILE_OBJECT,
            currentUser,
            TRUSTEE_IS_OBJECTS_AND_SID,
            GENERIC_ALL,
            GRANT_ACCESS,
            SUB_CONTAINERS_AND_OBJECTS_INHERIT) == -1)
        {
            std::cout << "ACE操作已执行。" << std::endl;
        }

    }
    std::cout << "所有操作已完成。" << std::endl;
    system("pause");

    return 0;
}

2.2 调试效果

下图是在提升的命令提示符中执行的效果:

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具
程序执行过程

从图中可见程序执行完毕,并且没有错误。

下图展示的是程序执行完毕后,目标对象的属性变化:

windows 目录权限,C++学习笔记,Windows 基础编程,windows,c++,测试工具
目标被修改后的安全属性

从图中可以看出目标对象的所有者发生变化,且为当前登陆账户添加了完全控制权限。

三、利用Windows工具实现修改安全控制对象权限

3.1 通过 ICacls 命令实现修改访问控制权限

      icacls

      Intergrity Control Access Control List: 完整性权限控制列表
      Windows系统下控制文件及文件夹的访问权限的命令行指令,相当于Linux中的chmod
原命令cacls已经被废弃。

      这一篇博客园作者整理的命令详细信息比较全面清晰:Cacls和ICacls - 傩舞 - 博客园 (cnblogs.com)

3.2 通过 powershell / 注册表 实现修改访问控制权限

就不详细列出了,这里给出一篇知乎,整理的也比较全面:渗透技巧——Windows下的Access Control List - 知乎


本文为原创文章,转载请注明出处。(修改于:2023/9/19)

本人博客:涟幽516-CSDN博客涟幽516擅长C++学习笔记,Win10动态壁纸开发,Windows上的编程,等方面的知识,涟幽516关注python,c++,c语言,系统安全领域.https://blog.csdn.net/qq_59075481文章来源地址https://www.toymoban.com/news/detail-754118.html

到了这里,关于修改 Windows 文件访问权限的多种方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux - samba实现Linux与windows文件共享——共享文件夹目标文件访问权限被拒绝解决方案(超详细,看不懂你怪我)

            最近做一个项目,需要用到linux上的内容,于是需要将linux与window共享文件,上网查阅了一些资料,做完了之后,总结一下自己遇到的问题,以及自己是咋解决的,供大家参考。 这里其实只需要一步就可以操作出来,现在我们看一下: 一、打开虚拟机,选择设置

    2024年02月04日
    浏览(66)
  • Linux中如何修改文件或目录的权限?

    ​ 在Linux系统中,文件权限是非常重要的一个概念,它能够决定谁可以访问文件,以及可以执行哪些操作,正确地设置文件权限可以确保系统的安全性和稳定性,那么如何设置文件权限呢?以下是详细的内容: 在 Linux 系统中,可以使用 `chmod` 命令来修改文件或目录的权限。

    2024年02月07日
    浏览(52)
  • 【ubuntu】修改文件夹(目录)及其内部文件的权限

    目录 修改文件夹(目录)及其内部文件的权限 在 Ubuntu 中,你可以使用 chmod 命令来修改文件夹(目录)及其内部文件的权限。下面是一个将文件夹及其内部所有文件的权限都修改为相同权限的示例命令: 其中, permission 是权限设置,表示所需的权限,例如 755 或 777 , fold

    2024年02月03日
    浏览(49)
  • UOS共享文件夹给windows系统访问的方法

    1、前提条件:UOS主机和windows主机处于同一个局域网内 2、在UOS主机中选择需要共享的文件夹点击右键,把共享文件夹勾选上,可以允许匿名访问(即不需要输入任何账号密码),选择完成后退出。 3、在UOS系统上右键点击打开终端,输入ifconfig,查看当前UOS系统的IP地址。 4、

    2024年02月14日
    浏览(208)
  • Linux Tip 03 文件类型属性、权限管理、拓展名、主要目录介绍、文件的相关操作、文件内容查看、文件的修改、文件和目录的权限、文件的查找

    一、用户的存储 在Linux系统中 系统上所有的账号和一般身份的用户以及root的相关信息都存在/etc/passwd这个文件中 个人的密码记录在/etc/shadow中 所有的组名都记录在/etc/group中 二、文件类型和属性 三、文件和目录的权限管理 四、文件的类型 五、文件的拓展名 文件长度的限制

    2023年04月10日
    浏览(65)
  • windows 环境修改 Docker 存储目录

    windows 环境修改存储目录 docker 安装时不提供指定安装路径和数据存储路径的选项,且默认是安装在C盘的。C盘比较小的,等docker运行久了,一大堆的东西放在上面容易导致磁盘爆掉。所以安装前可以做些准备,让安装的实际路径不在C盘,当然安装好的的,也可以卸载了重新来

    2024年02月16日
    浏览(38)
  • 头歌--第1关:Linux文件权限修改(Linux文件/目录高级管理一)

    任务描述 假设系统中存在一个文件 File ,修改该文件的权限,根据实际需求添加/删除该文件读、写、执行权限,通过本关的学习,我们学会如何让一个文件允许哪些用户访问或禁止哪些用户访问。 本关任务:学会如何修改文件的权限。 相关知识 Linux 系统中的每个文件都有

    2024年02月05日
    浏览(124)
  • windows10/11 修改docker镜像存储目录

    windows10/11 修改docker镜像存储目录 docker默认pull的镜像在c盘,随着镜像的增加,C 盘很快就满了,直接影响不少程序的正常使用,使用下面的操作可以将镜像路径移动到其他位置 查看docker的状态 确保docker为关闭状态,如果state下为running时,直接退出docker 关闭所有正在运行的实例

    2024年02月13日
    浏览(47)
  • windows 访问SAMBA提示没有权限

    1 检查配置文件 /etc/samba/smb.conf 是否有问题 2 开放共享目录权限 3 确保linux下防火墙关闭 4 确保setlinux关闭 临时关闭 彻底禁用 在 /etc/sysconfig/selinux 或者 /etc/grub.conf 中添加

    2024年02月02日
    浏览(33)
  • 【Windows】你不能访问此共享文件夹,因为你的组织安全策略...解决方法

     Win+R键打开运行窗口,输入gpedit.msc进入本地组策略编辑器。 找到计算机配置,然后点击管理模板,找到网络,然后点击lanman工作站,将右侧窗口中的启用不安全的来吧登录开启就解决了 设置为已启用,应用后确定,就可以正常访问了 然后我们继续访问共享文件夹,发现就

    2024年02月01日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包