aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/elevate
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-12-06 13:47:00 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2019-12-11 12:06:25 +0100
commitb0b375d89566b4cfaa506c3bb22b25e816b15508 (patch)
tree3a7c5281129aa4702c85c490bf06d575af25d9db /elevate
parentfirewall: fix urls (diff)
downloadwireguard-windows-b0b375d89566b4cfaa506c3bb22b25e816b15508.tar.xz
wireguard-windows-b0b375d89566b4cfaa506c3bb22b25e816b15508.zip
elevate: add service impersonation
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'elevate')
-rw-r--r--elevate/doas.go75
1 files changed, 58 insertions, 17 deletions
diff --git a/elevate/doas.go b/elevate/doas.go
index ede22a9a..ceedb78b 100644
--- a/elevate/doas.go
+++ b/elevate/doas.go
@@ -12,6 +12,7 @@ import (
"unsafe"
"golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/svc/mgr"
)
func DoAsSystem(f func() error) error {
@@ -41,12 +42,13 @@ func DoAsSystem(f func() error) error {
if err != nil {
return err
}
- defer threadToken.Close()
tokenUser, err := threadToken.GetTokenUser()
if err == nil && tokenUser.User.Sid.IsWellKnown(windows.WinLocalSystemSid) {
+ threadToken.Close()
return f()
}
err = windows.AdjustTokenPrivileges(threadToken, false, &privileges, uint32(unsafe.Sizeof(privileges)), nil, nil)
+ threadToken.Close()
if err != nil {
return err
}
@@ -55,9 +57,6 @@ func DoAsSystem(f func() error) error {
if err != nil {
return err
}
- defer windows.CloseHandle(processes)
-
- var winlogonToken windows.Token
processEntry := windows.ProcessEntry32{Size: uint32(unsafe.Sizeof(windows.ProcessEntry32{}))}
for err = windows.Process32First(processes, &processEntry); err == nil; err = windows.Process32Next(processes, &processEntry) {
if strings.ToLower(windows.UTF16ToString(processEntry.ExeFile[:])) != "winlogon.exe" {
@@ -67,34 +66,76 @@ func DoAsSystem(f func() error) error {
if err != nil {
continue
}
+ var winlogonToken windows.Token
err = windows.OpenProcessToken(winlogonProcess, windows.TOKEN_QUERY|windows.TOKEN_IMPERSONATE|windows.TOKEN_DUPLICATE, &winlogonToken)
+ windows.CloseHandle(winlogonProcess)
if err != nil {
- windows.CloseHandle(winlogonProcess)
continue
}
tokenUser, err := winlogonToken.GetTokenUser()
if err != nil || !tokenUser.User.Sid.IsWellKnown(windows.WinLocalSystemSid) {
- windows.CloseHandle(winlogonProcess)
winlogonToken.Close()
- winlogonToken = 0
continue
}
- defer windows.CloseHandle(winlogonProcess)
- defer winlogonToken.Close()
- break
+ windows.CloseHandle(processes)
+
+ var duplicatedToken windows.Token
+ err = windows.DuplicateTokenEx(winlogonToken, 0, nil, windows.SecurityImpersonation, windows.TokenImpersonation, &duplicatedToken)
+ windows.CloseHandle(winlogonProcess)
+ if err != nil {
+ return err
+ }
+ err = windows.SetThreadToken(nil, duplicatedToken)
+ duplicatedToken.Close()
+ if err != nil {
+ return err
+ }
+ return f()
}
- if winlogonToken == 0 {
- return errors.New("unable to find winlogon.exe process")
+ windows.CloseHandle(processes)
+ return errors.New("unable to find winlogon.exe process")
+}
+
+func DoAsService(serviceName string, f func() error) error {
+ scm, err := mgr.Connect()
+ if err != nil {
+ return err
}
- var duplicatedToken windows.Token
- err = windows.DuplicateTokenEx(winlogonToken, 0, nil, windows.SecurityImpersonation, windows.TokenImpersonation, &duplicatedToken)
+ service, err := scm.OpenService(serviceName)
+ scm.Disconnect()
if err != nil {
return err
}
- defer duplicatedToken.Close()
- err = windows.SetThreadToken(nil, duplicatedToken)
+ status, err := service.Query()
+ service.Close()
if err != nil {
return err
}
- return f()
+ if status.ProcessId == 0 {
+ return errors.New("service is not running")
+ }
+ return DoAsSystem(func() error {
+ serviceProcess, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, status.ProcessId)
+ if err != nil {
+ return err
+ }
+ var serviceToken windows.Token
+ err = windows.OpenProcessToken(serviceProcess, windows.TOKEN_IMPERSONATE|windows.TOKEN_DUPLICATE, &serviceToken)
+ windows.CloseHandle(serviceProcess)
+ if err != nil {
+ return err
+ }
+ var duplicatedToken windows.Token
+ err = windows.DuplicateTokenEx(serviceToken, 0, nil, windows.SecurityImpersonation, windows.TokenImpersonation, &duplicatedToken)
+ serviceToken.Close()
+ if err != nil {
+ return err
+ }
+ err = windows.SetThreadToken(nil, duplicatedToken)
+ duplicatedToken.Close()
+ if err != nil {
+ return err
+ }
+ return f()
+ })
}