diff --git a/Plugins/scanner.go b/Plugins/scanner.go index 99a11da..50da4a2 100644 --- a/Plugins/scanner.go +++ b/Plugins/scanner.go @@ -11,71 +11,103 @@ import ( ) func Scan(info common.HostInfo) { - fmt.Println("start infoscan") - Hosts, err := common.ParseIP(info.Host, common.HostFile, common.NoHosts) - if err != nil { - fmt.Println("len(hosts)==0", err) + fmt.Println("[*] 开始信息扫描...") + + // 本地信息收集模块 + if common.Scantype == "localinfo" { + ch := make(chan struct{}, common.Threads) + wg := sync.WaitGroup{} + AddScan("1000006", info, &ch, &wg) + wg.Wait() + common.LogWG.Wait() + close(common.Results) + fmt.Printf("[✓] 扫描完成 %v/%v\n", common.End, common.Num) return } + + // 解析目标主机IP + Hosts, err := common.ParseIP(info.Host, common.HostFile, common.NoHosts) + if err != nil { + fmt.Printf("[!] 解析主机错误: %v\n", err) + return + } + + // 初始化配置 lib.Inithttp() - var ch = make(chan struct{}, common.Threads) - var wg = sync.WaitGroup{} + ch := make(chan struct{}, common.Threads) + wg := sync.WaitGroup{} web := strconv.Itoa(common.PORTList["web"]) ms17010 := strconv.Itoa(common.PORTList["ms17010"]) + var AlivePorts, severports []string + if len(Hosts) > 0 || len(common.HostPort) > 0 { - if common.NoPing == false && len(Hosts) > 1 || common.Scantype == "icmp" { + // ICMP存活性检测 + if (common.NoPing == false && len(Hosts) > 1) || common.Scantype == "icmp" { Hosts = CheckLive(Hosts, common.Ping) - fmt.Println("[*] Icmp alive hosts len is:", len(Hosts)) - } - if common.Scantype == "icmp" { - common.LogWG.Wait() - return - } - var AlivePorts []string - if common.Scantype == "webonly" || common.Scantype == "webpoc" { - AlivePorts = NoPortScan(Hosts, common.Ports) - } else if common.Scantype == "hostname" { - common.Ports = "139" - AlivePorts = NoPortScan(Hosts, common.Ports) - } else if len(Hosts) > 0 { - AlivePorts = PortScan(Hosts, common.Ports, common.Timeout) - fmt.Println("[*] alive ports len is:", len(AlivePorts)) - if common.Scantype == "portscan" { + fmt.Printf("[+] ICMP存活主机数量: %d\n", len(Hosts)) + if common.Scantype == "icmp" { common.LogWG.Wait() return } } + + // 端口扫描策略 + switch common.Scantype { + case "webonly", "webpoc": + AlivePorts = NoPortScan(Hosts, common.Ports) + case "hostname": + common.Ports = "139" + AlivePorts = NoPortScan(Hosts, common.Ports) + default: + if len(Hosts) > 0 { + AlivePorts = PortScan(Hosts, common.Ports, common.Timeout) + fmt.Printf("[+] 存活端口数量: %d\n", len(AlivePorts)) + if common.Scantype == "portscan" { + common.LogWG.Wait() + return + } + } + } + + // 处理自定义端口 if len(common.HostPort) > 0 { AlivePorts = append(AlivePorts, common.HostPort...) AlivePorts = common.RemoveDuplicate(AlivePorts) common.HostPort = nil - fmt.Println("[*] AlivePorts len is:", len(AlivePorts)) + fmt.Printf("[+] 总计存活端口: %d\n", len(AlivePorts)) } - var severports []string //severports := []string{"21","22","135"."445","1433","3306","5432","6379","9200","11211","27017"...} + + // 构建服务端口列表 for _, port := range common.PORTList { severports = append(severports, strconv.Itoa(port)) } - fmt.Println("start vulscan") + + // 开始漏洞扫描 + fmt.Println("[*] 开始漏洞扫描...") for _, targetIP := range AlivePorts { - info.Host, info.Ports = strings.Split(targetIP, ":")[0], strings.Split(targetIP, ":")[1] + hostParts := strings.Split(targetIP, ":") + if len(hostParts) != 2 { + fmt.Printf("[!] 无效的目标地址格式: %s\n", targetIP) + continue + } + info.Host, info.Ports = hostParts[0], hostParts[1] + if common.Scantype == "all" || common.Scantype == "main" { switch { case info.Ports == "135": - AddScan(info.Ports, info, &ch, &wg) //findnet + AddScan(info.Ports, info, &ch, &wg) if common.IsWmi { - AddScan("1000005", info, &ch, &wg) //wmiexec + AddScan("1000005", info, &ch, &wg) } case info.Ports == "445": - AddScan(ms17010, info, &ch, &wg) //ms17010 - //AddScan(info.Ports, info, ch, &wg) //smb - //AddScan("1000002", info, ch, &wg) //smbghost + AddScan(ms17010, info, &ch, &wg) case info.Ports == "9000": - AddScan(web, info, &ch, &wg) //http - AddScan(info.Ports, info, &ch, &wg) //fcgiscan + AddScan(web, info, &ch, &wg) + AddScan(info.Ports, info, &ch, &wg) case IsContain(severports, info.Ports): - AddScan(info.Ports, info, &ch, &wg) //plugins scan + AddScan(info.Ports, info, &ch, &wg) default: - AddScan(web, info, &ch, &wg) //webtitle + AddScan(web, info, &ch, &wg) } } else { scantype := strconv.Itoa(common.PORTList[common.Scantype]) @@ -83,45 +115,69 @@ func Scan(info common.HostInfo) { } } } + + // URL扫描 for _, url := range common.Urls { info.Url = url AddScan(web, info, &ch, &wg) } + + // 等待所有任务完成 wg.Wait() common.LogWG.Wait() close(common.Results) - fmt.Printf("已完成 %v/%v\n", common.End, common.Num) + fmt.Printf("[✓] 扫描已完成: %v/%v\n", common.End, common.Num) } +// Mutex用于保护共享资源的并发访问 var Mutex = &sync.Mutex{} +// AddScan 添加扫描任务到并发队列 func AddScan(scantype string, info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) { + // 获取信号量,控制并发数 *ch <- struct{}{} + // 添加等待组计数 wg.Add(1) + + // 启动goroutine执行扫描任务 go func() { + defer func() { + wg.Done() // 完成任务后减少等待组计数 + <-*ch // 释放信号量 + }() + + // 增加总任务数 Mutex.Lock() common.Num += 1 Mutex.Unlock() + + // 执行扫描 ScanFunc(&scantype, &info) + + // 增加已完成任务数 Mutex.Lock() common.End += 1 Mutex.Unlock() - wg.Done() - <-*ch }() } +// ScanFunc 通过反射调用对应的扫描插件 func ScanFunc(name *string, info *common.HostInfo) { + // 异常恢复处理 defer func() { if err := recover(); err != nil { - fmt.Printf("[-] %v:%v scan error: %v\n", info.Host, info.Ports, err) + fmt.Printf("[!] 扫描错误 %v:%v - %v\n", info.Host, info.Ports, err) } }() + + // 通过反射获取插件函数 f := reflect.ValueOf(PluginList[*name]) + // 构造参数并调用插件函数 in := []reflect.Value{reflect.ValueOf(info)} f.Call(in) } +// IsContain 检查切片中是否包含指定元素 func IsContain(items []string, item string) bool { for _, eachItem := range items { if eachItem == item {