-
Notifications
You must be signed in to change notification settings - Fork 0
/
subdomain_finder.go
137 lines (126 loc) · 2.97 KB
/
subdomain_finder.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
package main
import (
"bufio"
"errors"
"flag"
"fmt"
"os"
"text/tabwriter"
"github.com/miekg/dns"
)
type result struct {
IPAddress string
Hostname string
}
func main() {
var (
flDomain = flag.String("domain", "", "the domain to perform guessing arguments against.")
flWordList = flag.String("wordlist", "", "Wordlist to use for guessing")
flWorkerCount = flag.Int("c", 100, "Amount of workers to user")
flServerAddr = flag.String("server", "1.1.1.1:53", "DNS server to use")
)
flag.Parse()
if *flDomain == "" || *flWordList == "" {
fmt.Println("-domain and -wordlist are required")
os.Exit(1)
}
fmt.Println(*flWorkerCount, *flServerAddr)
var results []result
fqdns := make(chan string, *flWorkerCount)
gather := make(chan []result)
tracker := make(chan empty)
fh, err := os.Open(*flWordList)
if err != nil {
panic(err)
}
defer fh.Close()
scanner := bufio.NewScanner(fh)
for i := 0; i < *flWorkerCount; i++ {
go worker(tracker, fqdns, gather, *flServerAddr) // this is where all the lookup is done
}
go func() {
for r := range gather {
results = append(results, r...)
}
var e empty
tracker <- e
}()
for scanner.Scan() {
fqdns <- fmt.Sprintf("%s.%s", scanner.Text(), *flDomain)
}
close(fqdns)
for i := 0; i < *flWorkerCount; i++ {
<-tracker
}
close(gather)
<-tracker
w := tabwriter.NewWriter(os.Stdout, 0, 8, 4, ' ', 0)
for _, r := range results {
fmt.Fprintf(w, "%s\t%s\n", r.Hostname, r.IPAddress)
}
w.Flush()
}
func lookupA(fqdn, serverAddr string) ([]string, error) {
var m dns.Msg
var ips []string
m.SetQuestion(dns.Fqdn(fqdn), dns.TypeA)
in, err := dns.Exchange(&m, serverAddr)
if err != nil {
return ips, err
}
for _, answer := range in.Answer {
if a, ok := answer.(*dns.A); ok {
ips = append(ips, a.A.String())
}
}
return ips, nil
}
func lookupCNAME(fqdn, serverAddr string) ([]string, error) {
var m dns.Msg
var fqdns []string
m.SetQuestion(dns.Fqdn(fqdn), dns.TypeCNAME)
in, err := dns.Exchange(&m, serverAddr)
if err != nil {
return fqdns, err
}
if len(in.Answer) < 1 {
return fqdns, errors.New("no answer")
}
for _, answer := range in.Answer {
if c, ok := answer.(*dns.CNAME); ok {
fqdns = append(fqdns, c.Target)
}
}
return fqdns, nil
}
func lookup(fqdn, serverAddr string) []result {
var results []result
var cfqdn = fqdn // not modifying original
for {
cnames, err := lookupCNAME(cfqdn, serverAddr)
if err == nil && len(cnames) > 0 {
cfqdn = cnames[0]
continue // process next cname
}
ips, err := lookupA(cfqdn, serverAddr)
if err != nil {
break // no A records for this hostname
}
for _, ip := range ips {
results = append(results, result{IPAddress: ip, Hostname: fqdn})
}
break
}
return results
}
type empty struct{}
func worker(tracker chan empty, fqdns chan string, gather chan []result, serverAddr string) {
for fqdn := range fqdns {
results := lookup(fqdn, serverAddr)
if len(results) > 0 {
gather <- results
}
}
var e empty
tracker <- e
}