101 lines
2.8 KiB
Go
101 lines
2.8 KiB
Go
//go:build windows
|
|
|
|
package admin
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
func protectCodeFile(path string) error {
|
|
currentSID, err := currentProcessUserSID()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
systemSID, err := windows.CreateWellKnownSid(windows.WinLocalSystemSid)
|
|
if err != nil {
|
|
return fmt.Errorf("创建系统账户安全标识失败:%w", err)
|
|
}
|
|
adminSID, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid)
|
|
if err != nil {
|
|
return fmt.Errorf("创建本地管理员组安全标识失败:%w", err)
|
|
}
|
|
|
|
var pinner runtime.Pinner
|
|
pinner.Pin(currentSID)
|
|
pinner.Pin(systemSID)
|
|
pinner.Pin(adminSID)
|
|
defer pinner.Unpin()
|
|
|
|
readDelete := windows.ACCESS_MASK(windows.FILE_GENERIC_READ | windows.DELETE | windows.READ_CONTROL | windows.SYNCHRONIZE)
|
|
fullControl := windows.ACCESS_MASK(windows.FILE_GENERIC_READ |
|
|
windows.FILE_GENERIC_WRITE |
|
|
windows.FILE_GENERIC_EXECUTE |
|
|
windows.DELETE |
|
|
windows.READ_CONTROL |
|
|
windows.WRITE_DAC |
|
|
windows.WRITE_OWNER |
|
|
windows.SYNCHRONIZE)
|
|
entries := []windows.EXPLICIT_ACCESS{
|
|
{
|
|
AccessPermissions: readDelete,
|
|
AccessMode: windows.SET_ACCESS,
|
|
Inheritance: windows.NO_INHERITANCE,
|
|
Trustee: windows.TRUSTEE{
|
|
TrusteeForm: windows.TRUSTEE_IS_SID,
|
|
TrusteeType: windows.TRUSTEE_IS_USER,
|
|
TrusteeValue: windows.TrusteeValueFromSID(currentSID),
|
|
},
|
|
},
|
|
{
|
|
AccessPermissions: fullControl,
|
|
AccessMode: windows.SET_ACCESS,
|
|
Inheritance: windows.NO_INHERITANCE,
|
|
Trustee: windows.TRUSTEE{
|
|
TrusteeForm: windows.TRUSTEE_IS_SID,
|
|
TrusteeType: windows.TRUSTEE_IS_WELL_KNOWN_GROUP,
|
|
TrusteeValue: windows.TrusteeValueFromSID(systemSID),
|
|
},
|
|
},
|
|
{
|
|
AccessPermissions: fullControl,
|
|
AccessMode: windows.SET_ACCESS,
|
|
Inheritance: windows.NO_INHERITANCE,
|
|
Trustee: windows.TRUSTEE{
|
|
TrusteeForm: windows.TRUSTEE_IS_SID,
|
|
TrusteeType: windows.TRUSTEE_IS_ALIAS,
|
|
TrusteeValue: windows.TrusteeValueFromSID(adminSID),
|
|
},
|
|
},
|
|
}
|
|
acl, err := windows.ACLFromEntries(entries, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("创建校验码文件访问控制列表失败:%w", err)
|
|
}
|
|
if err := windows.SetNamedSecurityInfo(
|
|
path,
|
|
windows.SE_FILE_OBJECT,
|
|
windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION,
|
|
nil,
|
|
nil,
|
|
acl,
|
|
nil,
|
|
); err != nil {
|
|
return fmt.Errorf("应用校验码文件访问控制列表失败:%w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func currentProcessUserSID() (*windows.SID, error) {
|
|
user, err := windows.GetCurrentProcessToken().GetTokenUser()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("读取当前服务账户安全标识失败:%w", err)
|
|
}
|
|
if user == nil || user.User.Sid == nil {
|
|
return nil, fmt.Errorf("当前服务账户没有有效的安全标识")
|
|
}
|
|
return user.User.Sid, nil
|
|
}
|