2025-05-14 22:00:38 -04:00
|
|
|
package cmd
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"dehasher/internal/sqlite"
|
|
|
|
|
"dehasher/internal/whois"
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
// WHOIS command flags
|
|
|
|
|
whoisDomain string
|
|
|
|
|
whoisIPAddress string
|
|
|
|
|
whoisMXAddress string
|
|
|
|
|
whoisNSAddress string
|
|
|
|
|
whoisInclude string
|
|
|
|
|
whoisExclude string
|
|
|
|
|
whoisReverseType string
|
|
|
|
|
whoisOutputFormat string
|
|
|
|
|
whoisShowCredits bool
|
|
|
|
|
whoisHistory bool
|
|
|
|
|
whoisSubdomainScan bool
|
|
|
|
|
|
|
|
|
|
// WHOIS command
|
|
|
|
|
whoisCmd = &cobra.Command{
|
|
|
|
|
Use: "whois",
|
|
|
|
|
Short: "Dehashed WHOIS lookups and reverse WHOIS searches",
|
|
|
|
|
Long: `Perform WHOIS lookups, history searches, reverse WHOIS searches, IP lookups, MX lookups, NS lookups, and subdomain scans.`,
|
|
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
2025-05-15 14:43:13 -04:00
|
|
|
key := getStoredApiKey()
|
2025-05-14 22:00:38 -04:00
|
|
|
|
|
|
|
|
// Validate credentials
|
|
|
|
|
if key == "" {
|
2025-05-15 14:43:13 -04:00
|
|
|
fmt.Println("API key is required. Set the key with the \"set-key\" command. [dehasher set-key <api_key>]")
|
2025-05-14 22:00:38 -04:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Show credits if requested
|
|
|
|
|
if whoisShowCredits {
|
|
|
|
|
fmt.Println("[*] Getting WHOIS credits...")
|
|
|
|
|
credits, err := whois.GetWHOISCredits(key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("get_whois_credits",
|
|
|
|
|
zap.String("message", "failed to get whois credits"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error getting WHOIS credits: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("WHOIS Credits: %d\n", credits.WhoisCredits)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if domain is provided for history and subdomain scan
|
|
|
|
|
if whoisHistory || whoisSubdomainScan {
|
|
|
|
|
if whoisDomain == "" {
|
|
|
|
|
fmt.Println("Domain is required for history and subdomain scan.")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Determine which operation to perform based on flags
|
|
|
|
|
if whoisDomain != "" {
|
|
|
|
|
fmt.Println("[*] Performing WHOIS lookup...")
|
|
|
|
|
// Domain lookup
|
|
|
|
|
result, err := whois.WhoisSearch(whoisDomain, key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("whois_search",
|
|
|
|
|
zap.String("message", "failed to perform whois search"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error performing WHOIS lookup: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-05-15 14:43:13 -04:00
|
|
|
|
2025-05-14 22:00:38 -04:00
|
|
|
// Fix the output format to use proper formatting
|
|
|
|
|
fmt.Printf("WHOIS Lookup Result:\n%+v\n", result.Data.WhoisRecord)
|
|
|
|
|
|
|
|
|
|
// Store the record
|
|
|
|
|
err = sqlite.StoreWhoisRecord(result.Data.WhoisRecord)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("store_whois_record",
|
|
|
|
|
zap.String("message", "failed to store whois record"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error storing WHOIS record: %v\n", err)
|
|
|
|
|
// Continue execution even if storage fails
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if whoisHistory {
|
|
|
|
|
fmt.Println("[*] Performing WHOIS history search...")
|
|
|
|
|
// Perform history search
|
|
|
|
|
history, err := whois.WhoisHistory(whoisDomain, key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("whois_history",
|
|
|
|
|
zap.String("message", "failed to perform whois history lookup"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error performing WHOIS history lookup: %v\n", err)
|
|
|
|
|
} else {
|
|
|
|
|
fmt.Println("\nWHOIS History:")
|
|
|
|
|
fmt.Println(history)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = sqlite.StoreHistoryRecord(history.Data.Records)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("store_history_record",
|
|
|
|
|
zap.String("message", "failed to store history record"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error storing WHOIS history record: %v\n", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Perform subdomain scan
|
|
|
|
|
if whoisSubdomainScan {
|
|
|
|
|
fmt.Println("[*] Performing WHOIS subdomain scan...")
|
|
|
|
|
subdomains, err := whois.WhoisSubdomainScan(whoisDomain, key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("whois_subdomain_scan",
|
|
|
|
|
zap.String("message", "failed to perform subdomain scan"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error performing subdomain scan: %v\n", err)
|
|
|
|
|
} else {
|
|
|
|
|
fmt.Println("\nSubdomain Scan:")
|
|
|
|
|
fmt.Println(subdomains)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = sqlite.StoreSubdomainRecord(subdomains.Data.Result.Records)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("store_subdomain_record",
|
|
|
|
|
zap.String("message", "failed to store subdomain record"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error storing WHOIS subdomain record: %v\n", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get credits
|
|
|
|
|
credits, err := whois.GetWHOISCredits(key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("get_whois_credits",
|
|
|
|
|
zap.String("message", "failed to get whois credits"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error getting WHOIS credits: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("\nWHOIS Credits Remaining: %d\n", credits.WhoisCredits)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if whoisIPAddress != "" {
|
|
|
|
|
fmt.Println("[*] Performing reverse IP lookup...")
|
|
|
|
|
// IP lookup
|
|
|
|
|
result, err := whois.WhoisIP(whoisIPAddress, key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("whois_ip",
|
|
|
|
|
zap.String("message", "failed to perform ip lookup"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error performing IP lookup: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Println("IP Lookup Result:")
|
|
|
|
|
fmt.Println(string(result))
|
|
|
|
|
|
|
|
|
|
// Get credits
|
|
|
|
|
credits, err := whois.GetWHOISCredits(key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("get_whois_credits",
|
|
|
|
|
zap.String("message", "failed to get whois credits"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error getting WHOIS credits: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("\nWHOIS Credits Remaining: %d\n", credits.WhoisCredits)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if whoisMXAddress != "" {
|
|
|
|
|
fmt.Println("[*] Performing reverse MX lookup...")
|
|
|
|
|
// MX lookup
|
|
|
|
|
result, err := whois.WhoisMX(whoisMXAddress, key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("whois_mx",
|
|
|
|
|
zap.String("message", "failed to perform mx lookup"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error performing MX lookup: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// todo unmarshal mx lookup
|
|
|
|
|
fmt.Println("MX Lookup Result:")
|
|
|
|
|
fmt.Println(result)
|
|
|
|
|
|
|
|
|
|
// Get credits
|
|
|
|
|
credits, err := whois.GetWHOISCredits(key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("get_whois_credits",
|
|
|
|
|
zap.String("message", "failed to get whois credits"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error getting WHOIS credits: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("\nWHOIS Credits Remaining: %d\n", credits.WhoisCredits)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if whoisNSAddress != "" {
|
|
|
|
|
fmt.Println("[*] Performing reverse NS lookup...")
|
|
|
|
|
// NS lookup
|
|
|
|
|
result, err := whois.WhoisNS(whoisNSAddress, key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("whois_ns",
|
|
|
|
|
zap.String("message", "failed to perform ns lookup"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error performing NS lookup: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Println("NS Lookup Result:")
|
|
|
|
|
fmt.Println(result)
|
|
|
|
|
|
|
|
|
|
// Get credits
|
|
|
|
|
credits, err := whois.GetWHOISCredits(key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
zap.L().Error("get_whois_credits",
|
|
|
|
|
zap.String("message", "failed to get whois credits"),
|
|
|
|
|
zap.Error(err),
|
|
|
|
|
)
|
|
|
|
|
fmt.Printf("Error getting WHOIS credits: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("\nWHOIS Credits Remaining: %d\n", credits.WhoisCredits)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if whoisInclude != "" || whoisExclude != "" {
|
|
|
|
|
// Reverse WHOIS
|
|
|
|
|
includeTerms := []string{}
|
|
|
|
|
if whoisInclude != "" {
|
|
|
|
|
includeTerms = strings.Split(whoisInclude, ",")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
excludeTerms := []string{}
|
|
|
|
|
if whoisExclude != "" {
|
|
|
|
|
excludeTerms = strings.Split(whoisExclude, ",")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if whoisReverseType == "" {
|
|
|
|
|
whoisReverseType = "registrant"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fmt.Println("[*] Performing reverse WHOIS lookup...")
|
|
|
|
|
result, err := whois.ReverseWHOIS(includeTerms, excludeTerms, whoisReverseType, key)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("Error performing reverse WHOIS: %v\n", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Println("Reverse WHOIS Result:")
|
|
|
|
|
fmt.Println(result)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If no specific operation was requested
|
|
|
|
|
cmd.Help()
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
// Add whois command to root command
|
|
|
|
|
rootCmd.AddCommand(whoisCmd)
|
|
|
|
|
|
|
|
|
|
// Add flags specific to whois command
|
|
|
|
|
whoisCmd.Flags().StringVarP(&whoisDomain, "domain", "d", "", "Domain for WHOIS lookup, history search, and subdomain scan")
|
|
|
|
|
whoisCmd.Flags().StringVarP(&whoisIPAddress, "ip", "i", "", "IP address for reverse IP lookup")
|
|
|
|
|
whoisCmd.Flags().StringVarP(&whoisMXAddress, "mx", "m", "", "MX address for reverse MX lookup")
|
|
|
|
|
whoisCmd.Flags().StringVarP(&whoisNSAddress, "ns", "n", "", "NS address for reverse NS lookup")
|
|
|
|
|
whoisCmd.Flags().StringVarP(&whoisInclude, "include", "I", "", "Terms to include in reverse WHOIS search (comma-separated)")
|
|
|
|
|
whoisCmd.Flags().StringVarP(&whoisExclude, "exclude", "E", "", "Terms to exclude in reverse WHOIS search (comma-separated)")
|
|
|
|
|
whoisCmd.Flags().StringVarP(&whoisReverseType, "type", "t", "registrant", "Type of reverse WHOIS search (registrant, email, organization, address, phone)")
|
|
|
|
|
whoisCmd.Flags().StringVarP(&whoisOutputFormat, "format", "f", "text", "Output format (text, json)")
|
|
|
|
|
whoisCmd.Flags().BoolVarP(&whoisShowCredits, "credits", "c", false, "Show remaining WHOIS credits")
|
|
|
|
|
whoisCmd.Flags().BoolVarP(&whoisHistory, "history", "H", false, "Perform WHOIS history search [25 Credits]")
|
|
|
|
|
whoisCmd.Flags().BoolVarP(&whoisSubdomainScan, "subdomains", "s", false, "Perform WHOIS subdomain scan")
|
|
|
|
|
}
|