mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00
181 lines
4.6 KiB
Go
181 lines
4.6 KiB
Go
package vnc
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"time"
|
||
|
||
"github.com/shadow1ng/fscan/common"
|
||
"github.com/shadow1ng/fscan/plugins/base"
|
||
)
|
||
|
||
// VNCConnector VNC连接器
|
||
type VNCConnector struct {
|
||
host string
|
||
port string
|
||
}
|
||
|
||
// NewVNCConnector 创建VNC连接器
|
||
func NewVNCConnector() *VNCConnector {
|
||
return &VNCConnector{}
|
||
}
|
||
|
||
// Connect 连接到VNC服务
|
||
func (c *VNCConnector) Connect(ctx context.Context, info *common.HostInfo) (interface{}, error) {
|
||
c.host = info.Host
|
||
c.port = info.Ports
|
||
|
||
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
|
||
|
||
// 尝试连接到VNC服务
|
||
conn, err := common.WrapperTcpWithTimeout("tcp", target, time.Duration(common.Timeout)*time.Second)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("VNC连接失败: %v", err)
|
||
}
|
||
defer conn.Close()
|
||
|
||
// 读取VNC协议版本
|
||
versionBuf := make([]byte, 12)
|
||
_, err = conn.Read(versionBuf)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("读取VNC版本失败: %v", err)
|
||
}
|
||
|
||
versionStr := string(versionBuf)
|
||
if !c.isValidVNCVersion(versionStr) {
|
||
return nil, fmt.Errorf("无效的VNC协议版本: %s", versionStr)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"version": versionStr,
|
||
"target": target,
|
||
}, nil
|
||
}
|
||
|
||
// Authenticate VNC认证
|
||
func (c *VNCConnector) Authenticate(ctx context.Context, conn interface{}, cred *base.Credential) error {
|
||
connectionInfo, ok := conn.(map[string]interface{})
|
||
if !ok {
|
||
return fmt.Errorf("无效的连接信息")
|
||
}
|
||
|
||
target := connectionInfo["target"].(string)
|
||
|
||
// 重新连接进行认证测试
|
||
tcpConn, err := common.WrapperTcpWithTimeout("tcp", target, time.Duration(common.Timeout)*time.Second)
|
||
if err != nil {
|
||
return fmt.Errorf("重连VNC失败: %v", err)
|
||
}
|
||
defer tcpConn.Close()
|
||
|
||
// 读取并回应版本
|
||
versionBuf := make([]byte, 12)
|
||
_, err = tcpConn.Read(versionBuf)
|
||
if err != nil {
|
||
return fmt.Errorf("读取版本失败: %v", err)
|
||
}
|
||
|
||
// 发送版本响应
|
||
_, err = tcpConn.Write(versionBuf)
|
||
if err != nil {
|
||
return fmt.Errorf("发送版本响应失败: %v", err)
|
||
}
|
||
|
||
// 读取安全类型
|
||
secTypeBuf := make([]byte, 1)
|
||
_, err = tcpConn.Read(secTypeBuf)
|
||
if err != nil {
|
||
return fmt.Errorf("读取安全类型失败: %v", err)
|
||
}
|
||
|
||
secTypeCount := int(secTypeBuf[0])
|
||
if secTypeCount == 0 {
|
||
return fmt.Errorf("VNC服务器拒绝连接")
|
||
}
|
||
|
||
// 读取安全类型列表
|
||
secTypes := make([]byte, secTypeCount)
|
||
_, err = tcpConn.Read(secTypes)
|
||
if err != nil {
|
||
return fmt.Errorf("读取安全类型列表失败: %v", err)
|
||
}
|
||
|
||
// 检查是否支持无认证 (类型1) 或VNC认证 (类型2)
|
||
var selectedSecType byte = 0
|
||
for _, secType := range secTypes {
|
||
if secType == 1 { // 无认证
|
||
selectedSecType = 1
|
||
break
|
||
} else if secType == 2 { // VNC认证
|
||
selectedSecType = 2
|
||
break
|
||
}
|
||
}
|
||
|
||
if selectedSecType == 0 {
|
||
return fmt.Errorf("不支持的VNC安全类型")
|
||
}
|
||
|
||
// 发送选择的安全类型
|
||
_, err = tcpConn.Write([]byte{selectedSecType})
|
||
if err != nil {
|
||
return fmt.Errorf("发送安全类型失败: %v", err)
|
||
}
|
||
|
||
if selectedSecType == 1 {
|
||
// 无认证模式,直接成功
|
||
common.LogSuccess(fmt.Sprintf("VNC无认证访问成功: %s", target))
|
||
return nil
|
||
} else if selectedSecType == 2 {
|
||
// VNC认证模式,需要密码
|
||
if cred.Password == "" {
|
||
return fmt.Errorf("VNC认证需要密码")
|
||
}
|
||
|
||
// 读取质询
|
||
challenge := make([]byte, 16)
|
||
_, err = tcpConn.Read(challenge)
|
||
if err != nil {
|
||
return fmt.Errorf("读取VNC质询失败: %v", err)
|
||
}
|
||
|
||
// 这里应该实现DES加密,但为了简化,我们只检测是否需要密码
|
||
// 实际实现中需要使用DES加密算法对质询进行加密
|
||
return fmt.Errorf("VNC密码认证需要进一步实现")
|
||
}
|
||
|
||
return fmt.Errorf("未知的安全类型: %d", selectedSecType)
|
||
}
|
||
|
||
// Close 关闭连接
|
||
func (c *VNCConnector) Close(conn interface{}) error {
|
||
// VNC连接器不需要保持长连接
|
||
return nil
|
||
}
|
||
|
||
// GetDefaultCredentials 获取VNC默认凭据
|
||
func (c *VNCConnector) GetDefaultCredentials() []*base.Credential {
|
||
return []*base.Credential{
|
||
{Username: "", Password: ""}, // 无密码
|
||
{Username: "", Password: "admin"},
|
||
{Username: "", Password: "password"},
|
||
{Username: "", Password: "123456"},
|
||
{Username: "", Password: "vnc"},
|
||
{Username: "", Password: "root"},
|
||
}
|
||
}
|
||
|
||
// isValidVNCVersion 检查是否为有效的VNC版本
|
||
func (c *VNCConnector) isValidVNCVersion(version string) bool {
|
||
// VNC版本格式: RFB xxx.yyy\n
|
||
if len(version) < 12 {
|
||
return false
|
||
}
|
||
|
||
return version[:4] == "RFB " && (version[11] == '\n' || version[11] == '\r')
|
||
}
|
||
|
||
// GetSupportedVersions 获取支持的VNC版本
|
||
func (c *VNCConnector) GetSupportedVersions() []string {
|
||
return []string{"RFB 003.003", "RFB 003.007", "RFB 003.008"}
|
||
} |