c++ – SetNamedSecurityInfo() returning function ACCESS_IS_DENIED (error code 5 in Winerror.h) even when the application is run as admin

To set OWNER_SECURITY_INFORMATIONthe calling process must have WRITE_OWNER access, or must be the owner of the object or have the SE_TAKE_OWNERSHIP_NAME privilege enabled or SE_RESTORE_NAME when you set not self SID as the owner of object. And you don’t need to set the SID of the owner of the object necessary. The following sample work for me:

#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;
}

Or just use SetServiceObjectSecurity:

#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 {
                //securityDescriptorInAbsoluteFormatCreationErrorValue = MakeAbsoluteSD(securityDescriptorBuffer, NULL, &absoluteSecurityDescriptionBufferSize, (PACL)daclBuffer, &daclBufferSize, NULL, &saclBufferSize, NULL, &ownerSidBufferSize, NULL, &primaryGroupSidBufferSize);
                //if ((!securityDescriptorInAbsoluteFormatCreationErrorValue) && (ERROR_INSUFFICIENT_BUFFER) == GetLastError()) {
                //    // Induced error
                //    //cout << "ERROR: Inadequate size of the buffers implemented.n";
                //    absoluteSecurityDescriptionBuffer = new CHAR[absoluteSecurityDescriptionBufferSize];
                //    daclBuffer = new CHAR[daclBufferSize];
                //    securityDescriptorInAbsoluteFormatCreationErrorValue = MakeAbsoluteSD(securityDescriptorBuffer, absoluteSecurityDescriptionBuffer, &absoluteSecurityDescriptionBufferSize, (PACL)daclBuffer, &daclBufferSize, NULL, &saclBufferSize, NULL, &ownerSidBufferSize, NULL, &primaryGroupSidBufferSize);
                //}
                //securityInfoChangeOperationErrorValue = SetNamedSecurityInfo(serviceName, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, NULL, (ACL*)daclBuffer, NULL);
                //if (securityInfoChangeOperationErrorValue != ERROR_SUCCESS) {
                //    cout << "Error setting security info (" << securityInfoChangeOperationErrorValue << ").n";
                //}
                //delete[] absoluteSecurityDescriptionBuffer;
                //delete[] daclBuffer;
                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;
}

Note:

[SetServiceObjectSecurity is available for use in the operating
systems specified in the Requirements section. It may be altered or
unavailable in subsequent versions. Instead, use the
SetNamedSecurityInfo function.]

Leave a Comment