/
scan_servicescan.go
160 lines (135 loc) · 3.96 KB
/
scan_servicescan.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package yakcmds
import (
"github.com/urfave/cli"
"github.com/yaklang/yaklang/common/fp"
"github.com/yaklang/yaklang/common/fp/webfingerprint"
"github.com/yaklang/yaklang/common/log"
"github.com/yaklang/yaklang/common/utils"
"sync"
"time"
)
var servicescanCommand = cli.Command{
Name: "scan-service",
Usage: "ServiceScan means Fingerprint Scan, it will create a tcp/udp connection to the target and wait for the response",
Flags: []cli.Flag{
cli.StringFlag{
Name: "hosts,target,t",
Usage: "输入扫描主机,以逗号分隔例如:(192.168.1.1/24,192.168.1.1-23,10.1.1.2)",
},
cli.StringFlag{
Name: "port,tcp-port,p",
Usage: "输入想要扫描的端口,支持单个端口和范围,例如(80,443,21-25,8080-8082)",
Value: "22,80,443,3389,3306,8080-8082,9000-9002,7000-7002",
},
cli.StringFlag{
Name: "udp-port",
Usage: "想要扫描的 UDP 端口,支持单个端口和范围",
},
cli.StringFlag{
Name: "rule-path,rule,r",
Usage: "手动加载规则文件/文件夹",
},
cli.BoolFlag{
Name: "only-rule",
Usage: "只加载这个文件夹中的 Web 指纹",
},
cli.IntFlag{
Name: "concurrent,thread,c",
Usage: "并发速度,同时有多少个扫描过程进行?",
Value: 60,
},
//cli.IntFlag{
// Name: "timeout",
// Usage: "超时时间(Seconds)",
// Value: 3600,
//},
cli.BoolFlag{
Name: "web",
Usage: "主动开启 web 扫描模式",
},
cli.IntFlag{
Name: "request-timeout",
Usage: "单个请求的超时时间(Seconds)",
Value: 10,
},
cli.StringFlag{
Name: "json,o",
Usage: "详细结果输出 json 到文件",
},
},
Action: func(c *cli.Context) error {
var options []fp.ConfigOption
// web rule
webRules, _ := fp.GetDefaultWebFingerprintRules()
userRule := webfingerprint.FileOrDirToWebRules(c.String("rule-path"))
if c.Bool("only-rule") {
webRules = userRule
} else {
webRules = append(webRules, userRule...)
}
options = append(
options,
// 主动探测模式 - 主动发送符合条件的包
fp.WithActiveMode(true),
// 每一个指纹探测请求的超时时间
fp.WithProbeTimeout(time.Second*time.Duration(c.Int("request-timeout"))),
// web 指纹火力全开
fp.WithWebFingerprintUseAllRules(true),
// web 指纹
fp.WithWebFingerprintRule(webRules),
)
options = append(
options, fp.WithForceEnableAllFingerprint(true),
)
config := fp.NewConfig(options...)
matcher, err := fp.NewDefaultFingerprintMatcher(config)
if err != nil {
return err
}
// udp/tcp
portSwg := utils.NewSizedWaitGroup(c.Int("concurrent"))
// 结果处理的同步锁
resultLock := new(sync.Mutex)
var res []*fp.MatchResult
scanCore := func(tHost string, tPort int, opts ...fp.ConfigOption) {
defer portSwg.Done()
log.Infof("start scan %v", utils.HostPort(tHost, tPort))
result, err := matcher.Match(
tHost, tPort,
opts...,
)
if err != nil {
log.Errorf("scan %v failed: %s", utils.HostPort(tHost, tPort), err)
return
}
resultLock.Lock()
defer resultLock.Unlock()
log.Infof("[%6s] %s://%s cpe: %v", result.State, result.GetProto(), utils.HostPort(result.Target, result.Port), result.GetCPEs())
res = append(res, result)
}
for _, host := range utils.ParseStringToHosts(c.String("hosts")) {
host := host
for _, tcpPort := range utils.ParseStringToPorts(c.String("port")) {
tcpPort := tcpPort
portSwg.Add()
go scanCore(
host, tcpPort,
fp.WithForceEnableAllFingerprint(true),
fp.WithOnlyEnableWebFingerprint(c.Bool("web")),
fp.WithTransportProtos(fp.TCP),
)
}
for _, udpPort := range utils.ParseStringToPorts(c.String("udp-port")) {
udpPort := udpPort
portSwg.Add()
go scanCore(host, udpPort, fp.WithDisableWebFingerprint(true),
fp.WithTransportProtos(fp.UDP))
}
}
portSwg.Wait()
analysis := fp.MatcherResultsToAnalysis(res)
analysis.Show()
analysis.ToJson(c.String("json"))
return nil
},
}