forked from knownsec/ksubdomain
/
options.go
149 lines (145 loc) · 5.15 KB
/
options.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
package core
import (
"flag"
"github.com/ReAbout/ksubdomain/gologger"
"os"
"strconv"
)
type Options struct {
Rate int64
Domain []string
FileName string
Resolvers []string
Output string
OutputCSV bool
Test bool
NetworkId int
ListNetwork bool
Silent bool
TTL bool
Verify bool
Stdin bool
Debug bool
DomainLevel int
SkipWildCard bool
Summary bool
API bool
FULL bool
SubNameFileName string // 三级域名字典文件
FilterWildCard bool // 过滤泛解析结果
CheckOrigin bool // 会从返回包检查DNS是否为设定的,防止其他包的干扰
}
// ParseOptions parses the command line flags provided by a user
func ParseOptions() *Options {
options := &Options{}
bandwith := flag.String("b", "1M", "宽带的下行速度,可以5M,5K,5G")
domain := flag.String("d", "", "爆破域名")
domain_list := flag.String("dl", "", "从文件中读取爆破域名")
flag.StringVar(&options.FileName, "f", "", "字典路径,-d下文件为子域名字典,-verify下文件为需要验证的域名")
flag.StringVar(&options.SubNameFileName, "sf", "", "三级域名爆破字典文件(默认内置)")
resolvers := flag.String("s", "", "resolvers文件路径,默认使用内置DNS")
flag.StringVar(&options.Output, "o", "", "输出文件路径")
flag.BoolVar(&options.OutputCSV, "csv", false, "输出excel文件")
flag.BoolVar(&options.Test, "test", false, "测试本地最大发包数")
flag.IntVar(&options.NetworkId, "e", -1, "默认网络设备ID,默认-1,如果有多个网络设备会在命令行中选择")
flag.BoolVar(&options.ListNetwork, "list-network", false, "列出所有网络设备")
flag.BoolVar(&options.Silent, "silent", false, "使用后屏幕将仅输出域名")
flag.BoolVar(&options.TTL, "ttl", false, "导出格式中包含TTL选项")
flag.BoolVar(&options.Verify, "verify", false, "验证模式")
flag.BoolVar(&options.API, "api", false, "使用网络接口")
flag.BoolVar(&options.FULL, "full", false, "完整模式,使用网络接口和内置字典")
flag.IntVar(&options.DomainLevel, "l", 1, "爆破域名层级,默认爆破一级域名")
flag.BoolVar(&options.SkipWildCard, "skip-wild", false, "跳过泛解析的域名")
flag.BoolVar(&options.FilterWildCard, "filter-wild", false, "自动分析并过滤泛解析,最终输出文件,需要与'-o'搭配")
flag.BoolVar(&options.Summary, "summary", false, "在扫描完毕后整理域名归属asn以及IP段")
flag.BoolVar(&options.CheckOrigin, "check-origin", false, "会从返回包检查DNS是否为设定的,防止其他包的干扰")
flag.Parse()
options.Stdin = hasStdin()
if options.Silent {
gologger.MaxLevel = gologger.Silent
}
ShowBanner()
// handle resolver
if *resolvers != "" {
rs, err := LinesInFile(*resolvers)
if err != nil {
gologger.Fatalf("读取resolvers文件失败:%s\n", err.Error())
}
if len(rs) == 0 {
gologger.Fatalf("resolvers文件内容为空\n")
}
options.Resolvers = rs
} else {
defaultDns := []string{"223.5.5.5", "223.6.6.6", "180.76.76.76", "119.29.29.29", "182.254.116.116", "114.114.114.115"}
options.Resolvers = defaultDns
}
// handle domain
if *domain != "" {
options.Domain = append(options.Domain, *domain)
}
if *domain_list != "" {
dl, err := LinesInFile(*domain_list)
if err != nil {
gologger.Fatalf("读取domain文件失败:%s\n", err.Error())
}
options.Domain = append(dl, options.Domain...)
}
var rate int64
suffix := string([]rune(*bandwith)[len(*bandwith)-1])
rate, _ = strconv.ParseInt(string([]rune(*bandwith)[0:len(*bandwith)-1]), 10, 64)
switch suffix {
case "G":
fallthrough
case "g":
rate *= 1000000000
case "M":
fallthrough
case "m":
rate *= 1000000
case "K":
fallthrough
case "k":
rate *= 1000
default:
gologger.Fatalf("unknown bandwith suffix '%s' (supported suffixes are G,M and K)\n", suffix)
}
packSize := int64(100) // 一个DNS包大概有74byte
rate = rate / packSize
options.Rate = rate
if len(options.Domain) == 0 && !hasStdin() && (!options.Verify && options.FileName == "") && !options.Test && !options.ListNetwork {
flag.Usage()
os.Exit(0)
}
if len(options.Domain) > 0 && options.Verify {
gologger.Fatalf("-d 与 -verify参数不可以同时出现!")
}
if options.FileName != "" && !FileExists(options.FileName) {
gologger.Fatalf("文件:%s 不存在!\n", options.FileName)
}
if !options.Stdin && options.Verify && options.FileName == "" {
gologger.Fatalf("启用了 -verify 参数但传入域名为空!")
}
if options.FilterWildCard && options.Output == "" {
gologger.Fatalf("启用了 -filter-wild后,需要搭配一个输出文件 '-o'")
}
if options.FilterWildCard && options.Silent {
gologger.Fatalf("不支持 filter-wild 与 silent 同时使用")
}
if options.OutputCSV && options.Output == "" {
gologger.Fatalf("输出excel需要指定一个路径,使用参数 -o ")
}
if options.FULL {
options.API = true
}
return options
}
func hasStdin() bool {
fi, err := os.Stdin.Stat()
if err != nil {
return false
}
if fi.Mode()&os.ModeNamedPipe == 0 {
return false
}
return true
}