1
2
3
4
5
6
7 package windows_test
8
9 import (
10 "fmt"
11 "internal/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 }
140
View as plain text