Files

456 lines
12 KiB
Go

//go:build windows
package remote
import (
"bytes"
"crypto/rand"
"golang.org/x/sys/windows/registry"
"math/big"
"os"
)
// GetRemoteInfo 一次性获取远程控制相关信息(服务状态/端口/密码/主机信息)
func GetRemoteInfo() Info {
info := Info{}
status, _ := GetVncServiceStatus()
info.VncState = int(status)
status, _ = GetRdpServiceStatus()
info.RdpState = int(status)
port, _ := GetRdpPort()
info.RdpPort = port
port, _ = GetVncPort()
info.VncPort = port
password, _ := GetVncPassword()
info.VncPassword = password
hostname, _ := os.Hostname()
info.Hostname = hostname
info.IpAddr = getIPs()
info.MacAddr = getMacAddrs()
return info
}
// GetVncPort 从注册表读取 TightVNC 主端口
func GetVncPort() (int, error) {
var key registry.Key
var err error
key, err = registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\TightVNC\Server`, registry.ALL_ACCESS)
if err != nil {
return 0, err
}
var val uint64
val, _, err = key.GetIntegerValue("RfbPort")
if err != nil {
return 0, err
}
var port int = int(val)
return port, nil
}
// GetRdpPort 从注册表读取远程桌面端口
func GetRdpPort() (int, error) {
var key registry.Key
var err error
key, err = registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp`, registry.ALL_ACCESS)
if err != nil {
return 0, err
}
var val uint64
val, _, err = key.GetIntegerValue("PortNumber")
if err != nil {
return 0, err
}
var port int = int(val)
return port, nil
}
// GetVncPassword 读取并解密 TightVNC 连接密码
func GetVncPassword() (string, error) {
var key registry.Key
var err error
key, err = registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\TightVNC\Server`, registry.ALL_ACCESS)
if err != nil {
return "", err
}
val, _, err := key.GetBinaryValue("Password")
if err != nil {
return "", err
}
if len(val) == 0 {
return "", err
}
password := VncPasswordDecrypt(val)
if err != nil {
return "", err
}
return password, nil
}
// VncServerDefaultConfig 生成 TightVNC 服务端默认配置(连接 RDP 会话)
// randPass 为 true 时生成 8 位随机密码,否则使用固定密码
func VncServerDefaultConfig(randPass bool) VncServerConfig {
password := "tvncpass"
if randPass {
password = createRandomString(8)
}
config := VncServerConfig{
ExtraPorts: "",
QueryTimeout: 30,
QueryAcceptOnTimeout: 0,
LocalInputPriorityTimeout: 3,
LocalInputPriority: 1,
BlockRemoteInput: 0,
BlockLocalInput: 0,
IpAccessControl: "",
RfbPort: 5900,
HttpPort: 5800,
DisconnectAction: 0,
AcceptRfbConnections: 1,
UseVncAuthentication: 1,
UseControlAuthentication: 0,
RepeatControlAuthentication: 0,
LoopbackOnly: 0,
AcceptHttpConnections: 0,
LogLevel: 0,
EnableFileTransfers: 1,
RemoveWallpaper: 1,
UseD3D: 1,
UseMirrorDriver: 1,
EnableUrlParams: 1,
Password: VncPasswordCrypt(password),
AlwaysShared: 0,
NeverShared: 0,
DisconnectClients: 1,
PollingInterval: 1000,
AllowLoopback: 1,
VideoRecognitionInterval: 3000,
GrabTransparentWindows: 1,
SaveLogToAllUsersPath: 0,
RunControlInterface: 0,
IdleTimeout: 0,
VideoClasses: "",
VideoRects: "",
ConnectToRdp: 1,
}
return config
}
// VncClientDefaultConfig 生成 TightVNC 客户端默认配置(不连接 RDP 会话)
// randPass 为 true 时生成 8 位随机密码,否则使用固定密码
func VncClientDefaultConfig(randPass bool) VncServerConfig {
password := "tvncpass"
if randPass {
password = createRandomString(8)
}
config := VncServerConfig{
ExtraPorts: "",
QueryTimeout: 30,
QueryAcceptOnTimeout: 0,
LocalInputPriorityTimeout: 3,
LocalInputPriority: 1,
BlockRemoteInput: 0,
BlockLocalInput: 0,
IpAccessControl: "",
RfbPort: 5900,
HttpPort: 5800,
DisconnectAction: 0,
AcceptRfbConnections: 1,
UseVncAuthentication: 1,
UseControlAuthentication: 0,
RepeatControlAuthentication: 0,
LoopbackOnly: 0,
AcceptHttpConnections: 0,
LogLevel: 0,
EnableFileTransfers: 1,
RemoveWallpaper: 0,
UseD3D: 1,
UseMirrorDriver: 1,
EnableUrlParams: 1,
Password: VncPasswordCrypt(password),
AlwaysShared: 0,
NeverShared: 0,
DisconnectClients: 1,
PollingInterval: 1000,
AllowLoopback: 1,
VideoRecognitionInterval: 3000,
GrabTransparentWindows: 1,
SaveLogToAllUsersPath: 0,
RunControlInterface: 0,
IdleTimeout: 0,
VideoClasses: "",
VideoRects: "",
ConnectToRdp: 0,
}
return config
}
// WriteVncServerConfig 将 TightVNC 服务端配置写入注册表(项不存在时自动创建)
func WriteVncServerConfig(config VncServerConfig) error {
key, err := registry.OpenKey(registry.LOCAL_MACHINE, "SOFTWARE\\TightVNC\\Server", registry.ALL_ACCESS)
if err != nil {
if err == registry.ErrNotExist {
// 项不存在 创建它
key, _, err = registry.CreateKey(registry.LOCAL_MACHINE, "SOFTWARE\\TightVNC\\Server", registry.ALL_ACCESS)
if err != nil {
return err
}
} else {
return err
}
}
defer key.Close()
err = key.SetStringValue("ExtraPorts", config.ExtraPorts)
if err != nil {
return err
}
err = key.SetDWordValue("QueryTimeout", config.QueryTimeout)
if err != nil {
return err
}
err = key.SetDWordValue("QueryAcceptOnTimeout", config.QueryAcceptOnTimeout)
if err != nil {
return err
}
err = key.SetDWordValue("LocalInputPriorityTimeout", config.LocalInputPriorityTimeout)
if err != nil {
return err
}
err = key.SetDWordValue("LocalInputPriority", config.LocalInputPriority)
if err != nil {
return err
}
err = key.SetDWordValue("BlockRemoteInput", config.BlockRemoteInput)
if err != nil {
return err
}
err = key.SetDWordValue("BlockLocalInput", config.BlockLocalInput)
if err != nil {
return err
}
err = key.SetStringValue("IpAccessControl", config.IpAccessControl)
if err != nil {
return err
}
err = key.SetDWordValue("RfbPort", config.RfbPort)
if err != nil {
return err
}
err = key.SetDWordValue("HttpPort", config.HttpPort)
if err != nil {
return err
}
err = key.SetDWordValue("DisconnectAction", config.DisconnectAction)
if err != nil {
return err
}
err = key.SetDWordValue("AcceptRfbConnections", config.AcceptRfbConnections)
if err != nil {
return err
}
err = key.SetDWordValue("UseVncAuthentication", config.UseVncAuthentication)
if err != nil {
return err
}
err = key.SetDWordValue("UseControlAuthentication", config.UseControlAuthentication)
if err != nil {
return err
}
err = key.SetDWordValue("RepeatControlAuthentication", config.RepeatControlAuthentication)
if err != nil {
return err
}
err = key.SetDWordValue("LoopbackOnly", config.LoopbackOnly)
if err != nil {
return err
}
err = key.SetDWordValue("AcceptHttpConnections", config.AcceptHttpConnections)
if err != nil {
return err
}
err = key.SetDWordValue("LogLevel", config.LogLevel)
if err != nil {
return err
}
err = key.SetDWordValue("EnableFileTransfers", config.EnableFileTransfers)
if err != nil {
return err
}
err = key.SetDWordValue("RemoveWallpaper", config.RemoveWallpaper)
if err != nil {
return err
}
err = key.SetDWordValue("UseD3D", config.UseD3D)
if err != nil {
return err
}
err = key.SetDWordValue("UseMirrorDriver", config.UseMirrorDriver)
if err != nil {
return err
}
err = key.SetDWordValue("EnableUrlParams", config.EnableUrlParams)
if err != nil {
return err
}
err = key.SetBinaryValue("Password", config.Password)
if err != nil {
return err
}
err = key.SetDWordValue("AlwaysShared", config.AlwaysShared)
if err != nil {
return err
}
err = key.SetDWordValue("NeverShared", config.NeverShared)
if err != nil {
return err
}
err = key.SetDWordValue("DisconnectClients", config.DisconnectClients)
if err != nil {
return err
}
err = key.SetDWordValue("PollingInterval", config.PollingInterval)
if err != nil {
return err
}
err = key.SetDWordValue("AllowLoopback", config.AllowLoopback)
if err != nil {
return err
}
err = key.SetDWordValue("VideoRecognitionInterval", config.VideoRecognitionInterval)
if err != nil {
return err
}
err = key.SetDWordValue("GrabTransparentWindows", config.GrabTransparentWindows)
if err != nil {
return err
}
err = key.SetDWordValue("SaveLogToAllUsersPath", config.SaveLogToAllUsersPath)
if err != nil {
return err
}
err = key.SetDWordValue("RunControlInterface", config.RunControlInterface)
if err != nil {
return err
}
err = key.SetDWordValue("IdleTimeout", config.IdleTimeout)
if err != nil {
return err
}
err = key.SetStringValue("VideoClasses", config.VideoClasses)
if err != nil {
return err
}
err = key.SetStringValue("VideoRects", config.VideoRects)
if err != nil {
return err
}
err = key.SetDWordValue("ConnectToRdp", config.ConnectToRdp)
if err != nil {
return err
}
return nil
}
// EnableSoftwareSASGeneration 启用软件SAS模拟输入
func EnableSoftwareSASGeneration() error {
// SAS模拟输入
key, err := registry.OpenKey(registry.LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", registry.ALL_ACCESS)
if err != nil {
if err == registry.ErrNotExist {
// 项不存在 创建它
key, _, err = registry.CreateKey(registry.LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", registry.ALL_ACCESS)
if err != nil {
return err
}
} else {
return err
}
}
defer key.Close()
err = key.SetDWordValue("SoftwareSASGeneration", 1)
if err != nil {
return err
}
return nil
}
// EnableWinlogonDisableCAD 关闭 Ctrl + Alt + Del 组合键来登录
func EnableWinlogonDisableCAD() error {
key, err := registry.OpenKey(registry.LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", registry.ALL_ACCESS)
if err != nil {
if err == registry.ErrNotExist {
// 项不存在 创建它
key, _, err = registry.CreateKey(registry.LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", registry.ALL_ACCESS)
if err != nil {
return err
}
} else {
return err
}
}
defer key.Close()
err = key.SetDWordValue("DisableCAD", 1)
if err != nil {
return err
}
return nil
}
// EnableSystemDisableCAD 关闭 Ctrl + Alt + Del 组合键来登录
func EnableSystemDisableCAD() error {
key, err := registry.OpenKey(registry.LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", registry.ALL_ACCESS)
if err != nil {
if err == registry.ErrNotExist {
// 项不存在 创建它
key, _, err = registry.CreateKey(registry.LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", registry.ALL_ACCESS)
if err != nil {
return err
}
} else {
return err
}
}
defer key.Close()
err = key.SetDWordValue("DisableCAD", 1)
if err != nil {
return err
}
return nil
}
// createRandomString 生成指定长度的随机字符串
func createRandomString(len int) string {
var container string
var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
b := bytes.NewBufferString(str)
length := b.Len()
bigInt := big.NewInt(int64(length))
for i := 0; i < len; i++ {
randomInt, _ := rand.Int(rand.Reader, bigInt)
container += string(str[randomInt.Int64()])
}
return container
}