1

我正在尝试使用 Windows 权限 API 修改权限。我有一个独立的用例代码,如下所示,我首先撤销所有访问权限,然后授予读写权限。

#include <fstream>
#include <iostream>
#include <aclapi.h>
#include <windows.h>
#include <string>
using namespace std;
#include <memory>


bool CanAccessFolder(LPCTSTR folderName, DWORD genericAccessRights,DWORD& grantedRights)
{
    bool bRet = false;
    DWORD length = 0;
    if (!::GetFileSecurity(folderName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
        | DACL_SECURITY_INFORMATION, NULL, NULL, &length) &&
        ERROR_INSUFFICIENT_BUFFER == ::GetLastError()) {
        PSECURITY_DESCRIPTOR security = static_cast< PSECURITY_DESCRIPTOR >(::malloc(length));
        if (security && ::GetFileSecurity(folderName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
            | DACL_SECURITY_INFORMATION, security, length, &length)) {
            HANDLE hToken = NULL;
            if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_IMPERSONATE | TOKEN_QUERY |
                TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &hToken)) {
                HANDLE hImpersonatedToken = NULL;
                if (::DuplicateToken(hToken, SecurityImpersonation, &hImpersonatedToken)) {
                    GENERIC_MAPPING mapping = { 0xFFFFFFFF };
                    PRIVILEGE_SET privileges = { 0 };
                    DWORD grantedAccess = 0, privilegesLength = sizeof(privileges);
                    BOOL result = FALSE;

                    mapping.GenericRead = FILE_GENERIC_READ;
                    mapping.GenericWrite = FILE_GENERIC_WRITE;
                    mapping.GenericExecute = FILE_GENERIC_EXECUTE;
                    mapping.GenericAll = FILE_ALL_ACCESS;

                    ::MapGenericMask(&genericAccessRights, &mapping);
                    if (::AccessCheck(security, hImpersonatedToken, genericAccessRights,
                        &mapping, &privileges, &privilegesLength, &grantedAccess, &result)) 
                    {
                        bRet = (result == TRUE);
                        grantedRights = grantedAccess;
                    }
                    ::CloseHandle(hImpersonatedToken);
                }
                ::CloseHandle(hToken);
            }
            ::free(security);
        }
    }

    return bRet;
}
 void printMasks(DWORD Mask)
 {
     // This evaluation of the ACCESS_MASK is an example.
     // Applications should evaluate the ACCESS_MASK as necessary.
    std::wcout << "Effective Allowed Access Mask :  "<< Mask << std::hex << std::endl;
     if (((Mask & GENERIC_ALL) == GENERIC_ALL)
         || ((Mask & FILE_ALL_ACCESS) == FILE_ALL_ACCESS))
     {
         wprintf_s(L"Full Control\n");
         //return;
     }
     if (((Mask & GENERIC_READ) == GENERIC_READ)
         || ((Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ))
         wprintf_s(L"Read\n");
     if (((Mask & GENERIC_WRITE) == GENERIC_WRITE)
         || ((Mask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE))
         wprintf_s(L"Write\n");
     if (((Mask & GENERIC_EXECUTE) == GENERIC_EXECUTE)
         || ((Mask & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE))
         wprintf_s(L"Execute\n");
 }

 DWORD AddAceToObjectsSecurityDescriptor(
     LPTSTR pszObjName,          // name of object
     SE_OBJECT_TYPE ObjectType,  // type of object     
     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;

     // Get a pointer to the existing 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;
     }


     // 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 = TRUSTEE_IS_NAME;
     ea.Trustee.ptstrName = L"CURRENT_USER";
     ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
     // Create a new ACL that merges the new ACE
     // into the existing DACL.

     dwRes = SetEntriesInAcl(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 = 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()
 {
     DWORD access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | FILE_ALL_ACCESS;
     DWORD grant = 0;

     std::cout << "Before modification \n";

     bool b = CanAccessFolder(L"C:\\Deny\\file.txt", access_mask, grant);

     printMasks(grant);

     std::cout << "After removing access \n";

     DWORD dwres = AddAceToObjectsSecurityDescriptor(
         L"C:\\Deny\\file.txt",
         SE_FILE_OBJECT,
         FILE_ALL_ACCESS,
         DENY_ACCESS,
         NO_INHERITANCE);

     if (dwres == ERROR_SUCCESS)
     {
         grant = 0;
         bool b = CanAccessFolder(L"C:\\Deny\\file.txt", access_mask, grant);
         printMasks(grant);
     }
     else
     {
         std::cout << "Error   :   " << GetLastError() << '\n';
     }
     HANDLE hFile = CreateFileW(L"C:\\Deny\\file.txt",               // file name 
         GENERIC_READ,          // open for reading 
         0,                     // do not share 
         NULL,                  // default security 
         OPEN_EXISTING,         // existing file only 
         FILE_ATTRIBUTE_NORMAL, // normal file 
         NULL);                 // no template 
     if (hFile == INVALID_HANDLE_VALUE)
     {
         std::cout << "CreateFileW1 Error  :  " << GetLastError() << '\n';
     }

 // ?????????????????????? GRANT ACCESS ?????????????????????????????????

     std::cout << "After granting access \n";
     DWORD dwres1 = AddAceToObjectsSecurityDescriptor(
         L"C:\\Deny\\file.txt",
         SE_FILE_OBJECT,
         FILE_GENERIC_READ | FILE_GENERIC_WRITE,
         GRANT_ACCESS,
         NO_INHERITANCE);

     if (dwres1 == ERROR_SUCCESS)
     {
         grant = 0;
         bool b = CanAccessFolder(L"C:\\Deny\\file.txt", access_mask, grant);
         printMasks(grant);
     }
     else
     {
         std::cout << "Error   :   " << GetLastError() << '\n';
     }
     HANDLE hFile1 = CreateFileW(L"C:\\Deny\\file.txt",               // file name 
         GENERIC_READ,          // open for reading 
         0,                     // do not share 
         NULL,                  // default security 
         OPEN_EXISTING,         // existing file only 
         FILE_ATTRIBUTE_NORMAL, // normal file 
         NULL);                 // no template 
     if (hFile1 == INVALID_HANDLE_VALUE)
     {
         std::cout << "CreateFileW2 Error  :  " << GetLastError() << '\n';
     }

     return 0;
 }

我得到此代码的输出如下

Before modification
Effective Allowed Access Mask :  2032127
Full Control
Read
Write
Execute
After removing access
Effective Allowed Access Mask :  0
CreateFileW1 Error  :  5
After granting access
Effective Allowed Access Mask :  0

授予权限后,我可以访问文件“file.txt”,我可以打开它/写入它(例如 CreateFileW 通行证)

我不明白的是权限位背后的奥秘,0即使我已将权限授予FILE_GENERIC_READ | FILE_GENERIC_WRITE受托人CURRENT_USER,它也会显示出来。

我还使用检查了 DAC 列表icacls,它给了我以下输出

C:\>icacls C:\Deny\file.txt
C:\Deny\file.txt DOMAIN\user:(DENY)(D,WDAC,WO,X,DC)
                 DOMAIN\user:(R,W)
                 NT AUTHORITY\Authenticated Users:(I)(F)
                 DOMAIN\user:(I)(F)
                 BUILTIN\Users:(I)(F)
                 BUILTIN\Administrators:(I)(F)
                 NT AUTHORITY\SYSTEM:(I)(F)

这告诉我,我的GRANT权限 ACE 被推到了权限之下DENY,这是一个有据可查的行为

这就是我将标志值设为 的原因0吗?

有什么方法/API/函数可以让我得到正确的标志,即可以告诉我FILE_GENERIC_READFILE_GENERIC_WRITE设置?

4

0 回答 0