2023-08-18 08:55:46 +02:00
|
|
|
|
package common
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
2024-04-03 06:32:26 +02:00
|
|
|
|
"dddd/ddout"
|
2023-08-18 08:55:46 +02:00
|
|
|
|
"dddd/lib/masscan"
|
|
|
|
|
"dddd/structs"
|
|
|
|
|
"dddd/utils"
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/projectdiscovery/gologger"
|
|
|
|
|
"os"
|
|
|
|
|
"os/exec"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func ParsePort(ports string) (scanPorts []int) {
|
|
|
|
|
if ports == "" {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
slices := strings.Split(ports, ",")
|
|
|
|
|
for _, port := range slices {
|
|
|
|
|
port = strings.TrimSpace(port)
|
|
|
|
|
if port == "" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
upper := port
|
|
|
|
|
if strings.Contains(port, "-") {
|
|
|
|
|
ranges := strings.Split(port, "-")
|
|
|
|
|
if len(ranges) < 2 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
startPort, _ := strconv.Atoi(ranges[0])
|
|
|
|
|
endPort, _ := strconv.Atoi(ranges[1])
|
|
|
|
|
if startPort < endPort {
|
|
|
|
|
port = ranges[0]
|
|
|
|
|
upper = ranges[1]
|
|
|
|
|
} else {
|
|
|
|
|
port = ranges[1]
|
|
|
|
|
upper = ranges[0]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
start, _ := strconv.Atoi(port)
|
|
|
|
|
end, _ := strconv.Atoi(upper)
|
|
|
|
|
for i := start; i <= end; i++ {
|
|
|
|
|
scanPorts = append(scanPorts, i)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
scanPorts = utils.RemoveDuplicateElementInt(scanPorts)
|
|
|
|
|
return scanPorts
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-24 10:30:19 +02:00
|
|
|
|
var BackList map[string]struct{}
|
|
|
|
|
var BackListLock sync.Mutex
|
|
|
|
|
|
2024-06-07 19:17:14 +08:00
|
|
|
|
func PortScanTCP(IPs []string, Ports string, NoPorts string, timeout int) []string {
|
2023-08-18 08:55:46 +02:00
|
|
|
|
var AliveAddress []string
|
2024-01-02 14:50:55 +01:00
|
|
|
|
gologger.AuditTimeLogger("开始TCP端口扫描,端口设置: %s\nTCP端口扫描目标:%s", Ports, strings.Join(IPs, ","))
|
2024-06-07 19:17:14 +08:00
|
|
|
|
ports := ParsePort(Ports)
|
|
|
|
|
noPorts := ParsePort(NoPorts)
|
|
|
|
|
|
|
|
|
|
var probePorts []int
|
|
|
|
|
for _, port := range ports {
|
|
|
|
|
ok := false
|
|
|
|
|
for _, nport := range noPorts {
|
|
|
|
|
if nport == port {
|
|
|
|
|
ok = true
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if !ok {
|
|
|
|
|
probePorts = append(probePorts, port)
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-18 08:55:46 +02:00
|
|
|
|
|
2024-05-24 10:30:19 +02:00
|
|
|
|
IPPortCount := make(map[string]int)
|
|
|
|
|
BackList = make(map[string]struct{})
|
|
|
|
|
|
2023-08-18 08:55:46 +02:00
|
|
|
|
workers := structs.GlobalConfig.TCPPortScanThreads
|
2023-12-11 09:27:46 +01:00
|
|
|
|
if workers > len(IPs)*len(probePorts) {
|
|
|
|
|
workers = len(IPs) * len(probePorts)
|
|
|
|
|
}
|
2024-06-07 19:17:14 +08:00
|
|
|
|
Addrs := make(chan Addr, structs.GlobalConfig.TCPPortScanThreads)
|
|
|
|
|
results := make(chan string, structs.GlobalConfig.TCPPortScanThreads)
|
2023-08-18 08:55:46 +02:00
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
|
|
|
|
|
//接收结果
|
|
|
|
|
go func() {
|
|
|
|
|
for found := range results {
|
|
|
|
|
AliveAddress = append(AliveAddress, found)
|
2024-05-24 10:30:19 +02:00
|
|
|
|
|
|
|
|
|
t := strings.Split(found, ":")
|
|
|
|
|
ip := t[0]
|
|
|
|
|
|
|
|
|
|
count, ok := IPPortCount[ip]
|
|
|
|
|
if ok {
|
|
|
|
|
if count > structs.GlobalConfig.PortsThreshold {
|
|
|
|
|
inblack := false
|
|
|
|
|
BackListLock.Lock()
|
|
|
|
|
_, inblack = BackList[ip]
|
|
|
|
|
BackListLock.Unlock()
|
|
|
|
|
if !inblack {
|
|
|
|
|
BackListLock.Lock()
|
|
|
|
|
BackList[ip] = struct{}{}
|
|
|
|
|
BackListLock.Unlock()
|
|
|
|
|
gologger.Error().Msgf("%s 端口数量超出阈值,放弃扫描", ip)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
IPPortCount[ip] = count + 1
|
|
|
|
|
} else {
|
|
|
|
|
IPPortCount[ip] = 1
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-18 08:55:46 +02:00
|
|
|
|
wg.Done()
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
//多线程扫描
|
|
|
|
|
for i := 0; i < workers; i++ {
|
|
|
|
|
go func() {
|
|
|
|
|
for addr := range Addrs {
|
|
|
|
|
PortConnect(addr, results, timeout, &wg)
|
|
|
|
|
wg.Done()
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//添加扫描目标
|
|
|
|
|
for _, port := range probePorts {
|
|
|
|
|
for _, host := range IPs {
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
Addrs <- Addr{host, port}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
wg.Wait()
|
|
|
|
|
close(Addrs)
|
|
|
|
|
close(results)
|
2024-01-02 14:50:55 +01:00
|
|
|
|
gologger.AuditTimeLogger("TCP端口扫描结束")
|
2023-08-18 08:55:46 +02:00
|
|
|
|
|
|
|
|
|
return AliveAddress
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Addr struct {
|
|
|
|
|
ip string
|
|
|
|
|
port int
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-11 09:27:46 +01:00
|
|
|
|
var PortScan bool
|
|
|
|
|
|
2023-08-18 08:55:46 +02:00
|
|
|
|
func PortConnect(addr Addr, respondingHosts chan<- string, adjustedTimeout int, wg *sync.WaitGroup) {
|
2024-05-24 10:30:19 +02:00
|
|
|
|
inblack := false
|
|
|
|
|
BackListLock.Lock()
|
|
|
|
|
_, inblack = BackList[addr.ip]
|
|
|
|
|
BackListLock.Unlock()
|
|
|
|
|
if inblack {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-18 08:55:46 +02:00
|
|
|
|
host, port := addr.ip, addr.port
|
|
|
|
|
conn, err := WrapperTcpWithTimeout("tcp4", fmt.Sprintf("%s:%v", host, port), time.Duration(adjustedTimeout)*time.Second)
|
|
|
|
|
defer func() {
|
|
|
|
|
if conn != nil {
|
|
|
|
|
conn.Close()
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
if err == nil {
|
|
|
|
|
address := host + ":" + strconv.Itoa(port)
|
2023-12-11 09:27:46 +01:00
|
|
|
|
if PortScan {
|
2024-04-03 06:32:26 +02:00
|
|
|
|
// gologger.Silent().Msgf("[PortScan] %v", address)
|
|
|
|
|
ddout.FormatOutput(ddout.OutputMessage{
|
|
|
|
|
Type: "PortScan",
|
|
|
|
|
IP: host,
|
|
|
|
|
Port: strconv.Itoa(port),
|
|
|
|
|
})
|
|
|
|
|
|
2023-12-11 09:27:46 +01:00
|
|
|
|
} else {
|
2024-04-03 06:32:26 +02:00
|
|
|
|
// gologger.Silent().Msgf("[TCP-Alive] %v", address)
|
|
|
|
|
ddout.FormatOutput(ddout.OutputMessage{
|
|
|
|
|
Type: "IPAlive",
|
|
|
|
|
IP: host,
|
|
|
|
|
AdditionalMsg: "TCP:" + strconv.Itoa(port),
|
|
|
|
|
})
|
2023-12-11 09:27:46 +01:00
|
|
|
|
}
|
2023-08-18 08:55:46 +02:00
|
|
|
|
wg.Add(1)
|
|
|
|
|
respondingHosts <- address
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func PortScanSYN(IPs []string) []string {
|
|
|
|
|
ips := strings.Join(utils.RemoveDuplicateElement(IPs), "\n")
|
|
|
|
|
err := os.WriteFile("masscan_tmp.txt", []byte(ips), 0666)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return []string{}
|
|
|
|
|
}
|
|
|
|
|
defer os.Remove("masscan_tmp.txt")
|
|
|
|
|
|
|
|
|
|
ms := masscan.New(structs.GlobalConfig.MasscanPath)
|
|
|
|
|
ms.SetFileName("masscan_tmp.txt")
|
|
|
|
|
ms.SetPorts("1-65535")
|
|
|
|
|
ms.SetRate(strconv.Itoa(structs.GlobalConfig.SYNPortScanThreads))
|
2024-01-02 14:50:55 +01:00
|
|
|
|
gologger.Info().Msgf("调用masscan进行SYN端口扫描")
|
2023-08-18 08:55:46 +02:00
|
|
|
|
err = ms.Run()
|
2024-01-02 14:50:55 +01:00
|
|
|
|
gologger.AuditTimeLogger("masscan扫描结束")
|
2023-08-18 08:55:46 +02:00
|
|
|
|
if err != nil {
|
|
|
|
|
return []string{}
|
|
|
|
|
}
|
|
|
|
|
hosts, errParse := ms.Parse()
|
|
|
|
|
if errParse != nil {
|
|
|
|
|
gologger.Error().Msgf("masscan结果解析失败")
|
|
|
|
|
return []string{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var results []string
|
|
|
|
|
for _, each := range hosts {
|
|
|
|
|
for _, port := range each.Ports {
|
|
|
|
|
results = append(results, each.Address.Addr+":"+port.Portid)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
results = utils.RemoveDuplicateElement(results)
|
|
|
|
|
for _, each := range results {
|
2024-04-03 06:32:26 +02:00
|
|
|
|
// gologger.Silent().Msg("[PortScan] " + each)
|
|
|
|
|
t := strings.Split(each, ":")
|
|
|
|
|
ddout.FormatOutput(ddout.OutputMessage{
|
|
|
|
|
Type: "PortScan",
|
|
|
|
|
IP: t[0],
|
|
|
|
|
Port: t[1],
|
|
|
|
|
})
|
2023-08-18 08:55:46 +02:00
|
|
|
|
}
|
|
|
|
|
return results
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CheckMasScan 校验MasScan是否正确安装
|
|
|
|
|
func CheckMasScan() bool {
|
|
|
|
|
var bsenv = ""
|
|
|
|
|
if OS != "windows" {
|
|
|
|
|
bsenv = "/bin/bash"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var command *exec.Cmd
|
|
|
|
|
if OS == "windows" {
|
|
|
|
|
command = exec.Command("cmd", "/c", structs.GlobalConfig.MasscanPath)
|
|
|
|
|
} else if OS == "linux" {
|
|
|
|
|
command = exec.Command(bsenv, "-c", structs.GlobalConfig.MasscanPath)
|
|
|
|
|
} else if OS == "darwin" {
|
|
|
|
|
command = exec.Command(bsenv, "-c", structs.GlobalConfig.MasscanPath)
|
|
|
|
|
}
|
|
|
|
|
outinfo := bytes.Buffer{}
|
|
|
|
|
command.Stdout = &outinfo
|
|
|
|
|
err := command.Start()
|
|
|
|
|
if err != nil {
|
|
|
|
|
gologger.Error().Msgf("未检测到路径 %v 存在masscan", structs.GlobalConfig.MasscanPath)
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
_ = command.Wait()
|
|
|
|
|
|
|
|
|
|
// 未检测到masscan的默认banner
|
|
|
|
|
if !strings.Contains(outinfo.String(), "masscan -p80,8000-8100 10.0.0.0/8 --rate=10000") {
|
|
|
|
|
gologger.Error().Msgf("未检测到路径 %v 存在masscan", structs.GlobalConfig.MasscanPath)
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func RemoveFirewall(ipPorts []string) []string {
|
|
|
|
|
var results []string
|
|
|
|
|
|
2024-01-02 14:50:55 +01:00
|
|
|
|
gologger.AuditTimeLogger("移除开放端口过多的目标")
|
|
|
|
|
|
2023-08-18 08:55:46 +02:00
|
|
|
|
m := make(map[string][]string)
|
|
|
|
|
for _, ipPort := range ipPorts {
|
|
|
|
|
t := strings.Split(ipPort, ":")
|
|
|
|
|
ip := t[0]
|
|
|
|
|
port := t[1]
|
|
|
|
|
|
|
|
|
|
_, ok := m[ip]
|
|
|
|
|
if !ok {
|
|
|
|
|
m[ip] = []string{port}
|
|
|
|
|
} else {
|
|
|
|
|
m[ip] = append(m[ip], port)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ip, ports := range m {
|
|
|
|
|
ps := utils.RemoveDuplicateElement(ports)
|
|
|
|
|
if len(ps) >= structs.GlobalConfig.PortsThreshold {
|
|
|
|
|
gologger.Error().Msgf("%s 端口数量超出阈值,已丢弃", ip)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
for _, p := range ports {
|
|
|
|
|
results = append(results, ip+":"+p)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return utils.RemoveDuplicateElement(results)
|
|
|
|
|
}
|