Skip to content

Commit

Permalink
Clean up main package
Browse files Browse the repository at this point in the history
  • Loading branch information
jrozner committed Feb 22, 2016
1 parent 1bc425a commit 3c2b4a8
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 133 deletions.
70 changes: 70 additions & 0 deletions bruteforce.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package sonar

import (
"fmt"
"net"
"sort"
"sync"
)

func BruteForce(threads int, wordlist <-chan string, domain string) Results {
results := make(Results, 0)

fmt.Println("[+] Detecting wildcard")
wildcard, responses, err := detectWildcard(domain)
if err != nil {
// TODO: Fail loudly
}

if wildcard {
fmt.Println("[+] Wildcard detected for domain")

wildcardResult := Result{
Domain: "*." + domain,
Addrs: keys(responses),
}

results = append(results, wildcardResult)
}

fmt.Println("[+] Beginning brute force attempt")

var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func(wordlist <-chan string) {
nextWord:
for {
word, ok := <-wordlist
if !ok {
break
}

guess := word + "." + domain
answers, err := net.LookupHost(word + "." + domain)
if err != nil {
continue
}

if wildcard {
for _, answer := range answers {
if _, ok := responses[answer]; ok {
// it's a wildcard response
continue nextWord
}
}
}

result := Result{Domain: guess, Addrs: answers}
results = append(results, result)
}

wg.Done()
}(wordlist)
}

wg.Wait()
sort.Sort(results)

return results
}
137 changes: 4 additions & 133 deletions cmd/sonar/main.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
package main

import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"encoding/xml"
"flag"
"fmt"
"log"
"net"
"os"
"sort"
"strings"
"sync"

"github.com/jrozner/sonar"
"github.com/miekg/dns"
)

func main() {
Expand All @@ -35,7 +29,7 @@ func main() {
flag.IntVar(&threads, "threads", 4, "number of threads for brute forcing")
flag.BoolVar(&zt, "zonetransfer", false, "perform zone transfer")
flag.StringVar(&output, "output", "", "write output to specified file")
flag.StringVar(&format, "format", "", "output format (json, xml, csv, nmap)")
flag.StringVar(&format, "format", "", "output format (json, xml, nmap)")
flag.Parse()

if flag.NArg() != 1 {
Expand All @@ -54,7 +48,7 @@ func main() {

switch {
case (zt == true):
results = zoneTransfer(domain)
results = sonar.ZoneTransfer(domain)
case (brute == true):
var wl sonar.Wordlist
if wordlist == "" {
Expand All @@ -66,7 +60,7 @@ func main() {
}
wl = sonar.NewFile(fp)
}
results = bruteForce(threads, wl.GetChannel(), domain)
results = sonar.BruteForce(threads, wl.GetChannel(), domain)
}

if output == "" {
Expand Down Expand Up @@ -94,7 +88,7 @@ func writeOutput(output, format string, results sonar.Results) error {
case "nmap":
serialized, err = sonar.ToNmap(results)
default:
// TODO: return error for invalid format
log.Fatal("invalid output format")
}

if err != nil {
Expand All @@ -109,135 +103,12 @@ func writeOutput(output, format string, results sonar.Results) error {
return nil
}

func zoneTransfer(domain string) sonar.Results {
results := sonar.NewResultSet()
fqdn := dns.Fqdn(domain)

servers, err := net.LookupNS(domain)
if err != nil {
log.Fatal(err)
}

for _, server := range servers {
msg := new(dns.Msg)
msg.SetAxfr(fqdn)

transfer := new(dns.Transfer)
answerChan, err := transfer.In(msg, net.JoinHostPort(server.Host, "53"))
if err != nil {
log.Println(err)
continue
}

for envelope := range answerChan {
if envelope.Error != nil {
log.Println(envelope.Error)
break
}

for _, rr := range envelope.RR {
switch v := rr.(type) {
case *dns.A:
results.Add(strings.TrimRight(v.Header().Name, "."), v.A.String())
case *dns.AAAA:
results.Add(strings.TrimRight(v.Header().Name, "."), v.AAAA.String())
default:
}
}
}
}

return results.Results()
}

func bruteForce(threads int, wordlist <-chan string, domain string) sonar.Results {
fmt.Println("[+] Detecting wildcard")
wildcard, responses, err := detectWildcard(domain)
if err != nil {
// TODO: Fail loudly
}

if wildcard {
fmt.Println("[+] Wildcard detected for domain")
}

fmt.Println("[+] Beginning brute force attempt")

results := make(sonar.Results, 0)

var wg sync.WaitGroup
for i := 0; i < threads; i++ {
wg.Add(1)
go func(wordlist <-chan string) {
nextWord:
for {
word, ok := <-wordlist
if !ok {
break
}

guess := word + "." + domain
answers, err := net.LookupHost(word + "." + domain)
if err != nil {
continue
}

if wildcard {
for _, answer := range answers {
if _, ok := responses[answer]; ok {
// it's a wildcard response
continue nextWord
}
}
}

result := sonar.Result{Domain: guess, Addrs: answers}
results = append(results, result)
}

wg.Done()
}(wordlist)
}

wg.Wait()
sort.Sort(results)

return results
}

func printResults(results sonar.Results) {
for _, result := range results {
fmt.Println(result)
}
}

func detectWildcard(domain string) (bool, map[string]struct{}, error) {
bytes := make([]byte, 12)
_, err := rand.Read(bytes)
if err != nil {
return false, nil, err
}

domain = fmt.Sprintf("%s.%s", hex.EncodeToString(bytes), domain)

answers, err := net.LookupHost(domain)
if err != nil {
if asserted, ok := err.(*net.DNSError); ok && asserted.Err == "no such host" {
return false, nil, nil
}

return false, nil, err
}

responses := make(map[string]struct{})

for _, answer := range answers {
responses[answer] = struct{}{}
}

return true, responses, nil
}

func printUsage() {
fmt.Fprintf(os.Stderr, "Usage: %s [options] domain\n", os.Args[0])
flag.PrintDefaults()
Expand Down
44 changes: 44 additions & 0 deletions wildcard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package sonar

import (
"crypto/rand"
"encoding/hex"
"fmt"
"net"
)

func detectWildcard(domain string) (bool, map[string]struct{}, error) {
bytes := make([]byte, 12)
_, err := rand.Read(bytes)
if err != nil {
return false, nil, err
}

domain = fmt.Sprintf("%s.%s", hex.EncodeToString(bytes), domain)

answers, err := net.LookupHost(domain)
if err != nil {
if asserted, ok := err.(*net.DNSError); ok && asserted.Err == "no such host" {
return false, nil, nil
}

return false, nil, err
}

responses := make(map[string]struct{})

for _, answer := range answers {
responses[answer] = struct{}{}
}

return true, responses, nil
}

func keys(set map[string]struct{}) []string {
keys := make([]string, 0, len(set))
for key, _ := range set {
keys = append(keys, key)
}

return keys
}
50 changes: 50 additions & 0 deletions zonetransfer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package sonar

import (
"log"
"net"
"strings"

"github.com/miekg/dns"
)

func ZoneTransfer(domain string) Results {
results := NewResultSet()
fqdn := dns.Fqdn(domain)

servers, err := net.LookupNS(domain)
if err != nil {
log.Fatal(err)
}

for _, server := range servers {
msg := new(dns.Msg)
msg.SetAxfr(fqdn)

transfer := new(dns.Transfer)
answerChan, err := transfer.In(msg, net.JoinHostPort(server.Host, "53"))
if err != nil {
log.Println(err)
continue
}

for envelope := range answerChan {
if envelope.Error != nil {
log.Println(envelope.Error)
break
}

for _, rr := range envelope.RR {
switch v := rr.(type) {
case *dns.A:
results.Add(strings.TrimRight(v.Header().Name, "."), v.A.String())
case *dns.AAAA:
results.Add(strings.TrimRight(v.Header().Name, "."), v.AAAA.String())
default:
}
}
}
}

return results.Results()
}

0 comments on commit 3c2b4a8

Please sign in to comment.