dddd/common/portscan.go

299 lines
6.7 KiB
Go
Raw Normal View History

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)
}