Sign in to follow this  
Followers 0
DmitryKa

Set Everyone write permission to a Registry key

5 posts in this topic

#1 ·  Posted (edited)

Sometimes we need to save a piece of data for the whole machine globally, not for a current user only. Unfortunately HKEY_LOCAL_MACHINE is write-protected for anybody except administrators. But you may create e.g. a key "a_key" below HKEY_LOCAL_MACHINE with admin rights and then - assign "write-everybody" permission to "a_key", so unprivileged users will share the same data and will be allowed to modify it.

The following function _RegSetKeySecuritySetNullDacl sets "write-everybody" permission to a Registry key.

Usage sample:

Local $szKey = "HKEY_LOCAL_MACHINE\SOFTWARE\YourCompany\a_key"
Local $code, $msg
Local $ok = _RegSetKeySecuritySetNullDacl($szKey, $code, $msg)
If Not $ok Then MsgBox(0, "Exited with code " & $code, $msg)

The library:

#include-once

#include <StructureConstants.au3>
#include <WinAPIError.au3>
#include <WinAPI.au3>


;
; Return value:
; 0 - failure
; 1 - success
;
Func _RegSetKeySecuritySetNullDacl($szKey, ByRef $errorCode, ByRef $errorMessage)
    Local $hKey = 0
    Local $ret = _RegSetKeySecuritySetNullDaclInternal($szKey, $hKey)
    If $hKey Then DllCall('AdvAPI32.dll', 'Long', 'RegCloseKey', "ulong_ptr", $hKey)
    If $ret Then
        If StringIsInt($ret) Then
            $errorCode = $ret
            $errorMessage = _WinAPI_GetErrorMessageByCode($ret)
        Else
            $errorCode = 1
            $errorMessage = $ret
        EndIf
        Return 0
    Else
        $errorCode = 0
        $errorMessage = 0
        Return 1
    EndIf
EndFunc


;
; Return values:
; 0     - success
; nnn   - Windows error code
; "..." - error description
;
Func _RegSetKeySecuritySetNullDaclInternal($szKey, ByRef $hKey)
    Local $HKEY_CLASSES_ROOT = 0x80000000
    Local $HKEY_CURRENT_USER = 0x80000001
    Local $HKEY_LOCAL_MACHINE = 0x80000002
    Local $HKEY_USERS = 0x80000003
    Local $HKEY_CURRENT_CONFIG = 0x80000005

    ; Parse key hive.
    Local $hRoot = StringLeft($szKey, StringInStr($szKey, '\') - 1)
    If $hRoot = "" Then $hRoot = $szKey ; passed a root key
    Switch StringUpper($hRoot)
        Case "HKEY_LOCAL_MACHINE", "HKLM"
            $hRoot = $HKEY_LOCAL_MACHINE
        Case "HKEY_USERS", "HKU"
            $hRoot = $HKEY_USERS
        Case "HKEY_CURRENT_USER", "HKCU"
            $hRoot = $HKEY_CURRENT_USER
        Case "HKEY_CLASSES_ROOT", "HKCR"
            $hRoot = $HKEY_CLASSES_ROOT
        Case "HKEY_CURRENT_CONFIG", "HKCC"
            $hRoot = $HKEY_CURRENT_CONFIG
        Case Else
            Return "Unknown hive name: " & $hRoot
    EndSwitch
    Local $szSubkey = StringTrimLeft($szKey, StringInStr($szKey, '\'))
    If $szSubkey = $szKey Then $szSubkey = "" ; root key

    ; Open existed registry key.
    Local $aRet = DllCall( _
        "advapi32.dll", "long", "RegOpenKeyExW", _
        "ulong_ptr", $hRoot, _
        "wstr", $szSubkey, _
        "dword", 0, _
        "ulong", 0x40000, _ ; WRITE_DAC
        "ulong_ptr*", 0 _
    )
    If @error Then Return "RegOpenKeyExW loading failed: @error=" & @error
    If $aRet[0] Then Return $aRet[0]
    $hKey = $aRet[5]
    
    ; The size of SECURITY_DESCRIPTOR is 20 bytes.  We just
    ; need a block of memory the right size, we aren't going to
    ; access any members directly so it's not important what
    ; the members are, just that the total size is correct.
    Local $pSecurityAttributes = 0
    Local $aRet = 0
    Local $tSecurityDescriptor = DllStructCreate("dword[5]")
    Local $pSecurityDescriptor = DllStructGetPtr($tSecurityDescriptor)
    
    ; Initialize the security descriptor.
    $aRet = DllCall( _
        "advapi32.dll", "bool", "InitializeSecurityDescriptor", _
        "ptr", $pSecurityDescriptor, _
        "dword", 1 _
    )
    If @error Then Return "InitializeSecurityDescriptor loading failed: @error=" & @error
    If Not $aRet[0] Then Return $aRet[0]

    ; Add the NULL DACL specifying access to everybody.
    $aRet = DllCall( _
        "advapi32.dll", "bool", "SetSecurityDescriptorDacl", _
        "ptr", $pSecurityDescriptor, _
        "bool", 1, _
        "ptr", 0, _
        "bool", 0 _
    )
    If @error Then Return "SetSecurityDescriptorDacl loading failed: @error=" & @error
    If Not $aRet[0] Then Return $aRet[0]

    ; Set permissions.    
    $aRet = DllCall( _
        "Advapi32.dll", "long", "RegSetKeySecurity", _
        "ulong_ptr", $hKey, _
        "dword", BitOr(0x00000004, 0x80000000), _
        "ptr", $pSecurityDescriptor _
    )
    If @error Then Return "RegSetKeySecurity loading failed: @error=" & @error
    If $aRet[0] Then Return $aRet[0]

    Return 0
EndFunc


;
; Convert Windows error code to message.
;
Func _WinAPI_GetErrorMessageByCode($code)
    Local $tBufferPtr = DllStructCreate("ptr")
    Local $pBufferPtr = DllStructGetPtr($tBufferPtr)

    Local $nCount = _WinAPI_FormatMessage(BitOR($__WINAPICONSTANT_FORMAT_MESSAGE_ALLOCATE_BUFFER, $__WINAPICONSTANT_FORMAT_MESSAGE_FROM_SYSTEM), _
        0, $code, 0, $pBufferPtr, 0, 0)
    If @error Then Return SetError(@error, 0, "")

     Local $sText = ""
    Local $pBuffer = DllStructGetData($tBufferPtr, 1)
    If $pBuffer Then
        If $nCount > 0 Then
            Local $tBuffer = DllStructCreate("wchar[" & ($nCount+1) & "]", $pBuffer)
            $sText = DllStructGetData($tBuffer, 1)
        EndIf
        _WinAPI_LocalFree($pBuffer)
    EndIf

    Return $sText
EndFunc   ;==>_WinAPI_GetErrorMessageByCode
Edited by DmitryKa
1 person likes this

Share this post


Link to post
Share on other sites



Thanks for this code. It fixed my issues with my new script.

Share this post


Link to post
Share on other sites

I just tested this code, and while it does allow everyone to write to the key 'Technically', I think that it is a little misleading. It isn't assigning 'Everyone: Full' access, it is nulling out the security on that key. If you look at it after you run the function you can see that it says that there are no permissions whatsoever on the key and it gives a warning. Once I added 'Everyone: Full' to the key manually, the other permissions it was supposed to have were inherited.

I am not sure of the security implications of this, but just a heads up before you go applying this to any old key. For myself, I am not willing to take the risk in my environment and will keep looking for a solution to my problem. Thanks for sharing the code though.

Share this post


Link to post
Share on other sites

How do I deny access to everybody

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0