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