Created
February 5, 2021 11:34
-
-
Save itxsoumya/3b22972578c8852b80576e7c9e897da9 to your computer and use it in GitHub Desktop.
find out subdomain using golang :)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"errors" | |
"flag" | |
"fmt" | |
"os" | |
"github.com/miekg/dns" | |
) | |
type empty struct{} | |
type result struct { | |
IPAddress string | |
Hostname string | |
} | |
func main() { | |
var ( | |
flDomain = flag.String("d", "", "The Domain to perform guessing against") | |
flWordlist = flag.String("w", "", "The wordlist use for guessing") | |
flWorkerCount = flag.Int("c", 1000, "The ammount of workers to use") | |
flServerAddr = flag.String("s", "8.8.8.8:53", "The dns Server to use") | |
) | |
flag.Parse() | |
checkArgs(flDomain, flWordlist) | |
// 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) | |
} | |
for scanner.Scan() { | |
fqdns <- fmt.Sprintf("%s.%s", scanner.Text(), *flDomain) | |
} | |
go func() { | |
for r := range gather { | |
results = append(results, r...) | |
} | |
var e empty | |
tracker <- e | |
}() | |
close(fqdns) | |
for i := 0; i < *flWorkerCount; i++ { | |
<-tracker | |
} | |
close(gather) | |
<-tracker | |
for _, r := range results { | |
fmt.Printf("%s\t%s\n", r.Hostname, r.IPAddress) | |
} | |
} | |
// returns list of ip address | |
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 | |
} | |
if len(in.Answer) < 1 { | |
return ips, errors.New("no answer") | |
} | |
for _, answer := range in.Answer { | |
if a, ok := answer.(*dns.A); ok { | |
ips = append(ips, a.A.String()) | |
} | |
} | |
return ips, nil | |
} | |
// returns a list of hostnames | |
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 | |
for { | |
cnames, err := lookupCNAME(cfqdn, serverAddr) | |
if err == nil && len(cnames) > 0 { | |
cfqdn = cnames[0] | |
continue // we hae to process the next CNAME | |
} | |
ips, err := lookupA(cfqdn, serverAddr) | |
if err != nil { | |
break // there are no records for this host name | |
} | |
for _, ip := range ips { | |
results = append(results, result{IPAddress: ip, Hostname: fqdn}) | |
} | |
break // we have processed all the requests | |
} | |
return results | |
} | |
// worker function | |
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 | |
} | |
func checkArgs(d *string, w *string) { | |
if *d == "" || *w == "" { | |
fmt.Println("domain and wordlist are required") | |
os.Exit(1) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
find sub domain using golang :)