diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-08-28 22:30:35 -0600 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-08-30 08:47:21 -0600 |
commit | 2bbd162221e56e0312593cb05956c100f253ff98 (patch) | |
tree | 2dab80c185282b6cb9270836cef88f852afe5a40 | |
parent | elevate: use more strict check for admin group (diff) | |
download | wireguard-windows-2bbd162221e56e0312593cb05956c100f253ff98.tar.xz wireguard-windows-2bbd162221e56e0312593cb05956c100f253ff98.zip |
elevate: check for desktop admin ownership
-rw-r--r-- | elevate/membership.go | 24 | ||||
-rw-r--r-- | elevate/syscall_windows.go | 3 | ||||
-rw-r--r-- | elevate/zsyscall_windows.go | 38 | ||||
-rw-r--r-- | main.go | 11 | ||||
-rw-r--r-- | manager/install.go | 4 |
5 files changed, 71 insertions, 9 deletions
diff --git a/elevate/membership.go b/elevate/membership.go index ccd0b60e..131c6d97 100644 --- a/elevate/membership.go +++ b/elevate/membership.go @@ -35,3 +35,27 @@ func TokenIsElevatedOrElevatable(token windows.Token) bool { defer linked.Close() return linked.IsElevated() && isAdmin(linked) } + +func IsAdminDesktop() (bool, error) { + hwnd := getShellWindow() + if hwnd == 0 { + return false, windows.ERROR_INVALID_WINDOW_HANDLE + } + var pid uint32 + _, err := getWindowThreadProcessId(hwnd, &pid) + if err != nil { + return false, err + } + process, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, pid) + if err != nil { + return false, err + } + defer windows.CloseHandle(process) + var token windows.Token + err = windows.OpenProcessToken(process, windows.TOKEN_QUERY | windows.TOKEN_IMPERSONATE, &token) + if err != nil { + return false, err + } + defer token.Close() + return TokenIsElevatedOrElevatable(token), nil +}
\ No newline at end of file diff --git a/elevate/syscall_windows.go b/elevate/syscall_windows.go index dba56375..1957dea2 100644 --- a/elevate/syscall_windows.go +++ b/elevate/syscall_windows.go @@ -84,3 +84,6 @@ const ( //sys coInitializeEx(reserved uintptr, coInit uint32) (ret error) = ole32.CoInitializeEx //sys coUninitialize() = ole32.CoUninitialize //sys coGetObject(name *uint16, bindOpts *cBIND_OPTS3, guid *windows.GUID, functionTable ***[0xffff]uintptr) (ret error) = ole32.CoGetObject + +//sys getWindowThreadProcessId(hwnd uintptr, pid *uint32) (tid uint32, err error) = user32.GetWindowThreadProcessId +//sys getShellWindow() (hwnd uintptr) = user32.GetShellWindow diff --git a/elevate/zsyscall_windows.go b/elevate/zsyscall_windows.go index 0ed13233..afff428f 100644 --- a/elevate/zsyscall_windows.go +++ b/elevate/zsyscall_windows.go @@ -37,14 +37,17 @@ func errnoErr(e syscall.Errno) error { } var ( - modntdll = windows.NewLazySystemDLL("ntdll.dll") - modole32 = windows.NewLazySystemDLL("ole32.dll") - - procRtlInitUnicodeString = modntdll.NewProc("RtlInitUnicodeString") - procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb") - procCoInitializeEx = modole32.NewProc("CoInitializeEx") - procCoUninitialize = modole32.NewProc("CoUninitialize") - procCoGetObject = modole32.NewProc("CoGetObject") + modntdll = windows.NewLazySystemDLL("ntdll.dll") + modole32 = windows.NewLazySystemDLL("ole32.dll") + moduser32 = windows.NewLazySystemDLL("user32.dll") + + procRtlInitUnicodeString = modntdll.NewProc("RtlInitUnicodeString") + procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb") + procCoInitializeEx = modole32.NewProc("CoInitializeEx") + procCoUninitialize = modole32.NewProc("CoUninitialize") + procCoGetObject = modole32.NewProc("CoGetObject") + procGetWindowThreadProcessId = moduser32.NewProc("GetWindowThreadProcessId") + procGetShellWindow = moduser32.NewProc("GetShellWindow") ) func rtlInitUnicodeString(destinationString *cUNICODE_STRING, sourceString *uint16) { @@ -78,3 +81,22 @@ func coGetObject(name *uint16, bindOpts *cBIND_OPTS3, guid *windows.GUID, functi } return } + +func getWindowThreadProcessId(hwnd uintptr, pid *uint32) (tid uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetWindowThreadProcessId.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(pid)), 0) + tid = uint32(r0) + if tid == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getShellWindow() (hwnd uintptr) { + r0, _, _ := syscall.Syscall(procGetShellWindow.Addr(), 0, 0, 0, 0) + hwnd = uintptr(r0) + return +} @@ -80,6 +80,13 @@ func checkForAdminGroup() { } } +func checkForAdminDesktop() { + adminDesktop, err := elevate.IsAdminDesktop() + if !adminDesktop && err == nil { + fatal("WireGuard is running, but the UI is only accessible from desktops of the Builtin Administrators group.") + } +} + func execElevatedManagerServiceInstaller() error { path, err := os.Executable() if err != nil { @@ -123,8 +130,12 @@ func main() { go ui.WaitForRaiseUIThenQuit() err := manager.InstallManager() if err != nil { + if err == manager.ErrManagerAlreadyRunning { + checkForAdminDesktop() + } fatal(err) } + checkForAdminDesktop() time.Sleep(30 * time.Second) fatal("WireGuard system tray icon did not appear after 30 seconds.") return diff --git a/manager/install.go b/manager/install.go index cff1289a..f84a96ae 100644 --- a/manager/install.go +++ b/manager/install.go @@ -32,6 +32,8 @@ func serviceManager() (*mgr.Mgr, error) { return cachedServiceManager, nil } +var ErrManagerAlreadyRunning = errors.New("Manager already installed and running") + func InstallManager() error { m, err := serviceManager() if err != nil { @@ -54,7 +56,7 @@ func InstallManager() error { } if status.State != svc.Stopped { service.Close() - return errors.New("Manager already installed and running") + return ErrManagerAlreadyRunning } err = service.Delete() service.Close() |