Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign upinternal/wguser: support Windows port's pipe interface #36
Comments
mdlayher
changed the title
internal/wgwindows: new package to support Windows port
internal/wguser: support Windows port's pipe interface
May 10, 2019
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
This CL should let us complete the implementation of this: https://go-review.googlesource.com/c/sys/+/176625. The actual part where we find and enumerate pipes is done, just need to put the appropriate token code in place to access it now. |
This comment has been minimized.
This comment has been minimized.
zx2c4
commented
May 13, 2019
|
Pending the merging of that CL, here's some working code: package main
import (
"errors"
"fmt"
"github.com/Microsoft/go-winio"
"golang.org/x/sys/windows"
"net"
"runtime"
"strings"
"unsafe"
)
func openPipe(tunnelName string) (net.Conn, error) {
runtime.LockOSThread()
defer func() {
windows.RevertToSelf()
runtime.UnlockOSThread()
}()
privileges := windows.Tokenprivileges{
PrivilegeCount: 1,
Privileges: [1]windows.LUIDAndAttributes{
{
Attributes: windows.SE_PRIVILEGE_ENABLED,
},
},
}
err := windows.LookupPrivilegeValue(nil, windows.StringToUTF16Ptr("SeDebugPrivilege"), &privileges.Privileges[0].Luid)
if err != nil {
return nil, err
}
err = windows.ImpersonateSelf(windows.SecurityImpersonation)
if err != nil {
return nil, err
}
thread, _ := windows.GetCurrentThread()
var threadToken windows.Token
err = windows.OpenThreadToken(thread, windows.TOKEN_ADJUST_PRIVILEGES, false, &threadToken)
if err != nil {
return nil, err
}
defer threadToken.Close()
err = windows.AdjustTokenPrivileges(threadToken, false, &privileges, uint32(unsafe.Sizeof(privileges)), nil, nil)
if err != nil {
return nil, err
}
processes, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0)
if err != nil {
return nil, err
}
defer windows.CloseHandle(processes)
processEntry := windows.ProcessEntry32{Size: uint32(unsafe.Sizeof(windows.ProcessEntry32{}))}
pid := uint32(0)
for err = windows.Process32First(processes, &processEntry); err == nil; err = windows.Process32Next(processes, &processEntry) {
if strings.ToLower(windows.UTF16ToString(processEntry.ExeFile[:])) == "winlogon.exe" {
pid = processEntry.ProcessID
break
}
}
if pid == 0 {
return nil, errors.New("Unable to find winlogon.exe process")
}
winlogonProcess, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, pid)
if err != nil {
return nil, err
}
defer windows.CloseHandle(winlogonProcess)
var winlogonToken windows.Token
err = windows.OpenProcessToken(winlogonProcess, windows.TOKEN_IMPERSONATE|windows.TOKEN_DUPLICATE, &winlogonToken)
if err != nil {
return nil, err
}
defer winlogonToken.Close()
var duplicatedToken windows.Token
err = windows.DuplicateTokenEx(winlogonToken, 0, nil, windows.SecurityImpersonation, windows.TokenImpersonation, &duplicatedToken)
if err != nil {
return nil, err
}
defer duplicatedToken.Close()
err = windows.SetThreadToken(nil, duplicatedToken)
if err != nil {
return nil, err
}
return winio.DialPipe(`\\.\pipe\WireGuard\`+tunnelName, nil)
}
func main() {
var findData windows.Win32finddata
findHandle, err := windows.FindFirstFile(windows.StringToUTF16Ptr(`\\.\pipe\*`), &findData)
defer windows.CloseHandle(findHandle)
if err != nil {
fmt.Println(err)
return
}
for {
name := windows.UTF16ToString(findData.FileName[:])
for strings.HasPrefix(name, `WireGuard\`) {
name = name[10:]
fmt.Printf("name=%s\n", name)
conn, err := openPipe(name)
if err != nil {
fmt.Println(err)
break
}
defer conn.Close()
conn.Write([]byte("get=1\n\n"))
var resp [0x10000]byte
n, err := conn.Read(resp[:])
if err != nil {
fmt.Println(err)
break
}
fmt.Print(string(resp[:n]))
break
}
err = windows.FindNextFile(findHandle, &findData)
if err != nil {
if err == windows.ERROR_NO_MORE_FILES {
break
}
fmt.Println(err)
break
}
}
} |
mdlayher
referenced this issue
May 13, 2019
Merged
internal/wguser: use Windows token impersonation for device access #43
mdlayher
closed this
in
#43
May 14, 2019
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
mdlayher commentedMay 10, 2019
The Windows port uses the userspace protocol but uses special pipes to pass configuration rather than a UNIX socket:
"\\\\.\\pipe\\WireGuard\\"+name. There should be a way to detect all of these pipes and configure them.Jason also recommends looking at https://github.com/Microsoft/go-winio.