You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
7.5 KiB
Go

2 years ago
package wincmd
import (
"fmt"
"strconv"
"strings"
"unsafe"
"b612.me/win32api"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)
func StartProcessWithSYS(appPath, cmdLine, workDir string, runas bool) error {
var (
sessionId win32api.HANDLE
userToken win32api.TOKEN = 0
envInfo win32api.HANDLE
impersonationToken win32api.HANDLE = 0
startupInfo win32api.StartupInfo
processInfo win32api.ProcessInformation
sessionInformation win32api.HANDLE = win32api.HANDLE(0)
sessionCount int = 0
sessionList []*win32api.WTS_SESSION_INFO = make([]*win32api.WTS_SESSION_INFO, 0)
err error
)
if err := win32api.WTSEnumerateSessions(0, 0, 1, &sessionInformation, &sessionCount); err != nil {
return err
}
structSize := unsafe.Sizeof(win32api.WTS_SESSION_INFO{})
current := uintptr(sessionInformation)
for i := 0; i < sessionCount; i++ {
sessionList = append(sessionList, (*win32api.WTS_SESSION_INFO)(unsafe.Pointer(current)))
current += structSize
}
if sessionId, err = func() (win32api.HANDLE, error) {
for i := range sessionList {
if sessionList[i].State == win32api.WTSActive {
return sessionList[i].SessionID, nil
}
}
if sessionId, err := win32api.WTSGetActiveConsoleSessionId(); sessionId == 0xFFFFFFFF {
return 0xFFFFFFFF, fmt.Errorf("get current user session token: call native WTSGetActiveConsoleSessionId: %s", err)
} else {
return win32api.HANDLE(sessionId), nil
}
}(); err != nil {
return err
}
if err := win32api.WTSQueryUserToken(sessionId, &impersonationToken); err != nil {
return err
}
if err := win32api.DuplicateTokenEx(impersonationToken, 0, 0, int(win32api.SecurityImpersonation), win32api.TokenPrimary, &userToken); err != nil {
return fmt.Errorf("call native DuplicateTokenEx: %s", err)
}
if runas {
var admin win32api.TOKEN_LINKED_TOKEN
var dt uintptr = 0
if err := win32api.GetTokenInformation(impersonationToken, 19, uintptr(unsafe.Pointer(&admin)), uintptr(unsafe.Sizeof(admin)), &dt); err == nil {
userToken = admin.LinkedToken
}
}
if err := win32api.CloseHandle(impersonationToken); err != nil {
return fmt.Errorf("close windows handle used for token duplication: %s", err)
}
if err := win32api.CreateEnvironmentBlock(&envInfo, userToken, 0); err != nil {
return fmt.Errorf("create environment details for process: %s", err)
}
creationFlags := win32api.CREATE_UNICODE_ENVIRONMENT | win32api.CREATE_NEW_CONSOLE
startupInfo.ShowWindow = win32api.SW_SHOW
startupInfo.Desktop = windows.StringToUTF16Ptr("winsta0\\default")
if err := win32api.CreateProcessAsUser(userToken, appPath, cmdLine, 0, 0, 0,
creationFlags, envInfo, workDir, &startupInfo, &processInfo); err != nil {
return fmt.Errorf("create process as user: %s", err)
}
return nil
}
func GetRunningProcess() ([]map[string]string, error) {
result := []map[string]string{}
pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0)
if err != nil {
return result, err
}
for {
var proc win32api.PROCESSENTRY32
proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc))
if err := win32api.Process32Next(pHandle, &proc); err == nil {
bytetmp := proc.SzExeFile[0:]
var sakura []byte
for _, v := range bytetmp {
if v == byte(0) {
break
}
sakura = append(sakura, v)
}
result = append(result, map[string]string{"name": string(sakura), "pid": strconv.Itoa(int(proc.Th32ProcessID)), "ppid": fmt.Sprint(int(proc.Th32ParentProcessID))})
} else {
break
}
}
win32api.CloseHandle(pHandle)
return result, nil
}
func IsProcessRunningByPID(pid int) bool {
pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0)
if err != nil {
return false
}
for {
var proc win32api.PROCESSENTRY32
proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc))
if err := win32api.Process32Next(pHandle, &proc); err == nil {
bytetmp := int(proc.Th32ProcessID)
if bytetmp == pid {
return true
}
} else {
break
}
}
win32api.CloseHandle(pHandle)
return false
}
func IsProcessRunning(name string) bool {
pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0)
if err != nil {
return false
}
for {
var proc win32api.PROCESSENTRY32
proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc))
if err := win32api.Process32Next(pHandle, &proc); err == nil {
bytetmp := proc.SzExeFile[0:]
var sakura []byte
for _, v := range bytetmp {
if v == byte(0) {
break
}
sakura = append(sakura, v)
}
if strings.ToLower(strings.TrimSpace(string(sakura))) == strings.ToLower(strings.TrimSpace(name)) {
return true
}
} else {
break
}
}
win32api.CloseHandle(pHandle)
return false
}
func GetProcessCount(name string) int {
var res int = 0
pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0)
if err != nil {
return 0
}
for {
var proc win32api.PROCESSENTRY32
proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc))
if err := win32api.Process32Next(pHandle, &proc); err == nil {
bytetmp := proc.SzExeFile[0:]
var sakura []byte
for _, v := range bytetmp {
if v == byte(0) {
break
}
sakura = append(sakura, v)
}
if strings.ToLower(strings.TrimSpace(string(sakura))) == strings.ToLower(strings.TrimSpace(name)) {
res++
}
} else {
break
}
}
win32api.CloseHandle(pHandle)
return res
}
func Isas() bool {
_, errs := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM`, registry.ALL_ACCESS)
if errs != nil {
return false
}
return true
}
func StartProcess(appPath, cmdLine, wordDir string, runas bool, ShowWindow int) bool {
var cst string
if runas {
cst = "runas"
} else {
cst = "open"
}
r := win32api.ShellExecute(0, cst, appPath, cmdLine, wordDir, ShowWindow)
if r != nil {
return false
}
return true
}
func StartProcessWithPID(appPath, cmdLine, workDir string, runas bool, ShowWindow int) int {
var sakura win32api.SHELLEXECUTEINFOW
sakura.Hwnd = 0
sakura.NShow = ShowWindow
sakura.FMask = 0x00000040
sakura.LpParameters = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(cmdLine)))
sakura.LpFile = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(appPath)))
sakura.LpDirectory = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(workDir)))
if runas {
sakura.LpVerb = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("runas")))
} else {
sakura.LpVerb = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("open")))
}
sakura.CbSize = win32api.DWORD(unsafe.Sizeof(sakura))
if err := win32api.ShellExecuteEx(&sakura); err != nil {
return 0
}
return int(win32api.GetProcessId(sakura.HProcess))
}
func AutoRun(key, path string) (bool, error) {
reg, errs := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS)
if errs != nil {
return false, errs
}
if errs = reg.SetStringValue(key, path); errs != nil {
return false, errs
}
return true, nil
}
func DeleteAutoRun(key string) (bool, error) {
reg, errs := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS)
if errs != nil {
return false, errs
}
if _, i, _ := reg.GetStringValue(key); i == 0 {
return true, nil
}
if errs = reg.DeleteValue(key); errs != nil {
return false, errs
}
return true, nil
}
func IsAutoRun(key, path string) bool {
reg, errs := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS)
if errs != nil {
return false
}
if sa, _, _ := reg.GetStringValue(key); sa == path {
return true
}
return false
}