aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--attacksurface.md2
-rw-r--r--main.go17
-rw-r--r--mksyscall.go8
-rw-r--r--services/tokens.go6
-rw-r--r--tunnel/firewall/helpers.go12
-rw-r--r--zsyscall_windows.go76
6 files changed, 11 insertions, 110 deletions
diff --git a/attacksurface.md b/attacksurface.md
index f2b56d08..7e1906b0 100644
--- a/attacksurface.md
+++ b/attacksurface.md
@@ -29,7 +29,7 @@ The manager service is a userspace service running as Local System, responsible
- A readable `CreateFileMapping` handle to a binary ringlog shared by all services, inherited by the UI process.
- It listens for service changes in tunnel services according to the string prefix "WireGuardTunnel$".
- It manages DPAPI-encrypted configuration files in Local System's local appdata directory, and makes some effort to enforce good configuration filenames.
- - It uses `WTSEnumerateSessions` and `WTSSESSION_NOTIFICATION` to walk through each available session. It then uses `WTSQueryUserToken`, and then calls `GetTokenInformation(TokenGroups)` on it. If one of the returned group's SIDs matches `CreateWellKnownSid(WinBuiltinAdministratorsSid)`, and has attributes of either `SE_GROUP_ENABLED` or `SE_GROUP_USE_FOR_DENY_ONLY` and calling `GetTokenInformation(TokenElevation)` on it or its `TokenLinkedToken` indicates that either is elevated, then it spawns the UI process as that the elevated user token, passing it three unnamed pipe handles for IPC and the log mapping handle, as described above.
+ - It uses `WTSEnumerateSessions` and `WTSSESSION_NOTIFICATION` to walk through each available session. It then uses `WTSQueryUserToken`, and then calls `GetTokenInformation(TokenGroups)` on it. If one of the returned group's SIDs matches `IsWellKnownSid(WinBuiltinAdministratorsSid)`, and has attributes of either `SE_GROUP_ENABLED` or `SE_GROUP_USE_FOR_DENY_ONLY` and calling `GetTokenInformation(TokenElevation)` on it or its `TokenLinkedToken` indicates that either is elevated, then it spawns the UI process as that the elevated user token, passing it three unnamed pipe handles for IPC and the log mapping handle, as described above.
### UI
diff --git a/main.go b/main.go
index 1cb1fd88..f642906e 100644
--- a/main.go
+++ b/main.go
@@ -32,11 +32,8 @@ var flags = [...]string{
"/dumplog OUTPUT_PATH",
}
-//sys messageBoxEx(hwnd windows.Handle, text *uint16, title *uint16, typ uint, languageId uint16) = user32.MessageBoxExW
-//sys isWow64Process(handle windows.Handle, isWow64 *bool) (err error) = kernel32.IsWow64Process
-
func fatal(v ...interface{}) {
- messageBoxEx(0, windows.StringToUTF16Ptr(fmt.Sprint(v...)), windows.StringToUTF16Ptr("Error"), 0x00000010, 0)
+ windows.MessageBox(0, windows.StringToUTF16Ptr(fmt.Sprint(v...)), windows.StringToUTF16Ptr("Error"), windows.MB_ICONERROR)
os.Exit(1)
}
@@ -46,14 +43,17 @@ func usage() {
builder.WriteString(fmt.Sprintf(" %s\n", flag))
}
msg := fmt.Sprintf("Usage: %s [\n%s]", os.Args[0], builder.String())
- messageBoxEx(0, windows.StringToUTF16Ptr(msg), windows.StringToUTF16Ptr("Command Line Options"), 0x00000040, 0)
+ windows.MessageBox(0, windows.StringToUTF16Ptr(msg), windows.StringToUTF16Ptr("Command Line Options"), windows.MB_ICONINFORMATION)
os.Exit(1)
}
func checkForWow64() {
var b bool
- p, _ := windows.GetCurrentProcess()
- err := isWow64Process(p, &b)
+ p, err := windows.GetCurrentProcess()
+ if err != nil {
+ fatal(err)
+ }
+ err = windows.IsWow64Process(p, &b)
if err != nil {
fatal("Unable to determine whether the process is running under WOW64: ", err)
}
@@ -74,13 +74,12 @@ func checkForAdminGroup() {
}
}
-//sys shellExecute(hwnd windows.Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int) (err error) = shell32.ShellExecuteW
func execElevatedManagerServiceInstaller() error {
path, err := os.Executable()
if err != nil {
return err
}
- err = shellExecute(0, windows.StringToUTF16Ptr("runas"), windows.StringToUTF16Ptr(path), windows.StringToUTF16Ptr("/installmanagerservice"), nil, windows.SW_SHOW)
+ err = windows.ShellExecute(0, windows.StringToUTF16Ptr("runas"), windows.StringToUTF16Ptr(path), windows.StringToUTF16Ptr("/installmanagerservice"), nil, windows.SW_SHOW)
if err != nil {
return err
}
diff --git a/mksyscall.go b/mksyscall.go
deleted file mode 100644
index d72dc999..00000000
--- a/mksyscall.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-package main
-
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go main.go
diff --git a/services/tokens.go b/services/tokens.go
index aa6f2c4a..d3854f2d 100644
--- a/services/tokens.go
+++ b/services/tokens.go
@@ -14,10 +14,6 @@ import (
)
func TokenIsMemberOfBuiltInAdministrator(token windows.Token) bool {
- adminSid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid)
- if err != nil {
- return false
- }
gs, err := token.GetTokenGroups()
if err != nil {
return false
@@ -25,7 +21,7 @@ func TokenIsMemberOfBuiltInAdministrator(token windows.Token) bool {
groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(unsafe.Pointer(&gs.Groups[0]))[:gs.GroupCount]
isAdmin := false
for _, g := range groups {
- if (g.Attributes&windows.SE_GROUP_USE_FOR_DENY_ONLY != 0 || g.Attributes&windows.SE_GROUP_ENABLED != 0) && windows.EqualSid(g.Sid, adminSid) {
+ if (g.Attributes&windows.SE_GROUP_USE_FOR_DENY_ONLY != 0 || g.Attributes&windows.SE_GROUP_ENABLED != 0) && g.Sid.IsWellKnown(windows.WinBuiltinAdministratorsSid) {
isAdmin = true
break
}
diff --git a/tunnel/firewall/helpers.go b/tunnel/firewall/helpers.go
index 6bc71806..ee783c2d 100644
--- a/tunnel/firewall/helpers.go
+++ b/tunnel/firewall/helpers.go
@@ -87,22 +87,12 @@ func getCurrentProcessSecurityDescriptor() (*wtFwpByteBlob, error) {
if g.Attributes != windows.SE_GROUP_ENABLED|windows.SE_GROUP_ENABLED_BY_DEFAULT|windows.SE_GROUP_OWNER {
continue
}
- if *(*byte)(unsafe.Pointer(g.Sid)) != 1 { // The revision.
- continue
- }
- if *getSidIdentifierAuthority(g.Sid) != windows.SECURITY_NT_AUTHORITY {
- continue
- }
// We could be checking != 6, but hopefully Microsoft will update
// RtlCreateServiceSid to use SHA2, which will then likely bump
// this up. So instead just roll with a minimum.
- if *getSidSubAuthorityCount(g.Sid) < 6 {
+ if !g.Sid.IsValid() || g.Sid.IdentifierAuthority() != windows.SECURITY_NT_AUTHORITY || g.Sid.SubAuthorityCount() < 6 || g.Sid.SubAuthority(0) != 80 {
continue
}
- if *getSidSubAuthority(g.Sid, 0) != 80 {
- continue
- }
-
sid = g.Sid
break
}
diff --git a/zsyscall_windows.go b/zsyscall_windows.go
deleted file mode 100644
index dc9f9ffc..00000000
--- a/zsyscall_windows.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package main
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
- errnoERROR_IO_PENDING = 997
-)
-
-var (
- errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
- switch e {
- case 0:
- return nil
- case errnoERROR_IO_PENDING:
- return errERROR_IO_PENDING
- }
- // TODO: add more here, after collecting data on the common
- // error values see on Windows. (perhaps when running
- // all.bat?)
- return e
-}
-
-var (
- moduser32 = windows.NewLazySystemDLL("user32.dll")
- modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
- modshell32 = windows.NewLazySystemDLL("shell32.dll")
-
- procMessageBoxExW = moduser32.NewProc("MessageBoxExW")
- procIsWow64Process = modkernel32.NewProc("IsWow64Process")
- procShellExecuteW = modshell32.NewProc("ShellExecuteW")
-)
-
-func messageBoxEx(hwnd windows.Handle, text *uint16, title *uint16, typ uint, languageId uint16) {
- syscall.Syscall6(procMessageBoxExW.Addr(), 5, uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(title)), uintptr(typ), uintptr(languageId), 0)
- return
-}
-
-func isWow64Process(handle windows.Handle, isWow64 *bool) (err error) {
- r1, _, e1 := syscall.Syscall(procIsWow64Process.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(isWow64)), 0)
- if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}
-
-func shellExecute(hwnd windows.Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int) (err error) {
- r1, _, e1 := syscall.Syscall6(procShellExecuteW.Addr(), 6, uintptr(hwnd), uintptr(unsafe.Pointer(verb)), uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(args)), uintptr(unsafe.Pointer(cwd)), uintptr(showCmd))
- if r1 == 0 {
- if e1 != 0 {
- err = errnoErr(e1)
- } else {
- err = syscall.EINVAL
- }
- }
- return
-}