You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何灰化基于Win32 API开发的自研Windows服务启动类型?

如何通过Win32 API限制Windows服务的启动类型修改

要实现类似WinDefend服务那样灰化启动类型选项、阻止用户修改的效果,核心是通过修改服务的安全权限,移除或拒绝普通用户拥有修改服务配置的权限(即SERVICE_CHANGE_CONFIG权限)。以下是具体实现步骤及代码示例:

实现思路

Windows服务的启动类型修改属于服务配置变更操作,需要调用方拥有SERVICE_CHANGE_CONFIG权限。我们通过修改服务的安全描述符(SD),添加拒绝普通用户/组获取该权限的访问控制项(ACE),即可阻止用户修改启动类型。

具体步骤

  1. 打开服务管理器与目标服务
    使用OpenSCManager打开本地服务管理器,再通过OpenService打开目标服务,需确保拥有READ_CONTROL(读取安全设置)和WRITE_DAC(修改权限)权限。

  2. 获取当前服务的安全描述符
    调用QueryServiceObjectSecurity获取服务当前的安全描述符,用于后续修改。

  3. 构建新的访问控制列表(DACL)
    创建拒绝SERVICE_CHANGE_CONFIG权限的ACE,针对目标用户/组(比如普通用户组Users),通过SetEntriesInAcl将该ACE合并到原有的DACL中,生成新的DACL。

  4. 应用修改后的安全描述符
    将包含新DACL的安全描述符通过SetServiceObjectSecurity应用到目标服务上,完成权限限制。

代码示例(C++ Win32 API)

#include <windows.h>
#include <aclapi.h>

// 限制指定服务的启动类型修改权限
BOOL RestrictServiceStartupTypeChange(LPCWSTR szServiceName) {
    // 打开服务管理器
    SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!hSCManager) return FALSE;

    // 打开目标服务,需拥有读写权限
    SC_HANDLE hService = OpenService(hSCManager, szServiceName, READ_CONTROL | WRITE_DAC);
    if (!hService) {
        CloseServiceHandle(hSCManager);
        return FALSE;
    }

    // 获取当前安全描述符
    PSECURITY_DESCRIPTOR pSD = NULL;
    DWORD dwBytesNeeded = 0;
    if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, NULL, 0, &dwBytesNeeded) &&
        GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
        pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwBytesNeeded);
        if (!pSD) goto Cleanup;
        
        if (!QueryServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, pSD, dwBytesNeeded, &dwBytesNeeded))
            goto Cleanup;
    }

    // 提取原有DACL
    PACL pOldDACL = NULL;
    BOOL bDaclPresent = FALSE, bDaclDefaulted = FALSE;
    if (!GetSecurityDescriptorDacl(pSD, &bDaclPresent, &pOldDACL, &bDaclDefaulted))
        goto Cleanup;

    // 创建拒绝SERVICE_CHANGE_CONFIG权限的ACE(针对普通用户组)
    EXPLICIT_ACCESS ea = {0};
    ea.grfAccessPermissions = SERVICE_CHANGE_CONFIG;
    ea.grfAccessMode = DENY_ACCESS;
    ea.grfInheritance = NO_INHERITANCE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea.Trustee.ptstrName = L"Users";

    PACL pNewDACL = NULL;
    if (SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL) != ERROR_SUCCESS)
        goto Cleanup;

    // 更新安全描述符的DACL并应用到服务
    BOOL bResult = FALSE;
    if (SetSecurityDescriptorDacl(pSD, TRUE, pNewDACL, FALSE)) {
        bResult = SetServiceObjectSecurity(hService, DACL_SECURITY_INFORMATION, pSD);
    }

Cleanup:
    // 释放资源
    if (pNewDACL) LocalFree(pNewDACL);
    if (pSD) LocalFree(pSD);
    CloseServiceHandle(hService);
    CloseServiceHandle(hSCManager);
    return bResult;
}

注意事项

  • 操作必须以管理员身份执行,否则无法获取修改服务权限的权限。
  • 可根据需求调整目标用户/组(比如替换L"Users"为L"Authenticated Users"或特定用户名)。
  • 权限设置生效后,普通用户打开服务属性窗口时,启动类型下拉框会被灰化,无法修改。
  • 若需恢复修改权限,只需移除对应的拒绝ACE即可,流程与上述步骤类似,将DENY_ACCESS改为REVOKE_ACCESS或删除目标ACE。

内容的提问来源于stack exchange,提问作者NImIPKZvUc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 07:47:27