github.com/google/osv-scalibr@v0.4.1/detector/weakcredentials/winlocal/win32_windows.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //go:build windows
    16  
    17  package winlocal
    18  
    19  import (
    20  	"errors"
    21  	"syscall"
    22  	"unsafe"
    23  
    24  	"golang.org/x/sys/windows"
    25  )
    26  
    27  var (
    28  	advapiDLL    = syscall.NewLazyDLL("Advapi32.dll")
    29  	regSaveKeyEx = advapiDLL.NewProc("RegSaveKeyExW")
    30  )
    31  
    32  func securityAttributesFromSDDL(sddl string) (*windows.SecurityAttributes, error) {
    33  	if sddl == "" {
    34  		return nil, nil
    35  	}
    36  
    37  	sd, err := windows.SecurityDescriptorFromString(sddl)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	sa := &windows.SecurityAttributes{
    43  		Length:             uint32(unsafe.Sizeof(windows.SecurityAttributes{})),
    44  		SecurityDescriptor: sd,
    45  		InheritHandle:      0,
    46  	}
    47  
    48  	return sa, nil
    49  }
    50  
    51  // RegSaveKey wraps the `RegSaveKeyExW` Win32 API to save a registry key to a file.
    52  //
    53  // Note: sddl is optional. If empty, the security attribute will be null and the file will get a
    54  // default security descriptor.
    55  //
    56  // https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsavekeyexw
    57  //
    58  // LSTATUS RegSaveKeyExW(
    59  //
    60  //	[in]           HKEY                        hKey,
    61  //	[in]           LPCWSTR                     lpFile,
    62  //	[in, optional] const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    63  //	[in]           DWORD                       Flags
    64  //
    65  // );
    66  func RegSaveKey(key syscall.Handle, path string, sddl string) error {
    67  	if regSaveKeyEx == nil {
    68  		return errors.New("cannot find RegSaveKeyExW in Advapi32.dll")
    69  	}
    70  
    71  	securityAttributes, err := securityAttributesFromSDDL(sddl)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	p, err := syscall.UTF16PtrFromString(path)
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	// Note: we enforce the `Flags` parameter to be 1 (REG_STANDARD_FORMAT) to always use the standard
    82  	// registry format.
    83  	flags := uintptr(1)
    84  	hKey := uintptr(key)
    85  	lpFile := uintptr(unsafe.Pointer(p))
    86  	lpSecurityAttributes := uintptr(unsafe.Pointer(securityAttributes))
    87  
    88  	if ret, _, _ := regSaveKeyEx.Call(hKey, lpFile, lpSecurityAttributes, flags); ret != 0 {
    89  		return syscall.Errno(ret)
    90  	}
    91  
    92  	return nil
    93  }