SetNamedSecurityInfo()函数,即使应用程序以管理员身份运行,也返回ACCESS_IS_DENIED(Winerror.h中的错误代码5)。

问题描述 投票:0回答:1
我有一个应用程序,最好将它安装的服务设置为不能由用户编辑和中断(如以下安装的服务之一的屏幕截图所示,并且我实现了以下内容的变体实现此目的的逻辑:

    读取Windows服务的安全描述符,该文件不允许用户编辑和终止它(如下面的屏幕快照所示,在该屏幕快照中,相关服务的服务属性甚至不允许用户终止它,确保它永久运行,并且仅在最终删除后才终止)。
  1. 将先前读取的安全描述符设置为应用程序安装的服务,以显示相同的功能。
  2. 这是真正的问题:即使SetNamedSecurityInfo()返回的值与ACCESS_IS_DENIEDWinerror.h相对应,代码也会返回错误值5,即使该二进制文件是作为管理员运行的。最后,让我更加迷失的部分是,当我尝试使用其他已安装服务的服务名称或使用自定义字符串安全描述符(调用ConvertStringSecurityDescriptorToSecurityDescriptor()函数时)时,由于操作需要。在更进一步的调查中,我发现仅在使用实现所需行为的服务名称时才可重现此错误:不允许最终用户编辑启动类型以及服务的服务状态。

用于执行上述任务的代码:

// Fetch the security descriptor for "WdNisSvc" (Service name that corresponds to the display name of "Windows Security Service") LPCWSTR serviceNameToGetSecurityInformationFrom = L"WdNisSvc"; SC_HANDLE serviceManagerHandle = NULL, serviceHandle = NULL; char securityDescriptorBuffer[1024]; DWORD lengthOfReturnedValue = 0; LPWSTR stringBuffer = NULL; unsigned long lengthOfString = 0; PSECURITY_DESCRIPTOR securityDescriptor = { 0 }; LPSTR daclBuffer = nullptr, ownerSidBuffer = nullptr, absoluteSecurityDescriptionBuffer = nullptr; DWORD daclBufferSize = NULL, ownerSidBufferSize = NULL, absoluteSecurityDescriptionBufferSize = NULL, saclBufferSize = NULL, primaryGroupSidBufferSize = NULL; WCHAR serviceName[] = L"test_service"; DWORD securityInfoChangeOperationErrorValue = NULL; BOOL securityDescriptorInAbsoluteFormatCreationErrorValue = NULL; serviceManagerHandle = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); if (serviceManagerHandle == nullptr) { cout << "Error opening Service Manager Handle (" << GetLastError() << ").\n"; } else { serviceHandle = OpenService(serviceManagerHandle, serviceNameToGetSecurityInformationFrom, READ_CONTROL); //| WRITE_OWNER | WRITE_DAC if (serviceHandle == nullptr) { cout << "Error opening service (" << GetLastError() << ").\n"; } else { if (!QueryServiceObjectSecurity(serviceHandle, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, securityDescriptorBuffer, sizeof(securityDescriptorBuffer), &lengthOfReturnedValue)) { cout << "Error obtaining service's security information (" << GetLastError() << ").\n"; } else { if (!ConvertSecurityDescriptorToStringSecurityDescriptor(securityDescriptorBuffer, SDDL_REVISION_1, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, &stringBuffer, &lengthOfString)) { cout << "Error getting string value corresponding to the security information (" << GetLastError() << ")"; } else { if (!ConvertStringSecurityDescriptorToSecurityDescriptor(stringBuffer, SDDL_REVISION_1, &securityDescriptor, NULL)) { cout << "Conversion of string descriptor to security descriptor failed with error " << GetLastError() << ".\n"; } else { absoluteSecurityDescriptionBuffer = new CHAR[0]; ownerSidBuffer = new CHAR[0]; daclBuffer = new CHAR[0]; securityDescriptorInAbsoluteFormatCreationErrorValue = MakeAbsoluteSD(securityDescriptor, absoluteSecurityDescriptionBuffer, &absoluteSecurityDescriptionBufferSize, (PACL)daclBuffer, &daclBufferSize, NULL, &saclBufferSize, ownerSidBuffer, &ownerSidBufferSize, NULL, &primaryGroupSidBufferSize); if ((!securityDescriptorInAbsoluteFormatCreationErrorValue) && (ERROR_INSUFFICIENT_BUFFER) == GetLastError()) { // Induced error //cout << "ERROR: Inadequate size of the buffers implemented.\n"; delete[] absoluteSecurityDescriptionBuffer; delete[] ownerSidBuffer; delete[] daclBuffer; absoluteSecurityDescriptionBuffer = new CHAR[absoluteSecurityDescriptionBufferSize]; ownerSidBuffer = new CHAR[ownerSidBufferSize]; daclBuffer = new CHAR[daclBufferSize]; securityDescriptorInAbsoluteFormatCreationErrorValue = MakeAbsoluteSD(securityDescriptor, absoluteSecurityDescriptionBuffer, &absoluteSecurityDescriptionBufferSize, (PACL)daclBuffer, &daclBufferSize, NULL, &saclBufferSize, ownerSidBuffer, &ownerSidBufferSize, NULL, &primaryGroupSidBufferSize); } securityInfoChangeOperationErrorValue = SetNamedSecurityInfo(serviceName, SE_SERVICE, OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, ownerSidBuffer, NULL, (ACL*)daclBuffer, NULL); if (securityInfoChangeOperationErrorValue != ERROR_SUCCESS) { cout << "Error setting security info (" << securityInfoChangeOperationErrorValue << ").\n"; } delete[] absoluteSecurityDescriptionBuffer; delete[] ownerSidBuffer; delete[] daclBuffer; } } } } }

显示所需行为的已安装Windows服务之一的屏幕快照:Screenshot of the properties box of "Windows Security Service"

提前感谢。

我有一个应用程序,最好将它安装的服务设置为不能被用户编辑和中断(如下面安装的服务之一的屏幕快照所示……)>

c++ windows winapi visual-c++ service
1个回答
0
投票
要设置OWNER_SECURITY_INFORMATION,调用进程必须具有WRITE_OWNER访问权限,或者必须是对象的所有者,或者必须启用SE_TAKE_OWNERSHIP_NAME特权,或者在您将非self SID设置为对象的所有者时启用SE_RESTORE_NAME。而且,您不需要设置对象所有者的SID。以下示例对我有用:

#include <windows.h> #include <iostream> #include <sddl.h> #include <aclapi.h> #include <WinError.h> #pragma comment(lib, "Advapi32.lib") using namespace std; int main(int argc, char* argv[]) { // Fetch the security descriptor for "WdNisSvc" (Service name that corresponds to the display name of "Windows Security Service") LPCWSTR serviceNameToGetSecurityInformationFrom = L"SecurityHealthService"; SC_HANDLE serviceManagerHandle = NULL, serviceHandle = NULL; char securityDescriptorBuffer[1024]; DWORD lengthOfReturnedValue = 0; LPSTR daclBuffer = nullptr, absoluteSecurityDescriptionBuffer = nullptr; DWORD daclBufferSize = NULL, ownerSidBufferSize = NULL, absoluteSecurityDescriptionBufferSize = NULL, saclBufferSize = NULL, primaryGroupSidBufferSize = NULL; WCHAR serviceName[] = L"MySampleService1"; DWORD securityInfoChangeOperationErrorValue = NULL; BOOL securityDescriptorInAbsoluteFormatCreationErrorValue = NULL; serviceManagerHandle = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); if (serviceManagerHandle == nullptr) { cout << "Error opening Service Manager Handle (" << GetLastError() << ").\n"; } else { serviceHandle = OpenService(serviceManagerHandle, serviceNameToGetSecurityInformationFrom, READ_CONTROL); //| WRITE_OWNER | WRITE_DAC if (serviceHandle == nullptr) { cout << "Error opening service (" << GetLastError() << ").\n"; } else { if (!QueryServiceObjectSecurity(serviceHandle, DACL_SECURITY_INFORMATION, securityDescriptorBuffer, sizeof(securityDescriptorBuffer), &lengthOfReturnedValue)) { cout << "Error obtaining service's security information (" << GetLastError() << ").\n"; } else { BOOL bDaclPresent = false, bDaclDefaulted = false; PACL pDacl = NULL; BOOL ret = GetSecurityDescriptorDacl(securityDescriptorBuffer, &bDaclPresent, &pDacl, &bDaclDefaulted); if (bDaclPresent) { securityInfoChangeOperationErrorValue = SetNamedSecurityInfo(serviceName, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, NULL, pDacl, NULL); } else { cout << "The security descriptor doesn't contain a DACL" << endl; } //SC_HANDLE target_service = OpenService(serviceManagerHandle, serviceName, WRITE_DAC); //| WRITE_OWNER | WRITE_DAC //if (serviceHandle == nullptr) { // cout << "Error opening service (" << GetLastError() << ").\n"; //} //else { // BOOL ret = SetServiceObjectSecurity(target_service, DACL_SECURITY_INFORMATION, securityDescriptorBuffer); // if (ret == 0) { // cout << "Error SetServiceObjectSecurity (" << GetLastError() << ").\n"; // } // CloseServiceHandle(target_service); //} } CloseServiceHandle(serviceHandle); } CloseServiceHandle(serviceManagerHandle); } return 0; }

© www.soinside.com 2019 - 2024. All rights reserved.