11package main
22
33import (
4- "crypto/rand"
5- "encoding/hex"
64 "encoding/json"
75 "encoding/xml"
86 "flag"
97 "fmt"
108 "log"
119 "net"
1210 "os"
13- "sort"
14- "strings"
15- "sync"
1611
1712 "github.com/jrozner/sonar"
18- "github.com/miekg/dns"
1913)
2014
2115func main () {
@@ -35,7 +29,7 @@ func main() {
3529 flag .IntVar (& threads , "threads" , 4 , "number of threads for brute forcing" )
3630 flag .BoolVar (& zt , "zonetransfer" , false , "perform zone transfer" )
3731 flag .StringVar (& output , "output" , "" , "write output to specified file" )
38- flag .StringVar (& format , "format" , "" , "output format (json, xml, csv, nmap)" )
32+ flag .StringVar (& format , "format" , "" , "output format (json, xml, nmap)" )
3933 flag .Parse ()
4034
4135 if flag .NArg () != 1 {
@@ -54,7 +48,7 @@ func main() {
5448
5549 switch {
5650 case (zt == true ):
57- results = zoneTransfer (domain )
51+ results = sonar . ZoneTransfer (domain )
5852 case (brute == true ):
5953 var wl sonar.Wordlist
6054 if wordlist == "" {
@@ -66,7 +60,7 @@ func main() {
6660 }
6761 wl = sonar .NewFile (fp )
6862 }
69- results = bruteForce (threads , wl .GetChannel (), domain )
63+ results = sonar . BruteForce (threads , wl .GetChannel (), domain )
7064 }
7165
7266 if output == "" {
@@ -94,7 +88,7 @@ func writeOutput(output, format string, results sonar.Results) error {
9488 case "nmap" :
9589 serialized , err = sonar .ToNmap (results )
9690 default :
97- // TODO: return error for invalid format
91+ log . Fatal ( " invalid output format" )
9892 }
9993
10094 if err != nil {
@@ -109,135 +103,12 @@ func writeOutput(output, format string, results sonar.Results) error {
109103 return nil
110104}
111105
112- func zoneTransfer (domain string ) sonar.Results {
113- results := sonar .NewResultSet ()
114- fqdn := dns .Fqdn (domain )
115-
116- servers , err := net .LookupNS (domain )
117- if err != nil {
118- log .Fatal (err )
119- }
120-
121- for _ , server := range servers {
122- msg := new (dns.Msg )
123- msg .SetAxfr (fqdn )
124-
125- transfer := new (dns.Transfer )
126- answerChan , err := transfer .In (msg , net .JoinHostPort (server .Host , "53" ))
127- if err != nil {
128- log .Println (err )
129- continue
130- }
131-
132- for envelope := range answerChan {
133- if envelope .Error != nil {
134- log .Println (envelope .Error )
135- break
136- }
137-
138- for _ , rr := range envelope .RR {
139- switch v := rr .(type ) {
140- case * dns.A :
141- results .Add (strings .TrimRight (v .Header ().Name , "." ), v .A .String ())
142- case * dns.AAAA :
143- results .Add (strings .TrimRight (v .Header ().Name , "." ), v .AAAA .String ())
144- default :
145- }
146- }
147- }
148- }
149-
150- return results .Results ()
151- }
152-
153- func bruteForce (threads int , wordlist <- chan string , domain string ) sonar.Results {
154- fmt .Println ("[+] Detecting wildcard" )
155- wildcard , responses , err := detectWildcard (domain )
156- if err != nil {
157- // TODO: Fail loudly
158- }
159-
160- if wildcard {
161- fmt .Println ("[+] Wildcard detected for domain" )
162- }
163-
164- fmt .Println ("[+] Beginning brute force attempt" )
165-
166- results := make (sonar.Results , 0 )
167-
168- var wg sync.WaitGroup
169- for i := 0 ; i < threads ; i ++ {
170- wg .Add (1 )
171- go func (wordlist <- chan string ) {
172- nextWord:
173- for {
174- word , ok := <- wordlist
175- if ! ok {
176- break
177- }
178-
179- guess := word + "." + domain
180- answers , err := net .LookupHost (word + "." + domain )
181- if err != nil {
182- continue
183- }
184-
185- if wildcard {
186- for _ , answer := range answers {
187- if _ , ok := responses [answer ]; ok {
188- // it's a wildcard response
189- continue nextWord
190- }
191- }
192- }
193-
194- result := sonar.Result {Domain : guess , Addrs : answers }
195- results = append (results , result )
196- }
197-
198- wg .Done ()
199- }(wordlist )
200- }
201-
202- wg .Wait ()
203- sort .Sort (results )
204-
205- return results
206- }
207-
208106func printResults (results sonar.Results ) {
209107 for _ , result := range results {
210108 fmt .Println (result )
211109 }
212110}
213111
214- func detectWildcard (domain string ) (bool , map [string ]struct {}, error ) {
215- bytes := make ([]byte , 12 )
216- _ , err := rand .Read (bytes )
217- if err != nil {
218- return false , nil , err
219- }
220-
221- domain = fmt .Sprintf ("%s.%s" , hex .EncodeToString (bytes ), domain )
222-
223- answers , err := net .LookupHost (domain )
224- if err != nil {
225- if asserted , ok := err .(* net.DNSError ); ok && asserted .Err == "no such host" {
226- return false , nil , nil
227- }
228-
229- return false , nil , err
230- }
231-
232- responses := make (map [string ]struct {})
233-
234- for _ , answer := range answers {
235- responses [answer ] = struct {}{}
236- }
237-
238- return true , responses , nil
239- }
240-
241112func printUsage () {
242113 fmt .Fprintf (os .Stderr , "Usage: %s [options] domain\n " , os .Args [0 ])
243114 flag .PrintDefaults ()
0 commit comments