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

  access-rights, c++, rights

I’m making an computer management program (that runs only as admin of course) that shouldn’t be accessible to normal users (only by the SYSTEM user because my uninstaller will run as this user) I have been trying to prevent normal users to modify and delete my main exe file in C++, and it worked. The problem here is that I want the user to be able to execute it and read it, but it wont let them read/execute the file. Here is my code:

#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 %un",
            GetLastError());
    
}

// Create a SID for the BUILTINAdministrators group.
if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
                 SECURITY_BUILTIN_DOMAIN_RID,
                 DOMAIN_ALIAS_RID_ADMINS,
                 0, 0, 0, 0, 0, 0,
                 &pSIDAdmin)) 
{
    printf("AllocateAndInitializeSid (Admin) error %un",
            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 SetEntriesInAcln");
    
}

// 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 DACLn");
    bRetval = TRUE;
    // No more processing needed.
   
}
if (dwRes != ERROR_ACCESS_DENIED)
{
    printf("First SetNamedSecurityInfo call failed: %un",
            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: %un", 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: %un", 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 DACLn");
    bRetval = TRUE; 
}
else
{
    printf("Second SetNamedSecurityInfo call failed: %un",
            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:Windowsprogram.exe");
  }

Now it sets correctly the delete/modify denied access permissions as you can see
right here
But when I try to execute the same file as you can see here, it doesn’t work for some reason.

I’m not sure why it happens, but I think it is because I forgot to put one or multiple access right(s) in the allowed section or that some access rights needed to read/execute the file are in the denied section.

Btw, here are the pictures of both allow/deny permissions section

denied permissions section

allowed permissions section

Do You have any idea of the permissions I forgot or that i setted wrong and if yes, what are they?

Source: Windows Questions C++

LEAVE A COMMENT