github.com/elijahmorg/goternal@v1.18.0/syscall/windows/exec_windows_test.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build windows 6 7 package windows_test 8 9 import ( 10 "fmt" 11 "github.com/elijahmorg/goternal/syscall/windows" 12 "os" 13 "os/exec" 14 "syscall" 15 "testing" 16 "unsafe" 17 ) 18 19 func TestRunAtLowIntegrity(t *testing.T) { 20 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { 21 wil, err := getProcessIntegrityLevel() 22 if err != nil { 23 fmt.Fprintf(os.Stderr, "error: %s\n", err.Error()) 24 os.Exit(9) 25 return 26 } 27 fmt.Printf("%s", wil) 28 os.Exit(0) 29 return 30 } 31 32 cmd := exec.Command(os.Args[0], "-test.run=TestRunAtLowIntegrity", "--") 33 cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} 34 35 token, err := getIntegrityLevelToken(sidWilLow) 36 if err != nil { 37 t.Fatal(err) 38 } 39 defer token.Close() 40 41 cmd.SysProcAttr = &syscall.SysProcAttr{ 42 Token: token, 43 } 44 45 out, err := cmd.CombinedOutput() 46 if err != nil { 47 t.Fatal(err) 48 } 49 50 if string(out) != sidWilLow { 51 t.Fatalf("Child process did not run as low integrity level: %s", string(out)) 52 } 53 } 54 55 const ( 56 sidWilLow = `S-1-16-4096` 57 ) 58 59 func getProcessIntegrityLevel() (string, error) { 60 procToken, err := syscall.OpenCurrentProcessToken() 61 if err != nil { 62 return "", err 63 } 64 defer procToken.Close() 65 66 p, err := tokenGetInfo(procToken, syscall.TokenIntegrityLevel, 64) 67 if err != nil { 68 return "", err 69 } 70 71 tml := (*windows.TOKEN_MANDATORY_LABEL)(p) 72 73 sid := (*syscall.SID)(unsafe.Pointer(tml.Label.Sid)) 74 75 return sid.String() 76 } 77 78 func tokenGetInfo(t syscall.Token, class uint32, initSize int) (unsafe.Pointer, error) { 79 n := uint32(initSize) 80 for { 81 b := make([]byte, n) 82 e := syscall.GetTokenInformation(t, class, &b[0], uint32(len(b)), &n) 83 if e == nil { 84 return unsafe.Pointer(&b[0]), nil 85 } 86 if e != syscall.ERROR_INSUFFICIENT_BUFFER { 87 return nil, e 88 } 89 if n <= uint32(len(b)) { 90 return nil, e 91 } 92 } 93 } 94 95 func getIntegrityLevelToken(wns string) (syscall.Token, error) { 96 var procToken, token syscall.Token 97 98 proc, err := syscall.GetCurrentProcess() 99 if err != nil { 100 return 0, err 101 } 102 defer syscall.CloseHandle(proc) 103 104 err = syscall.OpenProcessToken(proc, 105 syscall.TOKEN_DUPLICATE| 106 syscall.TOKEN_ADJUST_DEFAULT| 107 syscall.TOKEN_QUERY| 108 syscall.TOKEN_ASSIGN_PRIMARY, 109 &procToken) 110 if err != nil { 111 return 0, err 112 } 113 defer procToken.Close() 114 115 sid, err := syscall.StringToSid(wns) 116 if err != nil { 117 return 0, err 118 } 119 120 tml := &windows.TOKEN_MANDATORY_LABEL{} 121 tml.Label.Attributes = windows.SE_GROUP_INTEGRITY 122 tml.Label.Sid = sid 123 124 err = windows.DuplicateTokenEx(procToken, 0, nil, windows.SecurityImpersonation, 125 windows.TokenPrimary, &token) 126 if err != nil { 127 return 0, err 128 } 129 130 err = windows.SetTokenInformation(token, 131 syscall.TokenIntegrityLevel, 132 uintptr(unsafe.Pointer(tml)), 133 tml.Size()) 134 if err != nil { 135 token.Close() 136 return 0, err 137 } 138 return token, nil 139 }