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