210 lines
6.4 KiB
Go
Executable File
210 lines
6.4 KiB
Go
Executable File
package subf
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strings"
|
|
"github.com/subfinder/subfinder/libsubfinder/engines/passive"
|
|
"github.com/subfinder/subfinder/libsubfinder/helper"
|
|
)
|
|
|
|
// Subfinder represent a subdomain enumerator instance
|
|
type Subfinder struct {
|
|
State *helper.State
|
|
}
|
|
|
|
// NewSubfinder instantiate a new subfinder
|
|
func NewSubfinder() *Subfinder {
|
|
return &Subfinder{
|
|
State: helper.InitState(),
|
|
}
|
|
}
|
|
|
|
// Init setup the instance
|
|
func (s *Subfinder) Init() {
|
|
s.parseConfig()
|
|
s.parseSetting()
|
|
s.parseComResolver()
|
|
s.parseListResolver()
|
|
s.parseBruteForce()
|
|
s.setCommonResolver()
|
|
s.setOutput()
|
|
s.setDomain()
|
|
}
|
|
|
|
func (s *Subfinder) parseConfig() {
|
|
if s.State.SetConfig == "none" {
|
|
return
|
|
}
|
|
|
|
setConfig := strings.Split(s.State.SetConfig, ",")
|
|
|
|
// Build Configuration path
|
|
home := helper.GetHomeDir()
|
|
path := home + "/.config/subfinder/config.json"
|
|
|
|
for _, config := range setConfig {
|
|
object := strings.Split(config, "=")
|
|
|
|
// Change value dynamically using reflect package
|
|
if strings.EqualFold(object[0], "virustotalapikey") {
|
|
reflect.ValueOf(&s.State.ConfigState).Elem().FieldByName("VirustotalAPIKey").SetString(object[1])
|
|
} else if strings.EqualFold(object[0], "passivetotalusername") {
|
|
reflect.ValueOf(&s.State.ConfigState).Elem().FieldByName("PassivetotalUsername").SetString(object[1])
|
|
} else if strings.EqualFold(object[0], "passivetotalkey") {
|
|
reflect.ValueOf(&s.State.ConfigState).Elem().FieldByName("PassivetotalKey").SetString(object[1])
|
|
} else if strings.EqualFold(object[0], "securitytrailskey") {
|
|
reflect.ValueOf(&s.State.ConfigState).Elem().FieldByName("SecurityTrailsKey").SetString(object[1])
|
|
} else if strings.EqualFold(object[0], "riddleremail") {
|
|
reflect.ValueOf(&s.State.ConfigState).Elem().FieldByName("RiddlerEmail").SetString(object[1])
|
|
} else if strings.EqualFold(object[0], "riddlerpassword") {
|
|
reflect.ValueOf(&s.State.ConfigState).Elem().FieldByName("RiddlerPassword").SetString(object[1])
|
|
} else if strings.EqualFold(object[0], "censysusername") {
|
|
reflect.ValueOf(&s.State.ConfigState).Elem().FieldByName("CensysUsername").SetString(object[1])
|
|
} else if strings.EqualFold(object[0], "censyssecret") {
|
|
reflect.ValueOf(&s.State.ConfigState).Elem().FieldByName("CensysSecret").SetString(object[1])
|
|
} else if strings.EqualFold(object[0], "shodanapikey") {
|
|
reflect.ValueOf(&s.State.ConfigState).Elem().FieldByName("ShodanAPIKey").SetString(object[1])
|
|
}
|
|
|
|
configJSON, _ := json.MarshalIndent(s.State.ConfigState, "", " ")
|
|
err := ioutil.WriteFile(path, configJSON, 0644)
|
|
if err != nil {
|
|
fmt.Printf("\n\n[!] Error : %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Printf("Successfully configured %s%s%s=>%s\n", helper.Info, object[0], helper.Reset, object[1])
|
|
}
|
|
}
|
|
|
|
func (s *Subfinder) parseSetting() {
|
|
if s.State.SetSetting == "none" {
|
|
return
|
|
}
|
|
|
|
setSetting := strings.Split(s.State.SetSetting, ",")
|
|
|
|
for _, setting := range setSetting {
|
|
object := strings.Split(setting, "=")
|
|
|
|
// Change value dynamically using reflect package
|
|
reflect.ValueOf(&s.State.CurrentSettings).Elem().FieldByName(object[0]).SetString(object[1])
|
|
if !s.State.Silent && s.State.Verbose {
|
|
fmt.Printf("Successfully Set %s%s%s=>%s\n", helper.Info, object[0], helper.Reset, object[1])
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *Subfinder) parseComResolver() {
|
|
if s.State.ComResolver == "" {
|
|
return
|
|
}
|
|
|
|
setResolvers := strings.Split(s.State.ComResolver, ",")
|
|
|
|
s.State.LoadResolver = append(s.State.LoadResolver, setResolvers...)
|
|
}
|
|
|
|
func (s *Subfinder) parseListResolver() {
|
|
if s.State.ListResolver == "" {
|
|
return
|
|
}
|
|
|
|
// Load the resolvers from file
|
|
file, err := os.Open(s.State.ListResolver)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "\nerror: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
|
|
for scanner.Scan() {
|
|
s.State.LoadResolver = append(s.State.LoadResolver, scanner.Text())
|
|
}
|
|
}
|
|
|
|
func (s *Subfinder) parseBruteForce() {
|
|
if s.State.Bruteforce == true {
|
|
if s.State.Wordlist == "" {
|
|
if !s.State.Silent {
|
|
fmt.Printf("%s-> Must provide a wordlist when bruteforce is enabled.%s\nTry %s'./subfinder -h'%s for more information\n", helper.Bad, helper.Reset, helper.Info, helper.Reset)
|
|
}
|
|
os.Exit(1)
|
|
}
|
|
if !helper.Exists(s.State.Wordlist) {
|
|
if !s.State.Silent {
|
|
fmt.Printf("%s-> The wordlist file '%s' does not exist.%s\n", helper.Bad, s.State.Wordlist, helper.Reset)
|
|
}
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *Subfinder) setCommonResolver() {
|
|
// Use the default resolvers
|
|
if s.State.ComResolver != "" || s.State.ListResolver != "" {
|
|
return
|
|
}
|
|
|
|
s.State.LoadResolver = append(s.State.LoadResolver, "1.1.1.1")
|
|
s.State.LoadResolver = append(s.State.LoadResolver, "1.0.0.1")
|
|
s.State.LoadResolver = append(s.State.LoadResolver, "8.8.8.8")
|
|
s.State.LoadResolver = append(s.State.LoadResolver, "8.8.4.4")
|
|
s.State.LoadResolver = append(s.State.LoadResolver, "9.9.9.9")
|
|
s.State.LoadResolver = append(s.State.LoadResolver, "9.9.9.10")
|
|
s.State.LoadResolver = append(s.State.LoadResolver, "208.67.222.222")
|
|
s.State.LoadResolver = append(s.State.LoadResolver, "208.67.220.220")
|
|
}
|
|
|
|
func (s *Subfinder) setOutput() {
|
|
if s.State.Output != "" {
|
|
dir := filepath.Dir(s.State.Output)
|
|
if !helper.Exists(dir) {
|
|
fmt.Printf("\n%s-> The specified output directory does not exists !%s\n", helper.Yellow, helper.Reset)
|
|
} else {
|
|
// Get a handle to the out file if it is not json
|
|
if !s.State.AquatoneJSON && !s.State.IsJSON {
|
|
var err error
|
|
s.State.OutputHandle, err = os.OpenFile(s.State.Output, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
} else if s.State.OutputDir != "" {
|
|
if !helper.Exists(s.State.OutputDir) {
|
|
fmt.Printf("\n%s-> The specified output directory does not exists !%s\n", helper.Yellow, helper.Reset)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *Subfinder) setDomain() {
|
|
if s.State.Domain == "" && s.State.DomainList == "" {
|
|
if !s.State.Silent {
|
|
fmt.Printf("%s-> Missing \"domain\" argument %s\nTry %s'./subfinder -h'%s for more information\n", helper.Bad, helper.Reset, helper.Info, helper.Reset)
|
|
}
|
|
os.Exit(1)
|
|
}
|
|
|
|
if s.State.DomainList != "" && !helper.Exists(s.State.DomainList) {
|
|
if !s.State.Silent {
|
|
fmt.Printf("%s-> The domainlist file '%s' does not exist.%s\n", helper.Bad, s.State.DomainList, helper.Reset)
|
|
}
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// PassiveEnumeration execute a passive enumeration
|
|
func (s *Subfinder) PassiveEnumeration() []string {
|
|
return passive.Enumerate(s.State)
|
|
}
|