win32api/advapi32.go

296 lines
7.5 KiB
Go
Raw Permalink Normal View History

2019-03-07 11:39:54 +08:00
package win32api
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
func DuplicateTokenEx(hExistingToken HANDLE, dwDesiredAccess DWORD,
lpTokenAttributes uintptr, ImpersonationLevel int,
TokenType TOKEN_TYPE, phNewToken *TOKEN) error {
Dup, err := getProcAddr("advapi32.dll", "DuplicateTokenEx")
2019-03-07 11:39:54 +08:00
if err != nil {
return err
2019-03-07 11:39:54 +08:00
}
r, _, errno := syscall.Syscall6(Dup, 6, uintptr(hExistingToken), uintptr(dwDesiredAccess), lpTokenAttributes, uintptr(ImpersonationLevel),
2019-03-07 11:39:54 +08:00
uintptr(TokenType), uintptr(unsafe.Pointer(phNewToken)))
if r == 0 {
2021-09-01 11:03:37 +08:00
return error(errno)
2019-03-07 11:39:54 +08:00
}
return nil
}
func CreateProcessAsUser(hToken TOKEN, lpApplicationName, lpCommandLine string,
lpProcessAttributes, lpThreadAttributes, bInheritHandles uintptr,
dwCreationFlags DWORD, lpEnvironment HANDLE, lpCurrentDirectory string,
2019-03-07 11:39:54 +08:00
lpStartupInfo *StartupInfo, lpProcessInformation *ProcessInformation) error {
var (
applicationName uintptr
commandLine uintptr
workingDir uintptr
2019-03-07 11:39:54 +08:00
)
CPAU, err := getProcAddr("advapi32.dll", "CreateProcessAsUserW")
2019-03-07 11:39:54 +08:00
if err != nil {
return err
2019-03-07 11:39:54 +08:00
}
if len(lpApplicationName) > 0 {
applicationName = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpApplicationName)))
2019-03-07 11:39:54 +08:00
}
if len(lpCommandLine) > 0 {
commandLine = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpCommandLine)))
}
if len(lpCurrentDirectory) > 0 {
workingDir = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpCurrentDirectory)))
}
r, _, errno := syscall.Syscall12(CPAU, 11, uintptr(hToken), applicationName,
2019-03-07 11:39:54 +08:00
commandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, uintptr(dwCreationFlags), uintptr(lpEnvironment),
workingDir, uintptr(unsafe.Pointer(lpStartupInfo)), uintptr(unsafe.Pointer(lpProcessInformation)), 0)
if r == 0 {
2021-09-01 11:03:37 +08:00
return error(errno)
2019-03-07 11:39:54 +08:00
}
return nil
}
func GetTokenInformation(TokenHandle HANDLE, TokenInformationClass, TokenInformation,
TokenInformationLength uintptr, ReturnLength *uintptr) error {
GTI, err := getProcAddr("advapi32.dll", "GetTokenInformation")
2019-03-07 11:39:54 +08:00
if err != nil {
return err
}
if r, _, errno := syscall.Syscall6(GTI, 5, uintptr(TokenHandle), TokenInformationClass,
TokenInformation, TokenInformationLength, uintptr(unsafe.Pointer(ReturnLength)), 0); r == 0 {
return error(errno)
2019-03-07 11:39:54 +08:00
}
return nil
}
func GetUserName() (string, error) {
gun, err := getProcAddr("advapi32.dll", "GetUserNameW")
2019-03-07 11:39:54 +08:00
if err != nil {
return "", err
2019-03-07 11:39:54 +08:00
}
size := uint32(64)
for {
buf := make([]uint16, size)
n := uint32(len(buf))
r, _, errno := syscall.Syscall(gun, 2, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0)
if r != 0 {
return syscall.UTF16ToString(buf), nil
}
if errno == syscall.ERROR_INSUFFICIENT_BUFFER {
if n > size {
size = n
} else {
size *= 2
}
continue
}
if errno != 0 {
return "", error(errno)
}
return "", syscall.EINVAL
}
}
func OpenProcessToken(ProcessHandle HANDLE, DesiredAccess DWORD, TokenHandle *TOKEN) error {
if TokenHandle == nil {
return syscall.EINVAL
}
proc, err := getProcAddr("advapi32.dll", "OpenProcessToken")
if err != nil {
return err
}
r, _, errno := syscall.Syscall(proc, 3, uintptr(ProcessHandle), uintptr(DesiredAccess), uintptr(unsafe.Pointer(TokenHandle)))
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func CheckTokenMembership(tokenHandle HANDLE, sidToCheck unsafe.Pointer) (bool, error) {
if sidToCheck == nil {
return false, syscall.EINVAL
}
proc, err := getProcAddr("advapi32.dll", "CheckTokenMembership")
if err != nil {
return false, err
}
var isMember int32
r, _, errno := syscall.Syscall(proc, 3,
uintptr(tokenHandle),
uintptr(sidToCheck),
uintptr(unsafe.Pointer(&isMember)),
)
if r == 0 {
if errno != 0 {
return false, error(errno)
}
return false, syscall.EINVAL
}
return isMember != 0, nil
}
func LookupPrivilegeValue(lpSystemName, lpName string, lpLuid *LUID) error {
if lpLuid == nil {
return syscall.EINVAL
}
proc, err := getProcAddr("advapi32.dll", "LookupPrivilegeValueW")
if err != nil {
return err
}
var systemNamePtr uintptr
if len(lpSystemName) > 0 {
systemNamePtr = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpSystemName)))
}
r, _, errno := syscall.Syscall(proc, 3,
systemNamePtr,
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpName))),
uintptr(unsafe.Pointer(lpLuid)),
)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func AdjustTokenPrivileges(TokenHandle TOKEN, DisableAllPrivileges bool, NewState *TOKEN_PRIVILEGES, BufferLength DWORD,
PreviousState *TOKEN_PRIVILEGES, ReturnLength *DWORD) error {
proc, err := getProcAddr("advapi32.dll", "AdjustTokenPrivileges")
if err != nil {
return err
}
disableAll := uintptr(0)
if DisableAllPrivileges {
disableAll = 1
}
r, _, errno := syscall.Syscall6(proc, 6,
uintptr(TokenHandle),
disableAll,
uintptr(unsafe.Pointer(NewState)),
uintptr(BufferLength),
uintptr(unsafe.Pointer(PreviousState)),
uintptr(unsafe.Pointer(ReturnLength)),
)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
if errno == windows.ERROR_NOT_ALL_ASSIGNED {
2021-09-01 11:03:37 +08:00
return error(errno)
2019-03-07 11:39:54 +08:00
}
return nil
}
func RevertToSelf() error {
proc, err := getProcAddr("advapi32.dll", "RevertToSelf")
if err != nil {
return err
}
r, _, errno := syscall.Syscall(proc, 0, 0, 0, 0)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func CreateProcessWithToken(hToken TOKEN, dwLogonFlags DWORD, lpApplicationName, lpCommandLine string,
dwCreationFlags DWORD, lpEnvironment HANDLE, lpCurrentDirectory string,
lpStartupInfo *StartupInfo, lpProcessInformation *ProcessInformation) error {
var (
applicationName uintptr
commandLine uintptr
currentDir uintptr
)
if len(lpApplicationName) > 0 {
applicationName = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpApplicationName)))
}
if len(lpCommandLine) > 0 {
commandLine = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpCommandLine)))
}
if len(lpCurrentDirectory) > 0 {
currentDir = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpCurrentDirectory)))
}
proc, err := getProcAddr("advapi32.dll", "CreateProcessWithTokenW")
if err != nil {
return err
}
r, _, errno := syscall.Syscall12(proc, 9,
uintptr(hToken),
uintptr(dwLogonFlags),
applicationName,
commandLine,
uintptr(dwCreationFlags),
uintptr(lpEnvironment),
currentDir,
uintptr(unsafe.Pointer(lpStartupInfo)),
uintptr(unsafe.Pointer(lpProcessInformation)),
0,
0,
0,
)
if r == 0 {
if errno != 0 {
return error(errno)
}
return syscall.EINVAL
}
return nil
}
func IsTokenElevated(token TOKEN) (bool, error) {
var elevation TOKEN_ELEVATION
var retLen uintptr
if err := GetTokenInformation(
HANDLE(token),
TokenElevation,
uintptr(unsafe.Pointer(&elevation)),
uintptr(unsafe.Sizeof(elevation)),
&retLen,
); err != nil {
return false, err
}
return elevation.TokenIsElevated != 0, nil
}
func IsCurrentProcessElevated() (bool, error) {
processHandle, err := syscall.GetCurrentProcess()
if err != nil {
return false, err
}
var token TOKEN
if err := OpenProcessToken(HANDLE(processHandle), TOKEN_QUERY, &token); err != nil {
return false, err
}
defer func() {
_ = CloseHandle(HANDLE(token))
}()
return IsTokenElevated(token)
}
func IsCurrentUserInAdminGroup() (bool, error) {
adminSID, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid)
if err != nil {
return false, err
}
// Passing tokenHandle=0 lets Windows use the calling thread/process effective token.
return CheckTokenMembership(0, unsafe.Pointer(adminSID))
}