1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
*/
package elevate
import (
"path/filepath"
"runtime"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)
const (
releaseOffset = 2
shellExecuteOffset = 9
cSEE_MASK_DEFAULT = 0
)
func ShellExecute(program string, arguments string, directory string, show int32) (err error) {
var (
program16 *uint16
arguments16 *uint16
directory16 *uint16
)
if len(program) > 0 {
program16, _ = windows.UTF16PtrFromString(program)
}
if len(arguments) > 0 {
arguments16, _ = windows.UTF16PtrFromString(arguments)
}
if len(directory) > 0 {
directory16, _ = windows.UTF16PtrFromString(directory)
}
defer func() {
if err != nil {
err = windows.ShellExecute(0, windows.StringToUTF16Ptr("runas"), program16, arguments16, directory16, show)
}
}()
processToken, err := windows.OpenCurrentProcessToken()
if err != nil {
return
}
defer processToken.Close()
if processToken.IsElevated() {
err = windows.ERROR_SUCCESS
return
}
key, err := registry.OpenKey(registry.LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\UAC\\COMAutoApprovalList", registry.QUERY_VALUE)
if err == nil {
var autoApproved uint64
autoApproved, _, err = key.GetIntegerValue("{3E5FC7F9-9A51-4367-9063-A120244FBEC7}")
key.Close()
if err != nil {
return
}
if uint32(autoApproved) == 0 {
err = windows.ERROR_ACCESS_DENIED
return
}
}
moduleHandle, err := getModuleHandle(nil)
if err != nil {
return
}
var dataTableEntry *cLDR_DATA_TABLE_ENTRY
if ret := ldrFindEntryForAddress(moduleHandle, &dataTableEntry); ret != 0 {
err = syscall.Errno(windows.ERROR_INTERNAL_ERROR)
return
}
var windowsDirectory [windows.MAX_PATH]uint16
if _, err = getWindowsDirectory(&windowsDirectory[0], windows.MAX_PATH); err != nil {
return
}
originalPath := dataTableEntry.FullDllName.Buffer
explorerPath := windows.StringToUTF16Ptr(filepath.Join(windows.UTF16ToString(windowsDirectory[:]), "explorer.exe"))
rtlInitUnicodeString(&dataTableEntry.FullDllName, explorerPath)
defer func() {
rtlInitUnicodeString(&dataTableEntry.FullDllName, originalPath)
runtime.KeepAlive(explorerPath)
}()
if err = coInitializeEx(0, cCOINIT_APARTMENTTHREADED); err == nil {
defer coUninitialize()
}
var interfacePointer **[0xffff]uintptr
if err = coGetObject(
windows.StringToUTF16Ptr("Elevation:Administrator!new:{3E5FC7F9-9A51-4367-9063-A120244FBEC7}"),
&cBIND_OPTS3{
cbStruct: uint32(unsafe.Sizeof(cBIND_OPTS3{})),
dwClassContext: cCLSCTX_LOCAL_SERVER,
},
&windows.GUID{0x6EDD6D74, 0xC007, 0x4E75, [8]byte{0xB7, 0x6A, 0xE5, 0x74, 0x09, 0x95, 0xE2, 0x4C}},
&interfacePointer,
); err != nil {
return
}
defer syscall.Syscall((*interfacePointer)[releaseOffset], 1, uintptr(unsafe.Pointer(interfacePointer)), 0, 0)
if ret, _, _ := syscall.Syscall6((*interfacePointer)[shellExecuteOffset], 6,
uintptr(unsafe.Pointer(interfacePointer)),
uintptr(unsafe.Pointer(program16)),
uintptr(unsafe.Pointer(arguments16)),
uintptr(unsafe.Pointer(directory16)),
cSEE_MASK_DEFAULT,
uintptr(show),
); ret != uintptr(windows.ERROR_SUCCESS) {
err = syscall.Errno(ret)
return
}
err = nil
return
}
|