如何在不拒绝在 C++ 中读取或执行访问文件的情况下保护文件

How to protect an file without denying read or execute access to it in c++

我正在制作一个计算机管理程序(当然 运行 只能作为管理员使用)普通用户不应访问(只能由 SYSTEM 用户访问,因为我的卸载程序将 运行 作为该用户)。

我一直在努力防止普通用户修改和删除我的主 EXE 文件,它起作用了。

问题是我希望用户能够执行它并阅读它,但它不会让他们 read/execute 文件。

这是我的代码:

#include <windows.h>
#include <stdio.h>
#include <accctrl.h>
#include <aclapi.h>
#include <iostream>
#include <cstdio>
                                                                                            
#pragma comment(lib, "ntdll.lib")

extern "C" NTSTATUS NTAPI RtlAdjustPrivilege(ULONG Privilege, BOOLEAN Enable, BOOLEAN CurrThread, PBOOLEAN StatusPointer);

BOOL ProtectFile(LPTSTR lpszOwnFile) 
{
    BOOL bRetval = FALSE;

    HANDLE hToken = NULL; 
    PSID pSIDAdmin = NULL;
    PSID pSIDEveryone = NULL;
    PACL pACL = NULL;
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
    const int NUM_ACES = 2;
    EXPLICIT_ACCESS ea[NUM_ACES];
    DWORD dwRes;

    // Specify the DACL to use.
    // Create a SID for the Everyone group.
    if (!AllocateAndInitializeSid(&SIDAuthWorld, 1,
                     SECURITY_WORLD_RID,
                     0,
                     0, 0, 0, 0, 0, 0,
                     &pSIDEveryone)) 
    {
        printf("AllocateAndInitializeSid (Everyone) error %u\n",
                GetLastError());
    }

    // Create a SID for the BUILTIN\Administrators group.
    if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
                     SECURITY_BUILTIN_DOMAIN_RID,
                     DOMAIN_ALIAS_RID_ADMINS,
                     0, 0, 0, 0, 0, 0,
                     &pSIDAdmin)) 
    {
        printf("AllocateAndInitializeSid (Admin) error %u\n",
                GetLastError());
    }

    ZeroMemory(&ea, NUM_ACES * sizeof(EXPLICIT_ACCESS));

    // Set read and execute access for Everyone.
    ea[0].grfAccessPermissions = GENERIC_WRITE| GENERIC_EXECUTE | FILE_GENERIC_READ | STANDARD_RIGHTS_READ | STANDARD_RIGHTS_EXECUTE | READ_CONTROL | FILE_EXECUTE| FILE_READ_EA | FILE_CREATE_PIPE_INSTANCE;
    ea[0].grfAccessMode = SET_ACCESS;
    ea[0].grfInheritance = NO_INHERITANCE;
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea[0].Trustee.ptstrName = (LPTSTR) pSIDEveryone;

    // Set read and execute access for Administrators.
    ea[1].grfAccessPermissions = GENERIC_READ| GENERIC_EXECUTE | FILE_GENERIC_READ | STANDARD_RIGHTS_READ | STANDARD_RIGHTS_EXECUTE | READ_CONTROL | FILE_EXECUTE| FILE_READ_EA | FILE_CREATE_PIPE_INSTANCE ;
    ea[1].grfAccessMode = SET_ACCESS;
    ea[1].grfInheritance = NO_INHERITANCE;
    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[1].Trustee.ptstrName = (LPTSTR) pSIDAdmin;

    // Deny modify and delete access for Everyone.
    ea[0].grfAccessPermissions = GENERIC_WRITE| FILE_GENERIC_WRITE | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA |  WRITE_OWNER | DELETE | WRITE_DAC;
    ea[0].grfAccessMode = DENY_ACCESS;
    ea[0].grfInheritance = NO_INHERITANCE;
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea[0].Trustee.ptstrName = (LPTSTR) pSIDEveryone;

    // Deny modify and delete access for Administrators.
    ea[1].grfAccessPermissions = GENERIC_WRITE| FILE_GENERIC_WRITE | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA |  WRITE_OWNER | DELETE | WRITE_DAC;
    ea[1].grfAccessMode = DENY_ACCESS;
    ea[1].grfInheritance = NO_INHERITANCE;
    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[1].Trustee.ptstrName = (LPTSTR) pSIDAdmin;

    if (ERROR_SUCCESS != SetEntriesInAcl(NUM_ACES,
                                         ea,
                                         NULL,
                                         &pACL))
    {
        printf("Failed SetEntriesInAcl\n");
    }

    // Try to modify the object's DACL.
    dwRes = SetNamedSecurityInfo(
        lpszOwnFile,                 // name of the object
        SE_FILE_OBJECT,              // type of object
        DACL_SECURITY_INFORMATION,   // change only the object's DACL
        NULL, NULL,                  // do not change owner or group
        pACL,                        // DACL specified
        NULL);                       // do not change SACL

    if (ERROR_SUCCESS == dwRes) 
    {
        printf("Successfully changed DACL\n");
        bRetval = TRUE;
        // No more processing needed.
    }

    if (dwRes != ERROR_ACCESS_DENIED)
    {
        printf("First SetNamedSecurityInfo call failed: %u\n",
                dwRes); 
    }

    // If the preceding call failed because access was denied, 
    // enable the SE_TAKE_OWNERSHIP_NAME privilege, create a SID for 
    // the Administrators group, take ownership of the object, and 
    // disable the privilege. Then try again to set the object's DACL.

    // Open a handle to the access token for the calling process.
    if (!OpenProcessToken(GetCurrentProcess(), 
                          TOKEN_ADJUST_PRIVILEGES, 
                          &hToken)) 
    {
        printf("OpenProcessToken failed: %u\n", GetLastError()); 
    } 

    //get the take ownership privilege

    BOOLEAN PrivilegeState = FALSE;
    RtlAdjustPrivilege(9, TRUE, FALSE, &PrivilegeState);

    // Set the owner in the object's security descriptor.
    dwRes = SetNamedSecurityInfo(
        lpszOwnFile,                 // name of the object
        SE_FILE_OBJECT,              // type of object
        OWNER_SECURITY_INFORMATION,  // change only the object's owner
        pSIDAdmin,                   // SID of Administrator group
        NULL,
        NULL,
        NULL); 

    if (dwRes != ERROR_SUCCESS) 
    {
        printf("Could not set owner. Error: %u\n", dwRes); 
    }

    // Try again to modify the object's DACL,
    // now that we are the owner.
    dwRes = SetNamedSecurityInfo(
        lpszOwnFile,                 // name of the object
        SE_FILE_OBJECT,              // type of object
        DACL_SECURITY_INFORMATION,   // change only the object's DACL
        NULL, NULL,                  // do not change owner or group
        pACL,                        // DACL specified
        NULL);                       // do not change SACL

    if (dwRes == ERROR_SUCCESS)
    {
        printf("Successfully changed DACL\n");
        bRetval = TRUE; 
    }
    else
    {
        printf("Second SetNamedSecurityInfo call failed: %u\n",
                dwRes); 
    }

    if (pSIDAdmin)
        FreeSid(pSIDAdmin); 

    if (pSIDEveryone)
        FreeSid(pSIDEveryone); 

    if (pACL)
       LocalFree(pACL);

    if (hToken)
       CloseHandle(hToken);

    return bRetval;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    ProtectFile("C:\Windows\program.exe");
}

现在,它正确设置了 delete/modify 被拒绝的访问权限,正如您在此处看到的:

但是,当我尝试执行同一个文件时,正如您在此处看到的那样,出于某种原因,它不起作用。

我不确定为什么会这样,但我认为这是因为我忘记在允许的部分中设置一个或多个访问权限,或者 read/execute文件在被拒绝的部分。

顺便说一句,这里是 allow/deny 权限部分的图片:

拒绝权限部分:

允许的权限部分:

您是否知道我忘记或设置错误的权限?如果是,它们是什么?

您是拒绝还是允许读取权限? 怎么样?

如果你拒绝读取权限,怎么可能运行?

停止拒绝读取权限。

以下是一些可以帮助您的信息:How Permissions Work