c++ - 如何在不拒绝 C++ 中的读取或执行访问的情况下保护文件
问题描述
我正在制作一个计算机管理程序(当然只能以管理员身份运行),普通用户(只能由SYSTEM
用户访问,因为我的卸载程序将以该用户身份运行)。
我一直在试图阻止普通用户修改和删除我的主 EXE 文件,并且它有效。
问题是我希望用户能够执行并读取它,但它不会让他们读取/执行文件。
这是我的代码:
#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");
}
现在,它正确设置了删除/修改拒绝访问权限,如您在此处看到的:
但是,当我尝试执行同一个文件时,正如您在此处看到的,由于某种原因,它不起作用。
我不确定为什么会发生这种情况,但我认为这是因为我忘记在允许部分放置一个或多个访问权限,或者读取/执行文件所需的一些访问权限在拒绝部分中。
顺便说一句,这是允许/拒绝权限部分的图片:
拒绝权限部分:
允许的权限部分:
您对我忘记的权限或我设置错误的权限有任何想法吗?如果是,它们是什么?
解决方案
推荐阅读
- java - 您如何向 Cisco Contact Center Express Identity Service 进行身份验证?
- ruby-on-rails - 带有文件的rails http请求
- android - MPAndroidChart:HorizontalBarChart 仅在第一次显示时跑出屏幕
- swift - swift 是否包含类似线程的东西?
- android - 如何将设备连接到我的 Android firebase 数据库
- python - 将列值分组在一起
- angularjs - 将 AngularJS 应用程序迁移到 Angular 很难吗?
- javascript - event.item.valueField 显示未定义
- reactjs - 从反应中的对象数组中获取第一个对象
- sql - 在复杂的查询 SQL Server/Argos 中获取“0”计数