From c98805e85a8ea4993afb4b3a48a2810002d4f0af Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Mon, 27 Apr 2026 23:27:21 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=85=A8=E9=87=8F=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=20WrapperTcpWithTimeout=20=E4=B8=BA=20session.DialTCP?= =?UTF-8?q?=20(Phase=204)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - core/port_scan.go: EnhancedPortScan/connectWithRetry/scanSinglePort 接入 session - core/service_probe.go: SmartPortInfoScanner 持有 session,重连走 session.DialTCP - core/icmp.go: CheckLive/tcpProbeAlive 接入 session - 17 个 service 插件: 内部 helper 函数全部穿透 ctx+session - 移除插件中冗余的手动 TCP 计数(DialTCP 内部已处理) - plugins/core 下已无 WrapperTcpWithTimeout/SafeTCPDial 调用残留 --- core/alive_scanner.go | 6 +-- core/icmp.go | 20 +++++--- core/port_scan.go | 22 +++++---- core/service_probe.go | 27 +++++----- core/service_probe_strategy_test.go | 2 +- core/service_scanner.go | 20 +++++--- plugins/services/activemq.go | 28 ++++------- plugins/services/findnet.go | 8 +-- plugins/services/ldap.go | 39 ++++++--------- plugins/services/memcached.go | 27 +++++----- plugins/services/mongodb.go | 20 ++++---- plugins/services/ms17010.go | 39 ++++++--------- plugins/services/mysql.go | 8 +-- plugins/services/netbios.go | 8 +-- plugins/services/oracle.go | 6 +-- plugins/services/rabbitmq.go | 18 ++++--- plugins/services/redis.go | 46 ++++++++--------- plugins/services/rsync.go | 42 +++++++--------- plugins/services/smb.go | 18 +++---- plugins/services/smb_protocol.go | 22 ++++----- plugins/services/smtp.go | 76 +++++++++++------------------ plugins/services/ssh.go | 33 ++++++------- plugins/services/telnet.go | 47 ++++++++---------- plugins/services/vnc.go | 23 ++++----- 24 files changed, 266 insertions(+), 339 deletions(-) diff --git a/core/alive_scanner.go b/core/alive_scanner.go index 9062d1c..942476d 100644 --- a/core/alive_scanner.go +++ b/core/alive_scanner.go @@ -62,14 +62,14 @@ func (s *AliveScanStrategy) Execute(_ context.Context, session *common.ScanSessi } // 执行存活探测 - s.performAliveScan(info, session.Config, session.State) + s.performAliveScan(info, session) // 输出统计信息 s.outputStats() } // performAliveScan 执行存活探测 -func (s *AliveScanStrategy) performAliveScan(info common.HostInfo, config *common.Config, state *common.State) { +func (s *AliveScanStrategy) performAliveScan(info common.HostInfo, session *common.ScanSession) { // 解析目标主机 fv := common.GetFlagVars() hosts, err := parsers.ParseIP(info.Host, fv.HostsFile, fv.ExcludeHosts) @@ -90,7 +90,7 @@ func (s *AliveScanStrategy) performAliveScan(info common.HostInfo, config *commo // 执行存活检测 - aliveList := CheckLive(hosts, false, config, state) // 使用ICMP探测 + aliveList := CheckLive(hosts, false, session) // 使用ICMP探测 // 更新统计信息 s.stats.AliveHosts = len(aliveList) diff --git a/core/icmp.go b/core/icmp.go index 8dcaf1c..6aee615 100644 --- a/core/icmp.go +++ b/core/icmp.go @@ -2,6 +2,7 @@ package core import ( "bytes" + "context" "errors" "fmt" "net" @@ -39,7 +40,9 @@ var pingErrorKeywords = []string{ // CheckLive 检测主机存活状态 // 支持 ICMP/Ping 探测,并在响应率过低时自动启用 TCP 补充探测 -func CheckLive(hostslist []string, Ping bool, config *common.Config, state *common.State) []string { +func CheckLive(hostslist []string, Ping bool, session *common.ScanSession) []string { + config := session.Config + state := session.State // 创建局部WaitGroup var livewg sync.WaitGroup @@ -68,7 +71,7 @@ func CheckLive(hostslist []string, Ping bool, config *common.Config, state *comm // TCP 补充探测:当 ICMP/Ping 响应率过低时自动启用 // 这对防火墙过滤 ICMP 的环境特别有用 - aliveHosts = tcpSupplementaryProbe(hostslist, aliveHosts, config) + aliveHosts = tcpSupplementaryProbe(hostslist, aliveHosts, session) // 输出存活统计信息 printAliveStats(aliveHosts, hostslist) @@ -78,7 +81,7 @@ func CheckLive(hostslist []string, Ping bool, config *common.Config, state *comm // tcpSupplementaryProbe TCP 补充探测 // 当 ICMP 响应率过低时(<10%),对未响应主机进行 TCP 探测 -func tcpSupplementaryProbe(allHosts []string, aliveHosts []string, config *common.Config) []string { +func tcpSupplementaryProbe(allHosts []string, aliveHosts []string, session *common.ScanSession) []string { totalHosts := len(allHosts) if totalHosts == 0 { return aliveHosts @@ -102,7 +105,7 @@ func tcpSupplementaryProbe(allHosts []string, aliveHosts []string, config *commo common.LogInfo(i18n.Tr("tcp_probe_low_icmp_rate", fmt.Sprintf("%.1f%%", responseRate*100), len(unrespondedHosts))) // 执行 TCP 补充探测 - tcpAliveHosts := runTcpProbeForHosts(unrespondedHosts, config) + tcpAliveHosts := runTcpProbeForHosts(unrespondedHosts, session) // 合并结果 if len(tcpAliveHosts) > 0 { @@ -682,10 +685,10 @@ const tcpProbeThreshold = 0.1 // 10% // tcpProbeAlive 使用 TCP 探测主机是否存活 // 尝试连接常用端口,任一端口响应即认为存活 -func tcpProbeAlive(host string) bool { +func tcpProbeAlive(session *common.ScanSession, host string) bool { for _, port := range tcpProbeCommonPorts { addr := fmt.Sprintf("%s:%d", host, port) - conn, err := common.WrapperTcpWithTimeout("tcp", addr, tcpProbeTimeout) + conn, err := session.DialTCP(context.Background(), "tcp", addr, tcpProbeTimeout) if err == nil { _ = conn.Close() return true @@ -696,7 +699,8 @@ func tcpProbeAlive(host string) bool { // runTcpProbeForHosts 对指定主机列表进行 TCP 补充探测 // 返回存活的主机列表 -func runTcpProbeForHosts(hosts []string, config *common.Config) []string { +func runTcpProbeForHosts(hosts []string, session *common.ScanSession) []string { + config := session.Config if len(hosts) == 0 { return nil } @@ -722,7 +726,7 @@ func runTcpProbeForHosts(hosts []string, config *common.Config) []string { wg.Done() }() - if tcpProbeAlive(h) { + if tcpProbeAlive(session, h) { mu.Lock() aliveHosts = append(aliveHosts, h) mu.Unlock() diff --git a/core/port_scan.go b/core/port_scan.go index 47b4bc9..64643b4 100644 --- a/core/port_scan.go +++ b/core/port_scan.go @@ -1,6 +1,7 @@ package core import ( + "context" "fmt" "net" "strings" @@ -110,7 +111,9 @@ func (f *failedPortCollector) Count() int { // EnhancedPortScan 高性能端口扫描函数 // 使用滑动窗口调度 + 自适应线程池 + 流式迭代器 -func EnhancedPortScan(hosts []string, ports string, timeout int64, config *common.Config, state *common.State) []string { +func EnhancedPortScan(hosts []string, ports string, timeout int64, session *common.ScanSession) []string { + config := session.Config + state := session.State common.LogDebug(fmt.Sprintf("[PortScan] 开始: %d个主机, 线程数=%d", len(hosts), config.ThreadNum)) // 解析端口和排除端口 @@ -179,7 +182,7 @@ func EnhancedPortScan(hosts []string, ports string, timeout int64, config *commo }() addr := fmt.Sprintf("%s:%d", taskInfo.host, taskInfo.port) - scanSinglePort(taskInfo.host, taskInfo.port, addr, to, &count, collector, failedCollector, config, state) + scanSinglePort(taskInfo.host, taskInfo.port, addr, to, &count, collector, failedCollector, session) common.UpdateProgressBar(1) }, state) if err != nil { @@ -263,11 +266,11 @@ func slidingWindowSchedule(iter *SocketIterator, pool *AdaptivePool, wg *sync.Wa } // connectWithRetry 带重试的TCP连接 - 只对资源耗尽错误重试 -func connectWithRetry(addr string, timeout time.Duration, maxRetries int, state *common.State) (net.Conn, error) { +func connectWithRetry(ctx context.Context, session *common.ScanSession, addr string, timeout time.Duration, maxRetries int) (net.Conn, error) { var lastErr error for attempt := 0; attempt < maxRetries; attempt++ { - conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout) + conn, err := session.DialTCP(ctx, "tcp", addr, timeout) if err == nil { return conn, nil @@ -281,7 +284,7 @@ func connectWithRetry(addr string, timeout time.Duration, maxRetries int, state } // 记录资源耗尽错误 - state.IncrementResourceExhaustedCount() + session.State.IncrementResourceExhaustedCount() // 指数退避:第1次等50ms,第2次等150ms if attempt < maxRetries-1 { @@ -344,9 +347,10 @@ func buildServiceLogMessage(addr string, serviceInfo *ServiceInfo, isWeb bool) s } // scanSinglePort 扫描单个端口并进行服务识别(重构后的简洁版本) -func scanSinglePort(host string, port int, addr string, timeout time.Duration, count *int64, collector *resultCollector, failedCollector *failedPortCollector, config *common.Config, state *common.State) { +func scanSinglePort(host string, port int, addr string, timeout time.Duration, count *int64, collector *resultCollector, failedCollector *failedPortCollector, session *common.ScanSession) { + config := session.Config // 步骤1:建立连接 - conn, err := connectWithRetry(addr, timeout, 3, state) + conn, err := connectWithRetry(context.Background(), session, addr, timeout, 3) if err != nil { handleConnectionFailure(err, host, port, addr, failedCollector) return @@ -365,7 +369,7 @@ func scanSinglePort(host string, port int, addr string, timeout time.Duration, c if common.IsProxyEnabled() && verifyMethod != "direct" { _ = conn.Close() // 重新建立干净的连接用于服务识别 - conn, err = connectWithRetry(addr, timeout, 3, state) + conn, err = connectWithRetry(context.Background(), session, addr, timeout, 3) if err != nil { handleConnectionFailure(err, host, port, addr, failedCollector) return @@ -378,7 +382,7 @@ func scanSinglePort(host string, port int, addr string, timeout time.Duration, c saveOpenPort(host, port) // 步骤3:服务识别(Scanner负责关闭连接,包括探测中可能创建的新连接) - scanner := NewSmartPortInfoScanner(host, port, conn, timeout, config) + scanner := NewSmartPortInfoScanner(host, port, conn, timeout, config, session) defer scanner.Close() serviceInfo, _ := scanner.SmartIdentify() diff --git a/core/service_probe.go b/core/service_probe.go index b2ea612..d93f133 100644 --- a/core/service_probe.go +++ b/core/service_probe.go @@ -1,6 +1,7 @@ package core import ( + "context" "errors" "fmt" "io" @@ -70,13 +71,14 @@ type Service struct { // Info 定义单个端口探测的上下文信息 type Info struct { - Address string // 目标IP地址 - Port int // 目标端口 - Conn net.Conn // 网络连接 - Result Result // 探测结果 - Found bool // 是否成功识别服务 - config *common.Config // 配置引用 - readTimeoutMS int // 当前读取超时时间(毫秒) + Address string // 目标IP地址 + Port int // 目标端口 + Conn net.Conn // 网络连接 + Result Result // 探测结果 + Found bool // 是否成功识别服务 + config *common.Config // 配置引用 + session *common.ScanSession // 会话引用 + readTimeoutMS int // 当前读取超时时间(毫秒) } // SmartPortInfoScanner 智能服务识别器:保持nmap准确性,优化网络交互 @@ -86,24 +88,27 @@ type SmartPortInfoScanner struct { Conn net.Conn Timeout time.Duration info *Info - config *common.Config // 配置引用 + config *common.Config // 配置引用 + session *common.ScanSession // 会话引用 } // 预定义的基础探测器已在PortFinger.go中定义,这里不再重复定义 // NewSmartPortInfoScanner 创建智能服务识别器 -func NewSmartPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration, config *common.Config) *SmartPortInfoScanner { +func NewSmartPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration, config *common.Config, session *common.ScanSession) *SmartPortInfoScanner { return &SmartPortInfoScanner{ Address: addr, Port: port, Conn: conn, Timeout: timeout, config: config, + session: session, info: &Info{ Address: addr, Port: port, Conn: conn, config: config, + session: session, Result: Result{ Service: Service{}, }, @@ -251,7 +256,7 @@ func (s *SmartPortInfoScanner) reconnectIfNeeded() { } // 重新建立连接 - newConn, err := common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%d", s.Address, s.Port), s.Timeout) + newConn, err := s.session.DialTCP(context.Background(), "tcp", fmt.Sprintf("%s:%d", s.Address, s.Port), s.Timeout) if err != nil { return } @@ -511,7 +516,7 @@ func (i *Info) Write(msg []byte) error { _ = oldConn.Close() // 尝试重新连接 - 支持SOCKS5代理 - newConn, retryErr := common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second) + newConn, retryErr := i.session.DialTCP(context.Background(), "tcp", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second) if retryErr != nil { return retryErr } diff --git a/core/service_probe_strategy_test.go b/core/service_probe_strategy_test.go index 3922915..a014dac 100644 --- a/core/service_probe_strategy_test.go +++ b/core/service_probe_strategy_test.go @@ -155,7 +155,7 @@ func TestSmartPortInfoScanner_Creation(t *testing.T) { } // 使用 nil 连接(实际测试中会使用真实连接) - scanner := NewSmartPortInfoScanner("127.0.0.1", 80, nil, 3*time.Second, config) + scanner := NewSmartPortInfoScanner("127.0.0.1", 80, nil, 3*time.Second, config, nil) if scanner == nil { t.Fatal("Scanner 创建失败") diff --git a/core/service_scanner.go b/core/service_scanner.go index cd9122c..ccca3c8 100644 --- a/core/service_scanner.go +++ b/core/service_scanner.go @@ -141,7 +141,7 @@ func (s *ServiceScanStrategy) Execute(ctx context.Context, session *common.ScanS // performHostScan 执行主机扫描的完整流程 func (s *ServiceScanStrategy) performHostScan(ctx context.Context, session *common.ScanSession, info common.HostInfo, ch chan struct{}, wg *sync.WaitGroup) { // 发现目标主机和端口 - targetInfos, err := s.discoverTargets(info.Host, info, session.Config, session.State) + targetInfos, err := s.discoverTargets(info.Host, info, session) if err != nil { common.LogError(err.Error()) return @@ -154,9 +154,9 @@ func (s *ServiceScanStrategy) performHostScan(ctx context.Context, session *comm } // PrepareTargets 准备目标信息 -func (s *ServiceScanStrategy) PrepareTargets(info common.HostInfo, config *common.Config, state *common.State) []common.HostInfo { +func (s *ServiceScanStrategy) PrepareTargets(info common.HostInfo, session *common.ScanSession) []common.HostInfo { // 发现目标主机和端口 - targetInfos, err := s.discoverTargets(info.Host, info, config, state) + targetInfos, err := s.discoverTargets(info.Host, info, session) if err != nil { common.LogError(err.Error()) return nil @@ -215,7 +215,9 @@ func (s *ServiceScanStrategy) LogVulnerabilityPluginInfo(targets []common.HostIn // ============================================================================= // discoverTargets 发现目标主机和端口 -func (s *ServiceScanStrategy) discoverTargets(hostInput string, baseInfo common.HostInfo, config *common.Config, state *common.State) ([]common.HostInfo, error) { +func (s *ServiceScanStrategy) discoverTargets(hostInput string, baseInfo common.HostInfo, session *common.ScanSession) ([]common.HostInfo, error) { + config := session.Config + state := session.State // 标准流程:解析目标主机 fv := common.GetFlagVars() hosts, err := parsers.ParseIP(hostInput, fv.HostsFile, fv.ExcludeHosts) @@ -229,12 +231,12 @@ func (s *ServiceScanStrategy) discoverTargets(hostInput string, baseInfo common. if len(hosts) > 0 || len(state.GetHostPorts()) > 0 { // 主机存活检测 if s.shouldPerformLivenessCheck(hosts, config) { - hosts = CheckLive(hosts, false, config, state) + hosts = CheckLive(hosts, false, session) common.LogInfo(i18n.Tr("alive_hosts_count_info", len(hosts))) } // 端口扫描 - alivePorts := s.discoverAlivePorts(hosts, config, state) + alivePorts := s.discoverAlivePorts(hosts, session) if len(alivePorts) > 0 { targetInfos = s.convertToTargetInfos(alivePorts, baseInfo) } @@ -249,7 +251,9 @@ func (s *ServiceScanStrategy) shouldPerformLivenessCheck(hosts []string, config } // discoverAlivePorts 发现存活的端口 -func (s *ServiceScanStrategy) discoverAlivePorts(hosts []string, config *common.Config, state *common.State) []string { +func (s *ServiceScanStrategy) discoverAlivePorts(hosts []string, session *common.ScanSession) []string { + config := session.Config + state := session.State var alivePorts []string // 如果已经有明确指定的host:port,直接使用(让后续SmartIdentify统一验证和识别) @@ -263,7 +267,7 @@ func (s *ServiceScanStrategy) discoverAlivePorts(hosts []string, config *common. // 根据扫描模式选择端口扫描方式 if len(hosts) > 0 { - alivePorts = EnhancedPortScan(hosts, config.Target.Ports, int64(config.Timeout.Seconds()), config, state) + alivePorts = EnhancedPortScan(hosts, config.Target.Ports, int64(config.Timeout.Seconds()), session) } return alivePorts diff --git a/plugins/services/activemq.go b/plugins/services/activemq.go index d3a2b71..6782074 100644 --- a/plugins/services/activemq.go +++ b/plugins/services/activemq.go @@ -27,11 +27,10 @@ func NewActiveMQPlugin() *ActiveMQPlugin { func (p *ActiveMQPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State target := info.Target() if config.DisableBrute { - return p.identifyService(ctx, info, config, state) + return p.identifyService(ctx, info, session) } // 生成测试凭据 @@ -50,7 +49,7 @@ func (p *ActiveMQPlugin) Scan(ctx context.Context, info *common.HostInfo, sessio } // 使用公共框架进行并发凭据测试 - authFn := p.createAuthFunc(info, config, state) + authFn := p.createAuthFunc(info, session) testConfig := DefaultConcurrentTestConfig(config) result := TestCredentialsConcurrently(ctx, credentials, authFn, "activemq", testConfig) @@ -63,23 +62,23 @@ func (p *ActiveMQPlugin) Scan(ctx context.Context, info *common.HostInfo, sessio } // createAuthFunc 创建ActiveMQ认证函数 -func (p *ActiveMQPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc { +func (p *ActiveMQPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc { return func(ctx context.Context, cred Credential) *AuthResult { - return p.doActiveMQAuth(ctx, info, cred, config, state) + return p.doActiveMQAuth(ctx, info, cred, session) } } // doActiveMQAuth 执行ActiveMQ认证 -func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult { +func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult { target := info.Target() + config := session.Config timeout := config.Timeout resultChan := make(chan *AuthResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout) + conn, err := session.DialTCP(ctx, "tcp", target, timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: classifyActiveMQErrorType(err), @@ -90,7 +89,6 @@ func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostIn success, err := p.authenticateSTOMP(conn, cred.Username, cred.Password, config) if success { - state.IncrementTCPSuccessPacketCount() resultChan <- &AuthResult{ Success: true, Conn: &activeMQConnWrapper{conn}, @@ -101,7 +99,6 @@ func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostIn } _ = conn.Close() - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: classifyActiveMQErrorType(err), @@ -113,7 +110,6 @@ func (p *ActiveMQPlugin) doActiveMQAuth(ctx context.Context, info *common.HostIn case result := <-resultChan: return result case <-ctx.Done(): - // context 被取消,启动清理协程等待并关闭可能创建的连接 go func() { result := <-resultChan if result != nil && result.Conn != nil { @@ -201,13 +197,12 @@ func (p *ActiveMQPlugin) authenticateSTOMP(conn net.Conn, username, password str } // identifyService ActiveMQ服务识别 -func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - timeout := config.Timeout + timeout := session.Config.Timeout - conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout) + conn, err := session.DialTCP(ctx, "tcp", target, timeout) if err != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "activemq", @@ -220,7 +215,6 @@ func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostI _ = conn.SetWriteDeadline(time.Now().Add(timeout)) if _, writeErr := conn.Write([]byte(stompConnect)); writeErr != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "activemq", @@ -232,7 +226,6 @@ func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostI response := make([]byte, 512) n, err := conn.Read(response) if err != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "activemq", @@ -247,7 +240,6 @@ func (p *ActiveMQPlugin) identifyService(ctx context.Context, info *common.HostI } } - state.IncrementTCPSuccessPacketCount() responseStr := string(response[:n]) if common.ContainsAny(responseStr, "CONNECTED", "ERROR") { diff --git a/plugins/services/findnet.go b/plugins/services/findnet.go index 4f1da3e..5bf61a1 100644 --- a/plugins/services/findnet.go +++ b/plugins/services/findnet.go @@ -38,7 +38,6 @@ func NewFindNetPlugin() *FindNetPlugin { // Scan 执行FindNet扫描 - Windows网络信息收集 func (p *FindNetPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State target := info.Target() // 检查是否为RPC端口 @@ -50,10 +49,8 @@ func (p *FindNetPlugin) Scan(ctx context.Context, info *common.HostInfo, session } } - // WrapperTcpWithTimeout内部已包含发包限制检查 - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "findnet", @@ -68,7 +65,6 @@ func (p *FindNetPlugin) Scan(ctx context.Context, info *common.HostInfo, session // 执行RPC网络发现 networkInfo, err := p.performNetworkDiscovery(conn) if err != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "findnet", @@ -76,8 +72,6 @@ func (p *FindNetPlugin) Scan(ctx context.Context, info *common.HostInfo, session } } - state.IncrementTCPSuccessPacketCount() - // 记录发现的网络信息 (一次性输出,避免被其他日志打断) if networkInfo.Valid { var lines []string diff --git a/plugins/services/ldap.go b/plugins/services/ldap.go index 5e44ef8..1de9c9f 100644 --- a/plugins/services/ldap.go +++ b/plugins/services/ldap.go @@ -25,16 +25,15 @@ func NewLDAPPlugin() *LDAPPlugin { func (p *LDAPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State if config.DisableBrute { - return p.identifyService(ctx, info, config, state) + return p.identifyService(ctx, info, session) } target := info.Target() // Hash 认证优先:检查是否配置了 Hash 和 Domain if len(config.Credentials.HashValues) > 0 && config.Credentials.Domain != "" { - result := p.tryHashAuth(ctx, info, config, state) + result := p.tryHashAuth(ctx, info, session) if result != nil && result.Success { return result } @@ -50,7 +49,7 @@ func (p *LDAPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c } // 使用公共框架进行并发凭据测试 - authFn := p.createAuthFunc(info, config, state) + authFn := p.createAuthFunc(info, session) testConfig := DefaultConcurrentTestConfig(config) result := TestCredentialsConcurrently(ctx, credentials, authFn, "ldap", testConfig) @@ -63,24 +62,22 @@ func (p *LDAPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c } // createAuthFunc 创建LDAP认证函数 -func (p *LDAPPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc { +func (p *LDAPPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc { return func(ctx context.Context, cred Credential) *AuthResult { - return p.doLDAPAuth(ctx, info, cred, config, state) + return p.doLDAPAuth(ctx, info, cred, session) } } // doLDAPAuth 执行LDAP认证 -func (p *LDAPPlugin) doLDAPAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult { - conn, err := p.connectLDAP(ctx, info, config) +func (p *LDAPPlugin) doLDAPAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult { + conn, err := p.connectLDAP(ctx, info, session) if err != nil { - state.IncrementTCPFailedPacketCount() return &AuthResult{ Success: false, ErrorType: classifyLDAPErrorType(err), Error: err, } } - state.IncrementTCPSuccessPacketCount() // 尝试多种DN格式进行绑定测试 dnFormats := []string{ @@ -119,7 +116,8 @@ func (w *ldapConnWrapper) Close() error { } // tryHashAuth 尝试 NTLM Hash 认证 -func (p *LDAPPlugin) tryHashAuth(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *LDAPPlugin) tryHashAuth(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { + config := session.Config target := info.Target() domain := config.Credentials.Domain users := config.Credentials.Userdict["ldap"] @@ -141,7 +139,7 @@ func (p *LDAPPlugin) tryHashAuth(ctx context.Context, info *common.HostInfo, con default: } - result := p.doNTLMHashAuth(ctx, info, domain, user, hash, config, state) + result := p.doNTLMHashAuth(ctx, info, domain, user, hash, session) if result.Success { // 截断 hash 用于显示 displayHash := hash @@ -164,17 +162,15 @@ func (p *LDAPPlugin) tryHashAuth(ctx context.Context, info *common.HostInfo, con } // doNTLMHashAuth 执行单次 NTLM Hash 认证 -func (p *LDAPPlugin) doNTLMHashAuth(ctx context.Context, info *common.HostInfo, domain, username, hash string, config *common.Config, state *common.State) *AuthResult { - conn, err := p.connectLDAP(ctx, info, config) +func (p *LDAPPlugin) doNTLMHashAuth(ctx context.Context, info *common.HostInfo, domain, username, hash string, session *common.ScanSession) *AuthResult { + conn, err := p.connectLDAP(ctx, info, session) if err != nil { - state.IncrementTCPFailedPacketCount() return &AuthResult{ Success: false, ErrorType: classifyLDAPErrorType(err), Error: err, } } - state.IncrementTCPSuccessPacketCount() if err := conn.NTLMBindWithHash(domain, username, hash); err == nil { return &AuthResult{ @@ -194,7 +190,7 @@ func (p *LDAPPlugin) doNTLMHashAuth(ctx context.Context, info *common.HostInfo, } // connectLDAP 连接LDAP服务器 -func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, config *common.Config) (*ldaplib.Conn, error) { +func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, session *common.ScanSession) (*ldaplib.Conn, error) { target := info.Target() type result struct { @@ -204,7 +200,7 @@ func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, con resultChan := make(chan result, 1) go func() { - tcpConn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + tcpConn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { resultChan <- result{nil, err} return @@ -225,7 +221,6 @@ func (p *LDAPPlugin) connectLDAP(ctx context.Context, info *common.HostInfo, con case res := <-resultChan: return res.conn, res.err case <-ctx.Done(): - // context 被取消,启动清理协程等待并关闭可能创建的连接 go func() { res := <-resultChan if res.conn != nil { @@ -259,19 +254,17 @@ func classifyLDAPErrorType(err error) ErrorType { return ClassifyError(err, ldapAuthErrors, ldapNetworkErrors) } -func (p *LDAPPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *LDAPPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - conn, err := p.connectLDAP(ctx, info, config) + conn, err := p.connectLDAP(ctx, info, session) if err != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "ldap", Error: err, } } - state.IncrementTCPSuccessPacketCount() defer func() { _ = conn.Close() }() banner := "LDAP" diff --git a/plugins/services/memcached.go b/plugins/services/memcached.go index 3160767..be6800b 100644 --- a/plugins/services/memcached.go +++ b/plugins/services/memcached.go @@ -26,15 +26,14 @@ func NewMemcachedPlugin() *MemcachedPlugin { func (p *MemcachedPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State target := info.Target() if config.DisableBrute { - return p.identifyService(ctx, info, config, state) + return p.identifyService(ctx, info, session) } // 检测未授权访问 - if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success { + if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success { common.LogVuln(i18n.Tr("memcached_unauth", target)) return result } @@ -48,14 +47,14 @@ func (p *MemcachedPlugin) Scan(ctx context.Context, info *common.HostInfo, sessi } // testUnauthorizedAccess 测试Memcached未授权访问 -func (p *MemcachedPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { - conn := p.connectToMemcached(ctx, info, config, state) +func (p *MemcachedPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { + conn := p.connectToMemcached(ctx, info, session) if conn == nil { return nil } defer func() { _ = conn.Close() }() - if p.testBasicCommand(conn, config) { + if p.testBasicCommand(conn, session.Config) { return &ScanResult{ Type: plugins.ResultTypeVuln, Success: true, @@ -67,20 +66,19 @@ func (p *MemcachedPlugin) testUnauthorizedAccess(ctx context.Context, info *comm return nil } -func (p *MemcachedPlugin) connectToMemcached(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) net.Conn { +func (p *MemcachedPlugin) connectToMemcached(ctx context.Context, info *common.HostInfo, session *common.ScanSession) net.Conn { target := info.Target() + timeout := session.Config.Timeout connChan := make(chan net.Conn, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, timeout) if err != nil { - state.IncrementTCPFailedPacketCount() connChan <- nil return } - state.IncrementTCPSuccessPacketCount() - _ = conn.SetDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetDeadline(time.Now().Add(timeout)) connChan <- conn }() @@ -88,7 +86,6 @@ func (p *MemcachedPlugin) connectToMemcached(ctx context.Context, info *common.H case conn := <-connChan: return conn case <-ctx.Done(): - // context 被取消,启动清理协程等待并关闭可能创建的连接 go func() { conn := <-connChan if conn != nil { @@ -116,10 +113,10 @@ func (p *MemcachedPlugin) testBasicCommand(conn net.Conn, config *common.Config) return common.ContainsAny(responseStr, "VERSION", "memcached") } -func (p *MemcachedPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *MemcachedPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - conn := p.connectToMemcached(ctx, info, config, state) + conn := p.connectToMemcached(ctx, info, session) if conn == nil { return &ScanResult{ Success: false, @@ -129,7 +126,7 @@ func (p *MemcachedPlugin) identifyService(ctx context.Context, info *common.Host } defer func() { _ = conn.Close() }() - if p.testBasicCommand(conn, config) { + if p.testBasicCommand(conn, session.Config) { banner := "Memcached" common.LogSuccess(i18n.Tr("memcached_service", target, banner)) return &ScanResult{ diff --git a/plugins/services/mongodb.go b/plugins/services/mongodb.go index d4074e0..f3f3f41 100644 --- a/plugins/services/mongodb.go +++ b/plugins/services/mongodb.go @@ -34,11 +34,11 @@ func (p *MongoDBPlugin) Scan(ctx context.Context, info *common.HostInfo, session target := info.Target() if config.DisableBrute { - return p.identifyService(ctx, info, config) + return p.identifyService(ctx, info, session) } // 首先检测未授权访问 - isUnauth, err := p.mongodbUnauth(ctx, info, config) + isUnauth, err := p.mongodbUnauth(ctx, info, session) if err != nil { return &ScanResult{ Success: false, @@ -184,10 +184,10 @@ func classifyMongoDBErrorType(err error) ErrorType { return ClassifyError(err, mongoAuthErrors, mongoNetworkErrors) } -func (p *MongoDBPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config) *ScanResult { +func (p *MongoDBPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - isUnauth, err := p.mongodbUnauth(ctx, info, config) + isUnauth, err := p.mongodbUnauth(ctx, info, session) if err != nil { return &ScanResult{ Success: false, @@ -216,14 +216,14 @@ func (p *MongoDBPlugin) identifyService(ctx context.Context, info *common.HostIn } // mongodbUnauth 检测MongoDB未授权访问 -func (p *MongoDBPlugin) mongodbUnauth(ctx context.Context, info *common.HostInfo, config *common.Config) (bool, error) { +func (p *MongoDBPlugin) mongodbUnauth(ctx context.Context, info *common.HostInfo, session *common.ScanSession) (bool, error) { msgPacket := p.createOpMsgPacket() queryPacket := p.createOpQueryPacket() realhost := fmt.Sprintf("%s:%d", info.Host, info.Port) - reply, err := p.checkMongoAuth(ctx, realhost, msgPacket, config) + reply, err := p.checkMongoAuth(ctx, realhost, msgPacket, session) if err != nil { - reply, err = p.checkMongoAuth(ctx, realhost, queryPacket, config) + reply, err = p.checkMongoAuth(ctx, realhost, queryPacket, session) if err != nil { return false, err } @@ -241,8 +241,8 @@ func (p *MongoDBPlugin) mongodbUnauth(ctx context.Context, info *common.HostInfo } // checkMongoAuth 检查MongoDB认证状态 -func (p *MongoDBPlugin) checkMongoAuth(ctx context.Context, address string, packet []byte, config *common.Config) (string, error) { - conn, err := common.WrapperTcpWithTimeout("tcp", address, config.Timeout) +func (p *MongoDBPlugin) checkMongoAuth(ctx context.Context, address string, packet []byte, session *common.ScanSession) (string, error) { + conn, err := session.DialTCP(ctx, "tcp", address, session.Config.Timeout) if err != nil { return "", fmt.Errorf("连接失败: %w", err) } @@ -254,7 +254,7 @@ func (p *MongoDBPlugin) checkMongoAuth(ctx context.Context, address string, pack default: } - if deadlineErr := conn.SetDeadline(time.Now().Add(config.Timeout)); deadlineErr != nil { + if deadlineErr := conn.SetDeadline(time.Now().Add(session.Config.Timeout)); deadlineErr != nil { return "", fmt.Errorf("设置超时失败: %w", deadlineErr) } diff --git a/plugins/services/ms17010.go b/plugins/services/ms17010.go index dd773bb..a8949f0 100644 --- a/plugins/services/ms17010.go +++ b/plugins/services/ms17010.go @@ -36,7 +36,6 @@ func NewMS17010Plugin() *MS17010Plugin { // Scan 执行MS17-010扫描 func (p *MS17010Plugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State // 如果禁用暴力破解,也禁用漏洞检测 if config.DisableBrute { return &ScanResult{ @@ -58,7 +57,7 @@ func (p *MS17010Plugin) Scan(ctx context.Context, info *common.HostInfo, session } // 执行MS17010漏洞检测 - vulnerable, osVersion, err := p.checkMS17010Vulnerability(info.Host, config, state) + vulnerable, osVersion, err := p.checkMS17010Vulnerability(ctx, info.Host, session) if err != nil { return &ScanResult{ Success: false, @@ -90,7 +89,8 @@ func (p *MS17010Plugin) Scan(ctx context.Context, info *common.HostInfo, session } // Exploit 执行MS17-010漏洞利用 -func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, creds Credential, config *common.Config) *ExploitResult { +func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, creds Credential, session *common.ScanSession) *ExploitResult { + config := session.Config target := info.Target() common.LogSuccess(i18n.Tr("ms17010_start", target)) @@ -98,7 +98,7 @@ func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, cred output.WriteString(fmt.Sprintf("=== MS17-010漏洞利用结果 - %s ===\n", target)) // 首先确认漏洞存在 - vulnerable, osVersion, err := p.checkMS17010Vulnerability(info.Host, config, nil) + vulnerable, osVersion, err := p.checkMS17010Vulnerability(ctx, info.Host, session) if err != nil { output.WriteString(fmt.Sprintf("\n[漏洞检测失败] %v\n", err)) return &ExploitResult{ @@ -123,7 +123,7 @@ func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, cred } // 检测DOUBLEPULSAR后门 - hasBackdoor := p.checkDoublePulsar(info.Host, config) + hasBackdoor := p.checkDoublePulsar(ctx, info.Host, session) if hasBackdoor { output.WriteString("\n[后门检测] ⚠️ 发现DOUBLEPULSAR后门\n") } else { @@ -136,7 +136,7 @@ func (p *MS17010Plugin) Exploit(ctx context.Context, info *common.HostInfo, cred output.WriteString("[利用状态] 开始执行EternalBlue攻击...\n") // 执行实际的MS17010利用 - err = p.executeMS17010Exploit(info, config) + err = p.executeMS17010Exploit(info, session) if err != nil { output.WriteString(fmt.Sprintf("[利用结果] ❌ 利用失败: %v\n", err)) return &ExploitResult{ @@ -284,18 +284,14 @@ func init() { } // checkMS17010Vulnerability 检测MS17-010漏洞 (从原始MS17010.go复制和适配) -func (p *MS17010Plugin) checkMS17010Vulnerability(ip string, config *common.Config, state *common.State) (bool, string, error) { - // 使用统一TCP包装器,支持代理和限流 - conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", config.Timeout) +func (p *MS17010Plugin) checkMS17010Vulnerability(ctx context.Context, ip string, session *common.ScanSession) (bool, string, error) { + conn, err := session.DialTCP(ctx, "tcp", ip+":445", session.Config.Timeout) if err != nil { - if state != nil { - state.IncrementTCPFailedPacketCount() - } return false, "", fmt.Errorf("连接错误: %w", err) } defer func() { _ = conn.Close() }() - if err = conn.SetDeadline(time.Now().Add(config.Timeout)); err != nil { + if err = conn.SetDeadline(time.Now().Add(session.Config.Timeout)); err != nil { return false, "", fmt.Errorf("设置超时错误: %w", err) } @@ -383,29 +379,22 @@ func (p *MS17010Plugin) checkMS17010Vulnerability(ip string, config *common.Conf // 漏洞检测 - 关键检查点 if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 { - if state != nil { - state.IncrementTCPSuccessPacketCount() - } return true, osVersion, nil } - if state != nil { - state.IncrementTCPSuccessPacketCount() - } return false, osVersion, nil } // checkDoublePulsar 检测DOUBLEPULSAR后门 -func (p *MS17010Plugin) checkDoublePulsar(ip string, config *common.Config) bool { - // 使用统一TCP包装器,支持代理和限流 - conn, err := common.WrapperTcpWithTimeout("tcp", ip+":445", config.Timeout) +func (p *MS17010Plugin) checkDoublePulsar(ctx context.Context, ip string, session *common.ScanSession) bool { + conn, err := session.DialTCP(ctx, "tcp", ip+":445", session.Config.Timeout) if err != nil { return false } defer func() { _ = conn.Close() }() // 简化的后门检测逻辑 - vulnerable, _, err := p.checkMS17010Vulnerability(ip, config, nil) + vulnerable, _, err := p.checkMS17010Vulnerability(ctx, ip, session) if err != nil || !vulnerable { return false } @@ -416,8 +405,8 @@ func (p *MS17010Plugin) checkDoublePulsar(ip string, config *common.Config) bool } // executeMS17010Exploit 执行MS17010漏洞利用 (简化版,保留接口) -func (p *MS17010Plugin) executeMS17010Exploit(info *common.HostInfo, config *common.Config) error { - // address := info.Host + ":445" // 暂时不使用,为了保持原始复杂度 +func (p *MS17010Plugin) executeMS17010Exploit(info *common.HostInfo, session *common.ScanSession) error { + config := session.Config var sc string // 根据不同类型选择shellcode (从MS17010-Exp.go复制) diff --git a/plugins/services/mysql.go b/plugins/services/mysql.go index 892d4c5..6b6a668 100644 --- a/plugins/services/mysql.go +++ b/plugins/services/mysql.go @@ -40,7 +40,7 @@ func (p *MySQLPlugin) Scan(ctx context.Context, info *common.HostInfo, session * config := session.Config state := session.State if config.DisableBrute { - return p.identifyService(info, config) + return p.identifyService(ctx, info, session) } credentials := GenerateCredentials("mysql", config) @@ -139,10 +139,10 @@ func classifyMySQLErrorType(err error) ErrorType { return ClassifyError(err, mysqlAuthErrors, mysqlNetworkErrors) } -func (p *MySQLPlugin) identifyService(info *common.HostInfo, config *common.Config) *ScanResult { +func (p *MySQLPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - conn, err := common.SafeTCPDial(target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { return &ScanResult{ Success: false, @@ -152,7 +152,7 @@ func (p *MySQLPlugin) identifyService(info *common.HostInfo, config *common.Conf } defer func() { _ = conn.Close() }() - if banner := p.readMySQLBanner(conn, config); banner != "" { + if banner := p.readMySQLBanner(conn, session.Config); banner != "" { common.LogSuccess(i18n.Tr("mysql_service", target, banner)) return &ScanResult{ Type: plugins.ResultTypeService, diff --git a/plugins/services/netbios.go b/plugins/services/netbios.go index 2e8423b..3165acb 100644 --- a/plugins/services/netbios.go +++ b/plugins/services/netbios.go @@ -51,7 +51,7 @@ func (p *NetBIOSPlugin) Scan(ctx context.Context, info *common.HostInfo, session netbiosInfo, err = p.queryNetBIOSNames(info.Host, config, state) } else { // TCP端口139 - NetBIOS会话服务 - netbiosInfo, err = p.queryNetBIOSSession(info.Host, config) + netbiosInfo, err = p.queryNetBIOSSession(ctx, info.Host, session) } if err != nil { @@ -186,16 +186,16 @@ func (p *NetBIOSPlugin) queryNetBIOSNames(host string, config *common.Config, st } // queryNetBIOSSession 查询NetBIOS会话服务(TCP 139) -func (p *NetBIOSPlugin) queryNetBIOSSession(host string, config *common.Config) (*NetBIOSInfo, error) { +func (p *NetBIOSPlugin) queryNetBIOSSession(ctx context.Context, host string, session *common.ScanSession) (*NetBIOSInfo, error) { target := fmt.Sprintf("%s:139", host) - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { return nil, fmt.Errorf("连接NetBIOS会话服务失败: %w", err) } defer func() { _ = conn.Close() }() - _ = conn.SetDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetDeadline(time.Now().Add(session.Config.Timeout)) // 发送SMB协商数据包 smbNegotiate1 := []byte{ diff --git a/plugins/services/oracle.go b/plugins/services/oracle.go index fa80398..386021f 100644 --- a/plugins/services/oracle.go +++ b/plugins/services/oracle.go @@ -30,7 +30,7 @@ func (p *OraclePlugin) Scan(ctx context.Context, info *common.HostInfo, session target := info.Target() if config.DisableBrute { - return p.identifyService(ctx, info, config, state) + return p.identifyService(ctx, info, session) } // 先测试未授权访问 @@ -180,10 +180,10 @@ func (p *OraclePlugin) testUnauthorizedAccess(ctx context.Context, info *common. return nil } -func (p *OraclePlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *OraclePlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { return &ScanResult{ Success: false, diff --git a/plugins/services/rabbitmq.go b/plugins/services/rabbitmq.go index 7329f19..b2dbf41 100644 --- a/plugins/services/rabbitmq.go +++ b/plugins/services/rabbitmq.go @@ -32,7 +32,7 @@ func (p *RabbitMQPlugin) Scan(ctx context.Context, info *common.HostInfo, sessio target := info.Target() if config.DisableBrute { - return p.identifyService(ctx, info, config, state) + return p.identifyService(ctx, info, session) } // 先检测未授权访问 @@ -211,16 +211,16 @@ func (p *RabbitMQPlugin) testUnauthorizedAccess(ctx context.Context, info *commo } // testAMQPProtocol 检测AMQP协议 -func (p *RabbitMQPlugin) testAMQPProtocol(ctx context.Context, info *common.HostInfo, config *common.Config) *ScanResult { +func (p *RabbitMQPlugin) testAMQPProtocol(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { return nil } defer func() { _ = conn.Close() }() - _ = conn.SetDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetDeadline(time.Now().Add(session.Config.Timeout)) // 发送AMQP协议头 amqpHeader := []byte{0x41, 0x4d, 0x51, 0x50, 0x00, 0x00, 0x09, 0x01} @@ -249,19 +249,21 @@ func (p *RabbitMQPlugin) testAMQPProtocol(ctx context.Context, info *common.Host return nil } -func (p *RabbitMQPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *RabbitMQPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { // 对于AMQP端口,检测AMQP协议 if info.Port == 5672 || info.Port == 5671 { - if result := p.testAMQPProtocol(ctx, info, config); result != nil && result.Success { + if result := p.testAMQPProtocol(ctx, info, session); result != nil && result.Success { return result } } // 检测HTTP管理界面 - return p.testManagementInterface(ctx, info, config, state) + return p.testManagementInterface(ctx, info, session) } -func (p *RabbitMQPlugin) testManagementInterface(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *RabbitMQPlugin) testManagementInterface(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { + config := session.Config + state := session.State target := info.Target() baseURL := fmt.Sprintf("http://%s:%d", info.Host, info.Port) diff --git a/plugins/services/redis.go b/plugins/services/redis.go index dd2b842..2ab5cd0 100644 --- a/plugins/services/redis.go +++ b/plugins/services/redis.go @@ -33,21 +33,20 @@ func NewRedisPlugin() *RedisPlugin { // Scan 执行Redis扫描 func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State target := info.Target() // 如果禁用暴力破解,只做服务识别 if config.DisableBrute { - return p.identifyService(ctx, info, config, state) + return p.identifyService(ctx, info, session) } // 首先检查未授权访问 - if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success { + if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success { common.LogVuln(i18n.Tr("redis_unauth_success", target)) //nolint:govet // 如果需要利用,重新建立连接执行 if p.shouldExploit(config) { - p.exploitWithPassword(ctx, info, "", config) + p.exploitWithPassword(ctx, info, "", session) } return result } @@ -56,7 +55,7 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session * credentials := GenerateCredentials("redis", config) // 使用公共框架进行并发凭据测试 - authFn := p.createAuthFunc(info, config, state) + authFn := p.createAuthFunc(info, session) testConfig := DefaultConcurrentTestConfig(config) testConfig.Concurrency = 20 // Redis 默认并发度更高 @@ -68,7 +67,7 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session * // 如果需要利用,重新建立连接执行 if p.shouldExploit(config) { - p.exploitWithPassword(ctx, info, result.Password, config) + p.exploitWithPassword(ctx, info, result.Password, session) } } @@ -76,21 +75,20 @@ func (p *RedisPlugin) Scan(ctx context.Context, info *common.HostInfo, session * } // createAuthFunc 创建Redis认证函数 -func (p *RedisPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc { +func (p *RedisPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc { return func(ctx context.Context, cred Credential) *AuthResult { - return p.doRedisAuth(ctx, info, cred, config, state) + return p.doRedisAuth(ctx, info, cred, session) } } // doRedisAuth 执行Redis认证 -func (p *RedisPlugin) doRedisAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult { +func (p *RedisPlugin) doRedisAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult { target := info.Target() - timeout := config.Timeout + timeout := session.Config.Timeout // 建立TCP连接 - conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout) + conn, err := session.DialTCP(ctx, "tcp", target, timeout) if err != nil { - state.IncrementTCPFailedPacketCount() return &AuthResult{ Success: false, ErrorType: classifyRedisErrorType(err), @@ -169,7 +167,6 @@ func (p *RedisPlugin) doRedisAuth(ctx context.Context, info *common.HostInfo, cr responseStr := string(response[:n]) if !strings.Contains(responseStr, "PONG") { _ = conn.Close() - state.IncrementTCPFailedPacketCount() return &AuthResult{ Success: false, ErrorType: ErrorTypeUnknown, @@ -177,7 +174,6 @@ func (p *RedisPlugin) doRedisAuth(ctx context.Context, info *common.HostInfo, cr } } - state.IncrementTCPSuccessPacketCount() return &AuthResult{ Success: true, Conn: conn, @@ -204,10 +200,10 @@ func classifyRedisErrorType(err error) ErrorType { } // testUnauthorizedAccess 测试未授权访问 -func (p *RedisPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *RedisPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { emptyCred := Credential{Username: "", Password: ""} - result := p.doRedisAuth(ctx, info, emptyCred, config, state) + result := p.doRedisAuth(ctx, info, emptyCred, session) if result.Success { if result.Conn != nil { _ = result.Conn.Close() @@ -224,10 +220,10 @@ func (p *RedisPlugin) testUnauthorizedAccess(ctx context.Context, info *common.H } // exploitWithPassword 使用指定密码建立连接并执行利用 -func (p *RedisPlugin) exploitWithPassword(ctx context.Context, info *common.HostInfo, password string, config *common.Config) { +func (p *RedisPlugin) exploitWithPassword(ctx context.Context, info *common.HostInfo, password string, session *common.ScanSession) { target := info.Target() - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { common.LogError(i18n.Tr("redis_reconnect_failed", err)) return @@ -237,28 +233,27 @@ func (p *RedisPlugin) exploitWithPassword(ctx context.Context, info *common.Host // 如果有密码,先认证 if password != "" { authCmd := fmt.Sprintf("AUTH %s\r\n", password) - _ = conn.SetWriteDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetWriteDeadline(time.Now().Add(session.Config.Timeout)) if _, writeErr := conn.Write([]byte(authCmd)); writeErr != nil { return } - _ = conn.SetReadDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetReadDeadline(time.Now().Add(session.Config.Timeout)) response := make([]byte, 512) if _, readErr := conn.Read(response); readErr != nil { return } } - p.exploit(ctx, info, conn, password, config) + p.exploit(ctx, info, conn, password, session.Config) } // identifyService 服务识别 -func (p *RedisPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *RedisPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - timeout := config.Timeout + timeout := session.Config.Timeout - conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout) + conn, err := session.DialTCP(ctx, "tcp", target, timeout) if err != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "redis", @@ -302,7 +297,6 @@ func (p *RedisPlugin) identifyService(ctx context.Context, info *common.HostInfo banner = "Redis服务" } - state.IncrementTCPSuccessPacketCount() common.LogSuccess(i18n.Tr("redis_service_identified", target, banner)) //nolint:govet return &ScanResult{ diff --git a/plugins/services/rsync.go b/plugins/services/rsync.go index b63fe52..3bd66d2 100644 --- a/plugins/services/rsync.go +++ b/plugins/services/rsync.go @@ -30,17 +30,16 @@ func NewRsyncPlugin() *RsyncPlugin { func (p *RsyncPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State target := info.Target() if config.DisableBrute { - return p.identifyService(ctx, info, config, state) + return p.identifyService(ctx, info, session) } var findings []string // 检测未授权访问 - if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success { + if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success { common.LogSuccess(i18n.Tr("rsync_service", target, result.Banner)) findings = append(findings, result.Banner) } @@ -70,7 +69,7 @@ func (p *RsyncPlugin) Scan(ctx context.Context, info *common.HostInfo, session * } // 使用公共框架进行并发凭据测试 - authFn := p.createAuthFunc(info, config, state) + authFn := p.createAuthFunc(info, session) testConfig := DefaultConcurrentTestConfig(config) result := TestCredentialsConcurrently(ctx, creds, authFn, "rsync", testConfig) @@ -97,16 +96,16 @@ func (p *RsyncPlugin) Scan(ctx context.Context, info *common.HostInfo, session * } // createAuthFunc 创建Rsync认证函数 -func (p *RsyncPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc { +func (p *RsyncPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc { return func(ctx context.Context, cred Credential) *AuthResult { - return p.doRsyncAuth(ctx, info, cred, config, state) + return p.doRsyncAuth(ctx, info, cred, session) } } // doRsyncAuth 执行Rsync认证 -func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult { +func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult { // 先获取可用模块列表 - conn := p.connectToRsync(ctx, info, config, state) + conn := p.connectToRsync(ctx, info, session) if conn == nil { return &AuthResult{ Success: false, @@ -114,7 +113,7 @@ func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cr Error: fmt.Errorf("无法连接到Rsync服务"), } } - modules := p.getModules(conn, config) + modules := p.getModules(conn, session.Config) _ = conn.Close() if len(modules) == 0 { @@ -142,7 +141,6 @@ func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cr ) if err != nil { - state.IncrementTCPFailedPacketCount() errMsg := err.Error() if common.ContainsAny(errMsg, "auth", "password") { return &AuthResult{ @@ -158,7 +156,6 @@ func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cr } } - state.IncrementTCPSuccessPacketCount() return &AuthResult{ Success: true, Conn: &rsyncConnWrapper{}, @@ -208,14 +205,14 @@ func classifyRsyncErrorType(err error) ErrorType { } // testUnauthorizedAccess 测试未授权访问 -func (p *RsyncPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { - conn := p.connectToRsync(ctx, info, config, state) +func (p *RsyncPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { + conn := p.connectToRsync(ctx, info, session) if conn == nil { return nil } defer func() { _ = conn.Close() }() - modules := p.getModules(conn, config) + modules := p.getModules(conn, session.Config) if len(modules) > 0 { banner := fmt.Sprintf("未授权访问 - 可用模块: %s", strings.Join(modules, ", ")) @@ -231,22 +228,18 @@ func (p *RsyncPlugin) testUnauthorizedAccess(ctx context.Context, info *common.H } // connectToRsync 连接到Rsync服务 -func (p *RsyncPlugin) connectToRsync(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) net.Conn { +func (p *RsyncPlugin) connectToRsync(ctx context.Context, info *common.HostInfo, session *common.ScanSession) net.Conn { target := info.Target() + timeout := session.Config.Timeout connChan := make(chan net.Conn, 1) go func() { - timeout := config.Timeout - - conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout) + conn, err := session.DialTCP(ctx, "tcp", target, timeout) if err != nil { - state.IncrementTCPFailedPacketCount() connChan <- nil return } - - state.IncrementTCPSuccessPacketCount() _ = conn.SetDeadline(time.Now().Add(timeout)) connChan <- conn }() @@ -255,7 +248,6 @@ func (p *RsyncPlugin) connectToRsync(ctx context.Context, info *common.HostInfo, case conn := <-connChan: return conn case <-ctx.Done(): - // context 被取消,启动清理协程等待并关闭可能创建的连接 go func() { conn := <-connChan if conn != nil { @@ -328,10 +320,10 @@ func (p *RsyncPlugin) getModules(conn net.Conn, config *common.Config) []string } // identifyService Rsync服务识别 -func (p *RsyncPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *RsyncPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - conn := p.connectToRsync(ctx, info, config, state) + conn := p.connectToRsync(ctx, info, session) if conn == nil { return &ScanResult{ Success: false, @@ -341,7 +333,7 @@ func (p *RsyncPlugin) identifyService(ctx context.Context, info *common.HostInfo } defer func() { _ = conn.Close() }() - timeout := config.Timeout + timeout := session.Config.Timeout _ = conn.SetWriteDeadline(time.Now().Add(timeout)) if _, err := conn.Write([]byte("\n")); err != nil { diff --git a/plugins/services/smb.go b/plugins/services/smb.go index 278b90d..9d69b75 100644 --- a/plugins/services/smb.go +++ b/plugins/services/smb.go @@ -39,23 +39,21 @@ func (p *SmbPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co } // 1. 协议探测和信息收集 - smbTarget, err := probeTarget(info.Host, info.Port, config.Timeout) + smbTarget, err := probeTarget(ctx, info.Host, info.Port, config.Timeout, session) if err != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "smb", Error: fmt.Errorf("SMB协议探测失败: %w", err), } } - state.IncrementTCPSuccessPacketCount() // 输出信息收集结果 p.logSMBInfo(target, smbTarget) // 2. 漏洞检测 (仅SMBv2+且端口445) if smbTarget.Protocol == SMBProtocol2 && info.Port == 445 { - if checkSMBGhost(info.Host, config.Timeout) { + if checkSMBGhost(ctx, info.Host, config.Timeout, session) { smbTarget.Vulnerable = &SMBVuln{CVE20200796: true} common.LogVuln(i18n.Tr("smbghost_vuln", target)) } @@ -92,7 +90,7 @@ func (p *SmbPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co creds[i] = Credential{Username: c.Username, Password: c.Password} } - authFn := p.createAuthFunc(info, auth, config, state) + authFn := p.createAuthFunc(info, auth, session) testConfig := DefaultConcurrentTestConfig(config) result := TestCredentialsConcurrently(ctx, creds, authFn, "smb", testConfig) @@ -119,14 +117,10 @@ func (p *SmbPlugin) getAuthenticator(protocol SMBProtocol) SMBAuthenticator { } // createAuthFunc 创建认证函数 -func (p *SmbPlugin) createAuthFunc(info *common.HostInfo, auth SMBAuthenticator, config *common.Config, state *common.State) AuthFunc { +func (p *SmbPlugin) createAuthFunc(info *common.HostInfo, auth SMBAuthenticator, session *common.ScanSession) AuthFunc { + config := session.Config return func(ctx context.Context, cred Credential) *AuthResult { - result, _ := auth.Authenticate(ctx, info.Host, info.Port, cred, config.Credentials.Domain, config.Timeout) - if result.Success { - state.IncrementTCPSuccessPacketCount() - } else { - state.IncrementTCPFailedPacketCount() - } + result, _ := auth.Authenticate(ctx, info.Host, info.Port, cred, config.Credentials.Domain, config.Timeout, session) return result } } diff --git a/plugins/services/smb_protocol.go b/plugins/services/smb_protocol.go index 2f0e96c..1131054 100644 --- a/plugins/services/smb_protocol.go +++ b/plugins/services/smb_protocol.go @@ -201,10 +201,10 @@ var ( ) // probeTarget 探测目标SMB信息(协议版本、系统信息) -func probeTarget(host string, port int, timeout time.Duration) (*SMBTarget, error) { +func probeTarget(ctx context.Context, host string, port int, timeout time.Duration, session *common.ScanSession) (*SMBTarget, error) { target := fmt.Sprintf("%s:%d", host, port) - conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout) + conn, err := session.DialTCP(ctx, "tcp", target, timeout) if err != nil { return nil, fmt.Errorf("连接失败: %w", err) } @@ -230,7 +230,7 @@ func probeTarget(host string, port int, timeout time.Duration) (*SMBTarget, erro } // SMBv2路径 - return probeSMBv2(target, timeout) + return probeSMBv2(ctx, target, timeout, session) } // probeSMBv1 处理SMBv1协议信息收集 @@ -288,8 +288,8 @@ func probeSMBv1(conn net.Conn, target string, timeout time.Duration) (*SMBTarget } // probeSMBv2 处理SMBv2协议信息收集 -func probeSMBv2(target string, timeout time.Duration) (*SMBTarget, error) { - conn2, err := common.WrapperTcpWithTimeout("tcp", target, timeout) +func probeSMBv2(ctx context.Context, target string, timeout time.Duration, session *common.ScanSession) (*SMBTarget, error) { + conn2, err := session.DialTCP(ctx, "tcp", target, timeout) if err != nil { return nil, fmt.Errorf("SMBv2连接失败: %w", err) } @@ -354,10 +354,10 @@ func probeSMBv2(target string, timeout time.Duration) (*SMBTarget, error) { } // checkSMBGhost 检测CVE-2020-0796漏洞 -func checkSMBGhost(host string, timeout time.Duration) bool { +func checkSMBGhost(ctx context.Context, host string, timeout time.Duration, session *common.ScanSession) bool { addr := fmt.Sprintf("%s:445", host) - conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout) + conn, err := session.DialTCP(ctx, "tcp", addr, timeout) if err != nil { return false } @@ -390,7 +390,7 @@ func checkSMBGhost(host string, timeout time.Duration) bool { // SMBAuthenticator 统一认证接口 type SMBAuthenticator interface { - Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration) (*AuthResult, error) + Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration, session *common.ScanSession) (*AuthResult, error) ListShares(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration) ([]string, error) } @@ -398,7 +398,7 @@ type SMBAuthenticator interface { type SMB1Authenticator struct{} // Authenticate 执行SMB1认证 -func (a *SMB1Authenticator) Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration) (*AuthResult, error) { +func (a *SMB1Authenticator) Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration, session *common.ScanSession) (*AuthResult, error) { options := smb.Options{ Host: host, Port: port, @@ -480,11 +480,11 @@ func (a *SMB1Authenticator) ListShares(ctx context.Context, host string, port in type SMB2Authenticator struct{} // Authenticate 执行SMB2认证 -func (a *SMB2Authenticator) Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration) (*AuthResult, error) { +func (a *SMB2Authenticator) Authenticate(ctx context.Context, host string, port int, cred Credential, domain string, timeout time.Duration, session *common.ScanSession) (*AuthResult, error) { timeoutCtx, cancel := context.WithTimeout(ctx, timeout) defer cancel() - conn, err := common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%d", host, port), timeout) + conn, err := session.DialTCP(ctx, "tcp", fmt.Sprintf("%s:%d", host, port), timeout) if err != nil { return &AuthResult{ Success: false, diff --git a/plugins/services/smtp.go b/plugins/services/smtp.go index 7d61eea..2ccc110 100644 --- a/plugins/services/smtp.go +++ b/plugins/services/smtp.go @@ -27,15 +27,14 @@ func NewSMTPPlugin() *SMTPPlugin { func (p *SMTPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State target := info.Target() if config.DisableBrute { - return p.identifyService(ctx, info, config, state) + return p.identifyService(ctx, info, session) } // 检测未授权访问 - if result := p.testUnauthorizedAccess(ctx, info, config, state); result != nil && result.Success { + if result := p.testUnauthorizedAccess(ctx, info, session); result != nil && result.Success { common.LogSuccess(i18n.Tr("smtp_service", target, result.Banner)) return result } @@ -57,7 +56,7 @@ func (p *SMTPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c } // 使用公共框架进行并发凭据测试 - authFn := p.createAuthFunc(info, config, state) + authFn := p.createAuthFunc(info, session) testConfig := DefaultConcurrentTestConfig(config) result := TestCredentialsConcurrently(ctx, creds, authFn, "smtp", testConfig) @@ -70,23 +69,22 @@ func (p *SMTPPlugin) Scan(ctx context.Context, info *common.HostInfo, session *c } // createAuthFunc 创建SMTP认证函数 -func (p *SMTPPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc { +func (p *SMTPPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc { return func(ctx context.Context, cred Credential) *AuthResult { - return p.doSMTPAuth(ctx, info, cred, config, state) + return p.doSMTPAuth(ctx, info, cred, session) } } // doSMTPAuth 执行SMTP认证 -func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult { +func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult { target := info.Target() - timeout := config.Timeout + timeout := session.Config.Timeout resultChan := make(chan *AuthResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, timeout) + conn, err := session.DialTCP(ctx, "tcp", target, timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: classifySMTPErrorType(err), @@ -100,7 +98,6 @@ func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred client, err := smtp.NewClient(conn, info.Host) if err != nil { _ = conn.Close() - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: classifySMTPErrorType(err), @@ -113,7 +110,6 @@ func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred auth := smtp.PlainAuth("", cred.Username, cred.Password, info.Host) if err := client.Auth(auth); err != nil { _ = client.Close() - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: classifySMTPErrorType(err), @@ -125,7 +121,6 @@ func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred if err := client.Mail("test@test.com"); err != nil { _ = client.Close() - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: classifySMTPErrorType(err), @@ -134,7 +129,6 @@ func (p *SMTPPlugin) doSMTPAuth(ctx context.Context, info *common.HostInfo, cred return } - state.IncrementTCPSuccessPacketCount() resultChan <- &AuthResult{ Success: true, Conn: &smtpClientWrapper{client}, @@ -211,24 +205,24 @@ func classifySMTPErrorType(err error) ErrorType { } // testUnauthorizedAccess 测试SMTP未授权访问 -func (p *SMTPPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *SMTPPlugin) testUnauthorizedAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { // 测试匿名访问 - if result := p.testAnonymousAccess(ctx, info, config, state); result != nil { + if result := p.testAnonymousAccess(ctx, info, session); result != nil { return result } // 测试开放中继 - if result := p.testOpenRelay(ctx, info, config, state); result != nil { + if result := p.testOpenRelay(ctx, info, session); result != nil { return result } // 测试VRFY命令 - if result := p.testVRFYCommand(ctx, info, config, state); result != nil { + if result := p.testVRFYCommand(ctx, info, session); result != nil { return result } // 测试EXPN命令 - if result := p.testEXPNCommand(ctx, info, config, state); result != nil { + if result := p.testEXPNCommand(ctx, info, session); result != nil { return result } @@ -236,15 +230,14 @@ func (p *SMTPPlugin) testUnauthorizedAccess(ctx context.Context, info *common.Ho } // testAnonymousAccess 测试匿名邮件发送 -func (p *SMTPPlugin) testAnonymousAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *SMTPPlugin) testAnonymousAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() resultChan := make(chan *ScanResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- nil return } @@ -272,7 +265,6 @@ func (p *SMTPPlugin) testAnonymousAccess(ctx context.Context, info *common.HostI return } - state.IncrementTCPSuccessPacketCount() resultChan <- &ScanResult{ Success: true, Type: plugins.ResultTypeVuln, @@ -290,15 +282,14 @@ func (p *SMTPPlugin) testAnonymousAccess(ctx context.Context, info *common.HostI } // testOpenRelay 测试开放中继 -func (p *SMTPPlugin) testOpenRelay(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *SMTPPlugin) testOpenRelay(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() resultChan := make(chan *ScanResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- nil return } @@ -326,7 +317,6 @@ func (p *SMTPPlugin) testOpenRelay(ctx context.Context, info *common.HostInfo, c return } - state.IncrementTCPSuccessPacketCount() resultChan <- &ScanResult{ Success: true, Type: plugins.ResultTypeVuln, @@ -344,21 +334,20 @@ func (p *SMTPPlugin) testOpenRelay(ctx context.Context, info *common.HostInfo, c } // testVRFYCommand 测试VRFY命令用户枚举 -func (p *SMTPPlugin) testVRFYCommand(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *SMTPPlugin) testVRFYCommand(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() resultChan := make(chan *ScanResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- nil return } defer func() { _ = conn.Close() }() - _ = conn.SetDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetDeadline(time.Now().Add(session.Config.Timeout)) if _, heloWriteErr := fmt.Fprintf(conn, "HELO fscan.test\r\n"); heloWriteErr != nil { resultChan <- nil @@ -393,7 +382,6 @@ func (p *SMTPPlugin) testVRFYCommand(ctx context.Context, info *common.HostInfo, vrfyResponse := strings.TrimSpace(string(buffer[:n])) if strings.HasPrefix(vrfyResponse, "250") { - state.IncrementTCPSuccessPacketCount() resultChan <- &ScanResult{ Success: true, Type: plugins.ResultTypeVuln, @@ -416,21 +404,20 @@ func (p *SMTPPlugin) testVRFYCommand(ctx context.Context, info *common.HostInfo, } // testEXPNCommand 测试EXPN命令邮件列表枚举 -func (p *SMTPPlugin) testEXPNCommand(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *SMTPPlugin) testEXPNCommand(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() resultChan := make(chan *ScanResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- nil return } defer func() { _ = conn.Close() }() - _ = conn.SetDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetDeadline(time.Now().Add(session.Config.Timeout)) if _, heloWriteErr := fmt.Fprintf(conn, "HELO fscan.test\r\n"); heloWriteErr != nil { resultChan <- nil @@ -465,7 +452,6 @@ func (p *SMTPPlugin) testEXPNCommand(ctx context.Context, info *common.HostInfo, expnResponse := strings.TrimSpace(string(buffer[:n])) if strings.HasPrefix(expnResponse, "250") { - state.IncrementTCPSuccessPacketCount() resultChan <- &ScanResult{ Success: true, Type: plugins.ResultTypeVuln, @@ -488,21 +474,20 @@ func (p *SMTPPlugin) testEXPNCommand(ctx context.Context, info *common.HostInfo, } // getServerInfo 获取SMTP服务器信息 -func (p *SMTPPlugin) getServerInfo(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) string { +func (p *SMTPPlugin) getServerInfo(ctx context.Context, info *common.HostInfo, session *common.ScanSession) string { target := info.Target() resultChan := make(chan string, 1) go func() { - conn, err := common.SafeTCPDial(target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- "" return } defer func() { _ = conn.Close() }() - _ = conn.SetReadDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetReadDeadline(time.Now().Add(session.Config.Timeout)) buffer := make([]byte, 1024) n, err := conn.Read(buffer) if err != nil { @@ -510,7 +495,6 @@ func (p *SMTPPlugin) getServerInfo(ctx context.Context, info *common.HostInfo, c return } - state.IncrementTCPSuccessPacketCount() welcome := strings.TrimSpace(string(buffer[:n])) if strings.HasPrefix(welcome, "220") { @@ -531,18 +515,17 @@ func (p *SMTPPlugin) getServerInfo(ctx context.Context, info *common.HostInfo, c } // identifyService SMTP服务识别 -func (p *SMTPPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *SMTPPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - serverInfo := p.getServerInfo(ctx, info, config, state) + serverInfo := p.getServerInfo(ctx, info, session) var banner string if serverInfo != "" { banner = fmt.Sprintf("SMTP邮件服务 (%s)", serverInfo) } else { - conn, err := common.SafeTCPDial(target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "smtp", @@ -550,7 +533,6 @@ func (p *SMTPPlugin) identifyService(ctx context.Context, info *common.HostInfo, } } defer func() { _ = conn.Close() }() - state.IncrementTCPSuccessPacketCount() banner = "SMTP邮件服务" } diff --git a/plugins/services/ssh.go b/plugins/services/ssh.go index d98effc..48e6efa 100644 --- a/plugins/services/ssh.go +++ b/plugins/services/ssh.go @@ -36,12 +36,11 @@ func NewSSHPlugin() *SSHPlugin { // Scan 执行SSH扫描 func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State target := info.Target() // 如果指定了SSH密钥,优先使用密钥认证 if config.Credentials.SSHKeyPath != "" { - if result := p.scanWithKey(ctx, info, config, state); result != nil && result.Success { + if result := p.scanWithKey(ctx, info, session); result != nil && result.Success { common.LogVuln(i18n.Tr("ssh_key_auth_success", target, result.Username)) //nolint:govet return result } @@ -49,7 +48,7 @@ func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co // 如果禁用暴力破解,只做服务识别 if config.DisableBrute { - return p.identifyService(info, config, state) + return p.identifyService(ctx, info, session) } // 生成测试凭据 @@ -65,7 +64,7 @@ func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co } // 使用公共框架进行并发凭据测试 - authFn := p.createAuthFunc(info, config, state) + authFn := p.createAuthFunc(info, session) testConfig := DefaultConcurrentTestConfig(config) result := TestCredentialsConcurrently(ctx, credentials, authFn, "ssh", testConfig) @@ -79,14 +78,15 @@ func (p *SSHPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co } // createAuthFunc 创建SSH认证函数 -func (p *SSHPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc { +func (p *SSHPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc { return func(ctx context.Context, cred Credential) *AuthResult { - return p.doSSHAuth(ctx, info, cred, config, state) + return p.doSSHAuth(ctx, info, cred, session) } } // doSSHAuth 执行SSH认证 -func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult { +func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult { + config := session.Config target := info.Target() // 创建SSH配置 @@ -113,9 +113,8 @@ func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred C } // 建立TCP连接 - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() return &AuthResult{ Success: false, ErrorType: classifySSHErrorType(err), @@ -127,7 +126,6 @@ func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred C sshConn, chans, reqs, err := ssh.NewClientConn(conn, target, sshConfig) if err != nil { _ = conn.Close() - state.IncrementTCPFailedPacketCount() return &AuthResult{ Success: false, ErrorType: classifySSHErrorType(err), @@ -138,7 +136,6 @@ func (p *SSHPlugin) doSSHAuth(ctx context.Context, info *common.HostInfo, cred C // 创建SSH客户端 client := ssh.NewClient(sshConn, chans, reqs) - state.IncrementTCPSuccessPacketCount() return &AuthResult{ Success: true, Conn: &sshClientWrapper{client}, @@ -181,7 +178,8 @@ func classifySSHErrorType(err error) ErrorType { } // scanWithKey 使用SSH私钥扫描 -func (p *SSHPlugin) scanWithKey(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *SSHPlugin) scanWithKey(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { + config := session.Config keyData, err := os.ReadFile(config.Credentials.SSHKeyPath) if err != nil { common.LogError(i18n.Tr("ssh_key_read_failed", err)) //nolint:govet @@ -206,7 +204,7 @@ func (p *SSHPlugin) scanWithKey(ctx context.Context, info *common.HostInfo, conf KeyData: keyData, } - result := p.doSSHAuth(ctx, info, cred, config, state) + result := p.doSSHAuth(ctx, info, cred, session) if result.Success { if result.Conn != nil { _ = result.Conn.Close() @@ -224,12 +222,11 @@ func (p *SSHPlugin) scanWithKey(ctx context.Context, info *common.HostInfo, conf } // identifyService 服务识别 -func (p *SSHPlugin) identifyService(info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *SSHPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() - conn, err := common.SafeTCPDial(target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "ssh", @@ -238,8 +235,7 @@ func (p *SSHPlugin) identifyService(info *common.HostInfo, config *common.Config } defer func() { _ = conn.Close() }() - if banner := p.readSSHBanner(conn, config); banner != "" { - state.IncrementTCPSuccessPacketCount() + if banner := p.readSSHBanner(conn, session.Config); banner != "" { common.LogSuccess(i18n.Tr("ssh_service_identified", target, banner)) //nolint:govet return &ScanResult{ Type: plugins.ResultTypeService, @@ -249,7 +245,6 @@ func (p *SSHPlugin) identifyService(info *common.HostInfo, config *common.Config } } - state.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "ssh", diff --git a/plugins/services/telnet.go b/plugins/services/telnet.go index 48ff181..a908d04 100644 --- a/plugins/services/telnet.go +++ b/plugins/services/telnet.go @@ -56,14 +56,14 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session target := info.Target() if config.DisableBrute { - return p.identifyService(ctx, info, config, state) + return p.identifyService(ctx, info, session) } // 检测未授权访问 - if result := p.testUnauthAccess(ctx, info, config, state); result != nil && result.Success { + if result := p.testUnauthAccess(ctx, info, session); result != nil && result.Success { common.LogVuln(i18n.Tr("telnet_service", target, result.Banner)) // 验证命令执行能力 - if ok, osType, evidence := p.verifyCommandExecution(ctx, info, "", "", config, state); ok { + if ok, osType, evidence := p.verifyCommandExecution(ctx, info, "", "", session); ok { common.LogVuln(i18n.Tr("telnet_unauth_rce", target, osType, evidence)) } return result @@ -103,7 +103,7 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session } // 使用公共框架进行并发凭据测试 - authFn := p.createAuthFunc(info, config, state) + authFn := p.createAuthFunc(info, session) testConfig := DefaultConcurrentTestConfig(config) result := TestCredentialsConcurrently(ctx, creds, authFn, "telnet", testConfig) @@ -111,7 +111,7 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session if result.Success { common.LogVuln(i18n.Tr("telnet_credential", target, result.Username, result.Password)) // 验证命令执行能力 - if ok, osType, evidence := p.verifyCommandExecution(ctx, info, result.Username, result.Password, config, state); ok { + if ok, osType, evidence := p.verifyCommandExecution(ctx, info, result.Username, result.Password, session); ok { common.LogVuln(i18n.Tr("telnet_credential_rce", target, result.Username, result.Password, osType, evidence)) } } @@ -120,22 +120,21 @@ func (p *TelnetPlugin) Scan(ctx context.Context, info *common.HostInfo, session } // createAuthFunc 创建Telnet认证函数 -func (p *TelnetPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc { +func (p *TelnetPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc { return func(ctx context.Context, cred Credential) *AuthResult { - return p.doTelnetAuth(ctx, info, cred, config, state) + return p.doTelnetAuth(ctx, info, cred, session) } } // doTelnetAuth 执行Telnet认证 -func (p *TelnetPlugin) doTelnetAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult { +func (p *TelnetPlugin) doTelnetAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult { target := info.Target() resultChan := make(chan *AuthResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: classifyTelnetErrorType(err), @@ -144,10 +143,9 @@ func (p *TelnetPlugin) doTelnetAuth(ctx context.Context, info *common.HostInfo, return } - _ = conn.SetDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetDeadline(time.Now().Add(session.Config.Timeout)) if p.performTelnetAuth(conn, cred.Username, cred.Password) { - state.IncrementTCPSuccessPacketCount() resultChan <- &AuthResult{ Success: true, Conn: &telnetConnWrapper{conn}, @@ -156,7 +154,6 @@ func (p *TelnetPlugin) doTelnetAuth(ctx context.Context, info *common.HostInfo, } } else { _ = conn.Close() - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: ErrorTypeAuth, @@ -224,21 +221,20 @@ func classifyTelnetErrorType(err error) ErrorType { } // testUnauthAccess 测试Telnet未授权访问 -func (p *TelnetPlugin) testUnauthAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *TelnetPlugin) testUnauthAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() resultChan := make(chan *ScanResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- nil return } defer func() { _ = conn.Close() }() - _ = conn.SetDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetDeadline(time.Now().Add(session.Config.Timeout)) buffer := make([]byte, 1024) attempts := 0 @@ -261,7 +257,6 @@ func (p *TelnetPlugin) testUnauthAccess(ctx context.Context, info *common.HostIn p.handleIACNegotiation(conn, buffer[:n]) if p.isShellPrompt(cleaned) { - state.IncrementTCPSuccessPacketCount() resultChan <- &ScanResult{ Success: true, Type: plugins.ResultTypeVuln, @@ -521,15 +516,14 @@ func (p *TelnetPlugin) isLoginFailed(data string) bool { } // identifyService Telnet服务识别 -func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { target := info.Target() resultChan := make(chan *ScanResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- &ScanResult{ Success: false, Service: "telnet", @@ -539,12 +533,11 @@ func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInf } defer func() { _ = conn.Close() }() - _ = conn.SetDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetDeadline(time.Now().Add(session.Config.Timeout)) buffer := make([]byte, 2048) n, err := conn.Read(buffer) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- &ScanResult{ Success: false, Service: "telnet", @@ -553,8 +546,6 @@ func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInf return } - state.IncrementTCPSuccessPacketCount() - p.handleIACNegotiation(conn, buffer[:n]) cleaned := p.cleanResponse(string(buffer[:n])) cleanedLower := strings.ToLower(cleaned) @@ -606,7 +597,7 @@ func (p *TelnetPlugin) identifyService(ctx context.Context, info *common.HostInf } // verifyCommandExecution 验证Telnet命令执行能力(RCE检测) -func (p *TelnetPlugin) verifyCommandExecution(ctx context.Context, info *common.HostInfo, username, password string, config *common.Config, state *common.State) (bool, string, string) { +func (p *TelnetPlugin) verifyCommandExecution(ctx context.Context, info *common.HostInfo, username, password string, session *common.ScanSession) (bool, string, string) { target := info.Target() type rceResult struct { @@ -618,14 +609,14 @@ func (p *TelnetPlugin) verifyCommandExecution(ctx context.Context, info *common. resultChan := make(chan rceResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { resultChan <- rceResult{} return } defer func() { _ = conn.Close() }() - _ = conn.SetDeadline(time.Now().Add(config.Timeout + telnetRCEExtraTimeout)) + _ = conn.SetDeadline(time.Now().Add(session.Config.Timeout + telnetRCEExtraTimeout)) // 需要认证时先登录 if username != "" || password != "" { diff --git a/plugins/services/vnc.go b/plugins/services/vnc.go index ff0024a..5f5d7e0 100644 --- a/plugins/services/vnc.go +++ b/plugins/services/vnc.go @@ -26,11 +26,10 @@ func NewVNCPlugin() *VNCPlugin { func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { config := session.Config - state := session.State target := info.Target() // 检查未授权访问 - if result := p.testUnauthAccess(ctx, info, config, state); result != nil && result.Success { + if result := p.testUnauthAccess(ctx, info, session); result != nil && result.Success { common.LogVuln(i18n.Tr("vnc_unauth", target)) return result } @@ -49,7 +48,7 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co } // 使用公共框架进行并发凭据测试 - authFn := p.createAuthFunc(info, config, state) + authFn := p.createAuthFunc(info, session) testConfig := DefaultConcurrentTestConfig(config) result := TestCredentialsConcurrently(ctx, credentials, authFn, "vnc", testConfig) @@ -62,22 +61,21 @@ func (p *VNCPlugin) Scan(ctx context.Context, info *common.HostInfo, session *co } // createAuthFunc 创建VNC认证函数 -func (p *VNCPlugin) createAuthFunc(info *common.HostInfo, config *common.Config, state *common.State) AuthFunc { +func (p *VNCPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc { return func(ctx context.Context, cred Credential) *AuthResult { - return p.doVNCAuth(ctx, info, cred, config, state) + return p.doVNCAuth(ctx, info, cred, session) } } // doVNCAuth 执行VNC认证 -func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred Credential, config *common.Config, state *common.State) *AuthResult { +func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult { target := info.Target() resultChan := make(chan *AuthResult, 1) go func() { - conn, err := common.WrapperTcpWithTimeout("tcp", target, config.Timeout) + conn, err := session.DialTCP(ctx, "tcp", target, session.Config.Timeout) if err != nil { - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: classifyVNCErrorType(err), @@ -86,7 +84,7 @@ func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred C return } - _ = conn.SetDeadline(time.Now().Add(config.Timeout)) + _ = conn.SetDeadline(time.Now().Add(session.Config.Timeout)) vncConfig := &vnc.ClientConfig{ Auth: []vnc.ClientAuth{ @@ -97,7 +95,6 @@ func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred C client, err := vnc.Client(conn, vncConfig) if err != nil { _ = conn.Close() - state.IncrementTCPFailedPacketCount() resultChan <- &AuthResult{ Success: false, ErrorType: classifyVNCErrorType(err), @@ -106,8 +103,6 @@ func (p *VNCPlugin) doVNCAuth(ctx context.Context, info *common.HostInfo, cred C return } - state.IncrementTCPSuccessPacketCount() - resultChan <- &AuthResult{ Success: true, Conn: &vncClientWrapper{client, conn}, @@ -175,9 +170,9 @@ func classifyVNCErrorType(err error) ErrorType { return ClassifyError(err, nil, CommonNetworkErrors) } -func (p *VNCPlugin) testUnauthAccess(ctx context.Context, info *common.HostInfo, config *common.Config, state *common.State) *ScanResult { +func (p *VNCPlugin) testUnauthAccess(ctx context.Context, info *common.HostInfo, session *common.ScanSession) *ScanResult { cred := Credential{Username: "", Password: ""} - result := p.doVNCAuth(ctx, info, cred, config, state) + result := p.doVNCAuth(ctx, info, cred, session) if result.Success { if result.Conn != nil {