代码之家  ›  专栏  ›  技术社区  ›  Kerido

以编程方式允许对注册表项进行写访问

  •  4
  • Kerido  · 技术社区  · 16 年前

    1. 安装程序以管理模式运行。
    2. 将创建一个注册表项。
    3. 如果此函数发现组“Users”已具有写访问权限,则不应执行任何操作。
    4. 如果没有,它应该添加一个新的权限,允许对“Users”组进行写访问。
    5. 将保存注册表项的权限。

    Setting Registry key write permissions using .NET

    提前谢谢

    1 回复  |  直到 9 年前
        1
  •  4
  •   Luke    16 年前

    要获取和设置密钥的ACL,需要使用RegGetKeySecurity和RegSetKeySecurity。然后您需要遍历ace,检查任何应用于“Users”组SID的代码。然后您可以修改/删除现有的和/或添加一个新的。请注意,在普通的旧win32c中使用acl是一种痛苦。

        2
  •  2
  •   Mikhail Vorotilov    7 年前

    授予访问权限的最小代码由3个API调用组成。它可以完全访问给定的 hkey

    此代码段不包含正确的错误处理和报告。不要将其复制/粘贴到生产代码中。

        PSECURITY_DESCRIPTOR sd = nullptr;
        ULONG sd_size = 0;
        TCHAR* rights = TEXT( "D:" )                // Discretionary ACL
                      TEXT( "(A;OICI;GA;;;AU)" )    // Allow full control to all authenticated users
                      TEXT( "(A;OICI;GA;;;BA)" );   // Allow full control to administrators
    
        ConvertStringSecurityDescriptorToSecurityDescriptor( rights, SDDL_REVISION_1, &sd, &sd_size );
        RegSetKeySecurity( hkey, DACL_SECURITY_INFORMATION, sd );
        LocalFree( sd );
    

    检测“用户”是否具有对密钥的写访问权限可能比预期的更困难。最后,我将一个测试值写入注册表并检查写入结果。

        3
  •  2
  •   InsanityPants    6 年前

    只是为了扩展Mikhail Vorotilov的答案,同时也从 https://docs.microsoft.com/en-us/windows/win32/secbp/creating-a-dacl

    bool RegistryGrantAll(HKEY hKey)
    {
        bool bResult = false;
    
        PSECURITY_DESCRIPTOR sd = nullptr;
    
        const TCHAR* szSD =
            TEXT("D:")                  // Discretionary ACL
            TEXT("(D;OICI;KA;;;BG)")    // Deny access to built-in guests
            TEXT("(D;OICI;KA;;;AN)")    // Deny access to anonymous logon
            TEXT("(A;OICI;KRKW;;;AU)")  // Allow KEY_READ and KEY_WRITE to authenticated users ("AU")
            TEXT("(A;OICI;KA;;;BA)");   // Allow KEY_ALL_ACCESS to administrators ("BA" = Built-in Administrators)
    
        if (ConvertStringSecurityDescriptorToSecurityDescriptor((LPCTSTR)szSD, SDDL_REVISION_1, &sd, 0))
        {
            auto result = RegSetKeySecurity(hKey, DACL_SECURITY_INFORMATION, sd);
            if (ERROR_SUCCESS == result)
                bResult = true;
            else
                SetLastError(result);
    
            // Free the memory allocated for the SECURITY_DESCRIPTOR.
            LocalFree(sd);
        }
    
        return bResult;
    }
    

    代码在VS2019上编译,似乎可以正常工作。
    我没有添加代码来检查hKey是否是有效的注册表句柄。

    编辑:我在测试之后编辑了几次。很抱歉所有的编辑。我最终得到的比我开始得到的更接近米哈伊尔的答案。

    更多信息链接:

    https://docs.microsoft.com/en-us/windows/win32/secbp/creating-a-dacl

    https://docs.microsoft.com/en-us/windows/win32/api/sddl/nf-sddl-convertstringsecuritydescriptortosecuritydescriptorw

    https://docs.microsoft.com/en-us/windows/win32/secauthz/ace-strings

        4
  •  0
  •   alex yi    6 年前

    RegGetKeySecurity 或者需要手动创建ACL。甚至没有必要 RegOpenKeyEx . 有关详细信息,请查看 this MS doc.

    升级版

    // sk - alloced string / path to needed key
    // common look: MACHINE\\Software\\... where MACHINE == HKEY_LOCAL_MACHINE
    // google for more address abbrevations
    PSECURITY_DESCRIPTOR pSD = 0;
    EXPLICIT_ACCESS ea;
    PACL pOldDACL = 0, pNewDACL = 0;
    if (ERROR_SUCCESS == GetNamedSecurityInfo(sk, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, 0, 0, &pOldDACL, 0, &pSD)) {
        memset(&ea, 0, sizeof(EXPLICIT_ACCESS));
        ea.grfAccessPermissions = KEY_ALL_ACCESS;
        ea.grfAccessMode = GRANT_ACCESS;
        ea.grfInheritance = NO_INHERITANCE;
        ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
        ea.Trustee.ptstrName = <USERNAME HERE>; //DOMAIN\\USERNAME
        if (ERROR_SUCCESS == SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL)) {
            if (ERROR_SUCCESS == SetNamedSecurityInfo(sk, SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, 0, 0, pNewDACL, 0)) {
                if (pSD != 0) LocalFree((HLOCAL)pSD);
                if (pNewDACL != 0) LocalFree((HLOCAL)pNewDACL);
                SAFE_FREE(sk);
                // WE'RE GOOD!
                return ... ;
            } else {
                if (pSD) LocalFree((HLOCAL)pSD);
                if (pNewDACL) LocalFree((HLOCAL)pNewDACL);
                SAFE_FREE(sk);
                // SetNamedSecurityInfo failed
                return  ... ;
            }
        } else {
            if (pSD) LocalFree((HLOCAL)pSD);
            if (pNewDACL) LocalFree((HLOCAL)pNewDACL);
            SAFE_FREE(sk);
            // SetEntriesInAcl failed
            return ... ;
        }
    } else {
        if (pSD) LocalFree((HLOCAL)pSD);
        SAFE_FREE(sk);
        // GetNamedSecurityInfo failed
        return ... ;
    }