2024-12-19 15:24:10 +08:00
|
|
|
package Core
|
2020-12-29 17:17:10 +08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2024-12-18 22:00:18 +08:00
|
|
|
"github.com/shadow1ng/fscan/Common"
|
2021-05-29 12:13:10 +08:00
|
|
|
"github.com/shadow1ng/fscan/WebScan/lib"
|
2020-12-29 17:17:10 +08:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
2024-12-19 16:15:53 +08:00
|
|
|
func Scan(info Common.HostInfo) {
|
2024-12-18 15:18:58 +08:00
|
|
|
fmt.Println("[*] 开始信息扫描...")
|
|
|
|
|
|
|
|
// 本地信息收集模块
|
2024-12-18 22:00:18 +08:00
|
|
|
if Common.Scantype == "localinfo" {
|
|
|
|
ch := make(chan struct{}, Common.Threads)
|
2024-12-18 15:18:58 +08:00
|
|
|
wg := sync.WaitGroup{}
|
2024-12-18 21:56:08 +08:00
|
|
|
AddScan("localinfo", info, &ch, &wg)
|
2024-12-18 15:18:58 +08:00
|
|
|
wg.Wait()
|
2024-12-18 22:00:18 +08:00
|
|
|
Common.LogWG.Wait()
|
|
|
|
close(Common.Results)
|
|
|
|
fmt.Printf("[✓] 扫描完成 %v/%v\n", Common.End, Common.Num)
|
2024-12-18 15:18:58 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 解析目标主机IP
|
2024-12-18 22:00:18 +08:00
|
|
|
Hosts, err := Common.ParseIP(info.Host, Common.HostFile, Common.NoHosts)
|
2021-12-01 15:22:48 +08:00
|
|
|
if err != nil {
|
2024-12-18 15:18:58 +08:00
|
|
|
fmt.Printf("[!] 解析主机错误: %v\n", err)
|
2021-12-01 15:22:48 +08:00
|
|
|
return
|
|
|
|
}
|
2024-12-18 15:18:58 +08:00
|
|
|
|
|
|
|
// 初始化配置
|
2023-11-15 10:40:17 +08:00
|
|
|
lib.Inithttp()
|
2024-12-18 22:00:18 +08:00
|
|
|
ch := make(chan struct{}, Common.Threads)
|
2024-12-18 15:18:58 +08:00
|
|
|
wg := sync.WaitGroup{}
|
2024-12-18 21:56:08 +08:00
|
|
|
var AlivePorts []string
|
2024-12-18 15:18:58 +08:00
|
|
|
|
2024-12-18 22:00:18 +08:00
|
|
|
if len(Hosts) > 0 || len(Common.HostPort) > 0 {
|
2024-12-18 15:18:58 +08:00
|
|
|
// ICMP存活性检测
|
2024-12-18 22:00:18 +08:00
|
|
|
if (Common.NoPing == false && len(Hosts) > 1) || Common.Scantype == "icmp" {
|
|
|
|
Hosts = CheckLive(Hosts, Common.Ping)
|
2024-12-18 15:18:58 +08:00
|
|
|
fmt.Printf("[+] ICMP存活主机数量: %d\n", len(Hosts))
|
2024-12-18 22:00:18 +08:00
|
|
|
if Common.Scantype == "icmp" {
|
|
|
|
Common.LogWG.Wait()
|
2024-12-18 15:18:58 +08:00
|
|
|
return
|
|
|
|
}
|
2021-03-05 11:44:21 +08:00
|
|
|
}
|
2024-12-18 15:18:58 +08:00
|
|
|
|
|
|
|
// 端口扫描策略
|
2024-12-18 22:00:18 +08:00
|
|
|
AlivePorts = executeScanStrategy(Hosts, Common.Scantype)
|
2024-12-18 15:18:58 +08:00
|
|
|
|
|
|
|
// 处理自定义端口
|
2024-12-18 22:00:18 +08:00
|
|
|
if len(Common.HostPort) > 0 {
|
|
|
|
AlivePorts = append(AlivePorts, Common.HostPort...)
|
|
|
|
AlivePorts = Common.RemoveDuplicate(AlivePorts)
|
|
|
|
Common.HostPort = nil
|
2024-12-18 15:18:58 +08:00
|
|
|
fmt.Printf("[+] 总计存活端口: %d\n", len(AlivePorts))
|
2022-07-14 12:04:47 +08:00
|
|
|
}
|
2024-12-18 15:18:58 +08:00
|
|
|
|
2024-12-18 21:56:08 +08:00
|
|
|
// 执行扫描任务
|
2024-12-18 15:18:58 +08:00
|
|
|
fmt.Println("[*] 开始漏洞扫描...")
|
2021-03-05 11:44:21 +08:00
|
|
|
for _, targetIP := range AlivePorts {
|
2024-12-18 15:18:58 +08:00
|
|
|
hostParts := strings.Split(targetIP, ":")
|
|
|
|
if len(hostParts) != 2 {
|
|
|
|
fmt.Printf("[!] 无效的目标地址格式: %s\n", targetIP)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
info.Host, info.Ports = hostParts[0], hostParts[1]
|
|
|
|
|
2024-12-18 22:00:18 +08:00
|
|
|
executeScanTasks(info, Common.Scantype, &ch, &wg)
|
2020-12-29 17:17:10 +08:00
|
|
|
}
|
|
|
|
}
|
2024-12-18 15:18:58 +08:00
|
|
|
|
|
|
|
// URL扫描
|
2024-12-18 22:00:18 +08:00
|
|
|
for _, url := range Common.Urls {
|
2022-07-06 21:42:00 +08:00
|
|
|
info.Url = url
|
2024-12-18 21:56:08 +08:00
|
|
|
AddScan("web", info, &ch, &wg)
|
2021-03-04 14:42:10 +08:00
|
|
|
}
|
2024-12-18 15:18:58 +08:00
|
|
|
|
|
|
|
// 等待所有任务完成
|
2020-12-29 17:17:10 +08:00
|
|
|
wg.Wait()
|
2024-12-18 22:00:18 +08:00
|
|
|
Common.LogWG.Wait()
|
|
|
|
close(Common.Results)
|
2024-12-19 19:30:54 +08:00
|
|
|
fmt.Printf("[+] 扫描已完成: %v/%v\n", Common.End, Common.Num)
|
2020-12-29 17:17:10 +08:00
|
|
|
}
|
|
|
|
|
2024-12-18 21:56:08 +08:00
|
|
|
// executeScanStrategy 执行端口扫描策略
|
|
|
|
func executeScanStrategy(Hosts []string, scanType string) []string {
|
|
|
|
switch scanType {
|
|
|
|
case "webonly", "webpoc":
|
2024-12-18 22:00:18 +08:00
|
|
|
return NoPortScan(Hosts, Common.Ports)
|
2024-12-18 21:56:08 +08:00
|
|
|
case "hostname":
|
2024-12-18 22:00:18 +08:00
|
|
|
Common.Ports = "139"
|
|
|
|
return NoPortScan(Hosts, Common.Ports)
|
2024-12-18 21:56:08 +08:00
|
|
|
default:
|
|
|
|
if len(Hosts) > 0 {
|
2024-12-18 22:00:18 +08:00
|
|
|
ports := PortScan(Hosts, Common.Ports, Common.Timeout)
|
2024-12-18 21:56:08 +08:00
|
|
|
fmt.Printf("[+] 存活端口数量: %d\n", len(ports))
|
|
|
|
if scanType == "portscan" {
|
2024-12-18 22:00:18 +08:00
|
|
|
Common.LogWG.Wait()
|
2024-12-18 21:56:08 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return ports
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// executeScanTasks 执行扫描任务
|
2024-12-19 16:15:53 +08:00
|
|
|
func executeScanTasks(info Common.HostInfo, scanType string, ch *chan struct{}, wg *sync.WaitGroup) {
|
2024-12-18 21:56:08 +08:00
|
|
|
if scanType == "all" || scanType == "main" {
|
|
|
|
// 根据端口选择扫描插件
|
|
|
|
switch info.Ports {
|
|
|
|
case "135":
|
|
|
|
AddScan("findnet", info, ch, wg)
|
2024-12-18 22:00:18 +08:00
|
|
|
if Common.IsWmi {
|
2024-12-18 21:56:08 +08:00
|
|
|
AddScan("wmiexec", info, ch, wg)
|
|
|
|
}
|
|
|
|
case "445":
|
|
|
|
AddScan("ms17010", info, ch, wg)
|
|
|
|
case "9000":
|
|
|
|
AddScan("web", info, ch, wg)
|
|
|
|
AddScan("fcgi", info, ch, wg)
|
|
|
|
default:
|
|
|
|
// 查找对应端口的插件
|
2024-12-19 16:15:53 +08:00
|
|
|
for name, plugin := range Common.PluginManager {
|
2024-12-18 21:56:08 +08:00
|
|
|
if strconv.Itoa(plugin.Port) == info.Ports {
|
|
|
|
AddScan(name, info, ch, wg)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 默认执行Web扫描
|
|
|
|
AddScan("web", info, ch, wg)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// 直接使用指定的扫描类型
|
|
|
|
AddScan(scanType, info, ch, wg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-18 15:18:58 +08:00
|
|
|
// Mutex用于保护共享资源的并发访问
|
2021-03-30 18:12:54 +08:00
|
|
|
var Mutex = &sync.Mutex{}
|
|
|
|
|
2024-12-18 15:18:58 +08:00
|
|
|
// AddScan 添加扫描任务到并发队列
|
2024-12-19 16:15:53 +08:00
|
|
|
func AddScan(scantype string, info Common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
|
2024-12-18 15:18:58 +08:00
|
|
|
// 获取信号量,控制并发数
|
2022-08-16 11:18:09 +08:00
|
|
|
*ch <- struct{}{}
|
2024-12-18 15:18:58 +08:00
|
|
|
// 添加等待组计数
|
2020-12-29 17:17:10 +08:00
|
|
|
wg.Add(1)
|
2024-12-18 15:18:58 +08:00
|
|
|
|
|
|
|
// 启动goroutine执行扫描任务
|
2020-12-29 17:17:10 +08:00
|
|
|
go func() {
|
2024-12-18 15:18:58 +08:00
|
|
|
defer func() {
|
|
|
|
wg.Done() // 完成任务后减少等待组计数
|
|
|
|
<-*ch // 释放信号量
|
|
|
|
}()
|
|
|
|
|
|
|
|
// 增加总任务数
|
2021-03-30 18:12:54 +08:00
|
|
|
Mutex.Lock()
|
2024-12-18 22:00:18 +08:00
|
|
|
Common.Num += 1
|
2021-03-30 18:12:54 +08:00
|
|
|
Mutex.Unlock()
|
2024-12-18 15:18:58 +08:00
|
|
|
|
|
|
|
// 执行扫描
|
2022-08-16 11:18:09 +08:00
|
|
|
ScanFunc(&scantype, &info)
|
2024-12-18 15:18:58 +08:00
|
|
|
|
|
|
|
// 增加已完成任务数
|
2021-03-30 18:12:54 +08:00
|
|
|
Mutex.Lock()
|
2024-12-18 22:00:18 +08:00
|
|
|
Common.End += 1
|
2021-03-30 18:12:54 +08:00
|
|
|
Mutex.Unlock()
|
2020-12-29 17:17:10 +08:00
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
2024-12-18 21:56:08 +08:00
|
|
|
// ScanFunc 执行扫描插件
|
2024-12-19 16:15:53 +08:00
|
|
|
func ScanFunc(name *string, info *Common.HostInfo) {
|
2024-05-11 16:04:02 +08:00
|
|
|
defer func() {
|
|
|
|
if err := recover(); err != nil {
|
2024-12-18 15:18:58 +08:00
|
|
|
fmt.Printf("[!] 扫描错误 %v:%v - %v\n", info.Host, info.Ports, err)
|
2024-05-11 16:04:02 +08:00
|
|
|
}
|
|
|
|
}()
|
2024-12-18 15:18:58 +08:00
|
|
|
|
2024-12-18 21:56:08 +08:00
|
|
|
// 检查插件是否存在
|
2024-12-19 16:15:53 +08:00
|
|
|
plugin, exists := Common.PluginManager[*name]
|
2024-12-18 21:56:08 +08:00
|
|
|
if !exists {
|
|
|
|
fmt.Printf("[*] 扫描类型 %v 无对应插件,已跳过\n", *name)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 直接调用扫描函数
|
|
|
|
if err := plugin.ScanFunc(info); err != nil {
|
|
|
|
fmt.Printf("[!] 扫描错误 %v:%v - %v\n", info.Host, info.Ports, err)
|
|
|
|
}
|
2020-12-29 17:17:10 +08:00
|
|
|
}
|
|
|
|
|
2024-12-18 15:18:58 +08:00
|
|
|
// IsContain 检查切片中是否包含指定元素
|
2020-12-29 17:17:10 +08:00
|
|
|
func IsContain(items []string, item string) bool {
|
|
|
|
for _, eachItem := range items {
|
|
|
|
if eachItem == item {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|