Projects STRLCPY metabigor Commits 7f3d0dab
🤬
Showing first 32 files as there are too many
  • ■ ■ ■ ■ ■
    .gitignore
    skipped 1 lines
    2 2  .goreleaser.yml
    3 3  .idea
    4 4  dist
    5  -out*
     5 +out*dist/
     6 + 
  • ■ ■ ■ ■ ■
    Makefile
    skipped 15 lines
    16 16  run:
    17 17   $(GO) $(GOFLAGS) run *.go
    18 18   
     19 +release:
     20 + VERSION=$(cat $GOPATH/src/github.com/j3ssie/metabigor/core/version.go | grep 'VERSION =' | cut -d '"' -f 2)
     21 + echo "Building release version $VERSION"
     22 + git tag -a $VERSION-m "Release $VERSION"
     23 + git push origin $VERSION
    19 24  update:
    20 25   rm -rf $(GOPATH)/src/github.com/j3ssie/metabigor/static/ip2asn-combined.tsv.gz
    21 26   wget -q https://iptoasn.com/data/ip2asn-combined.tsv.gz -O $(GOPATH)/src/github.com/j3ssie/metabigor/static/ip2asn-combined.tsv.gz
    skipped 5 lines
  • ■ ■ ■ ■ ■
    README.md
    1 1  <p align="center">
    2 2   <img alt="Metabigor" src="https://user-images.githubusercontent.com/23289085/143042137-28f8e7e5-e485-4dc8-a09b-10759a593210.png" height="140" />
    3  - <p align="center">Intelligence Tool but without API key</p>
     3 + <br />
     4 + <strong>Metabigor - An Intelligence Tool but without API key</strong>
     5 + 
    4 6   <p align="center">
    5  - <a href="https://github.com/j3ssie/metabigor"><img alt="Release" src="https://img.shields.io/github/v/release/j3ssie/metabigor.svg"></a>
    6  - <a href=""><img alt="Software License" src="https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square"></a>
     7 + <a href="https://docs.osmedeus.org/donation/"><img src="https://img.shields.io/badge/Sponsors-0078D4?style=for-the-badge&logo=GitHub-Sponsors&logoColor=39ff14&labelColor=black&color=black"></a>
     8 + <a href="https://twitter.com/OsmedeusEngine"><img src="https://img.shields.io/badge/%40OsmedeusEngine-0078D4?style=for-the-badge&logo=Twitter&logoColor=39ff14&labelColor=black&color=black"></a>
     9 + <a href="https://github.com/j3ssie/osmedeus/releases"><img src="https://img.shields.io/github/release/j3ssie/metabigor?style=for-the-badge&labelColor=black&color=2fc414&logo=Github"></a>
    7 10   </p>
    8 11  </p>
    9 12   
    10  -## What is Metabigor?
     13 +***
     14 + 
     15 + 
     16 +# What is Metabigor?
    11 17   
    12 18  Metabigor is Intelligence tool, its goal is to do OSINT tasks and more but without any API key.
    13 19   
    14  -## Installation
     20 +# Installation
    15 21   
    16  -```
     22 +```shell
    17 23  go install github.com/j3ssie/metabigor@latest
    18 24  ```
    19 25   
    20  -## Main features
     26 +# Main features
    21 27   
    22 28  - Searching information about IP Address, ASN and Organization.
    23  -- Wrapper for running rustscan, masscan and nmap on IP/CIDR.
    24  -- Finding more root domains by searching certificate information on crt.sh
    25  -- Get Summary about IP address (powered by [@thebl4ckturtle](https://github.com/theblackturtle))
    26  -- Do searching from the command line on some search engine.
     29 +- Wrapper for running rustscan, masscan and nmap more efficient on IP/CIDR.
     30 +- Finding more related domains of the target by applying various techniques (certificate, whois, Google Analytics, etc).
     31 +- Get Summary about IP address (powered by [**@thebl4ckturtle**](https://github.com/theblackturtle))
    27 32   
    28 33   
    29  -## Example Commands
     34 +# Usage
    30 35   
    31  -```
    32  -Examples Commands:
     36 +## Discovery IP of a company/organization - `metabigor net`
     37 + 
     38 +The difference between net and **netd** command is that **netd** will get the dynamic result from the third-party source while net command will get the static result from the database.
     39 + 
     40 + 
     41 +```bash
    33 42  # discovery IP of a company/organization
    34 43  echo "company" | metabigor net --org -o /tmp/result.txt
    35 44   
    skipped 1 lines
    37 46  echo "ASN1111" | metabigor net --asn -o /tmp/result.txt
    38 47  cat list_of_ASNs | metabigor net --asn -o /tmp/result.txt
    39 48   
     49 +echo "ASN1111" | metabigor netd --asn -o /tmp/result.txt
     50 +```
     51 + 
     52 +***
     53 + 
     54 +## Finding more related domains of the target by applying various techniques (certificate, whois, Google Analytics, etc) - `metabigor related`
     55 + 
     56 +> Note some of the results are not 100% accurate. Please do a manual check first before put it directly to other tools to scan.
     57 + 
     58 +Some specific technique require different input so please see the usage of each technique.
     59 + 
     60 + 
     61 +## Using certificate to find related domains on crt.sh
     62 + 
     63 +```bash
     64 +# Getting more related domains by searching for certificate info
     65 +echo 'Target Inc' | metabigor cert --json | jq -r '.Domain' | unfurl format %r.%t | sort -u # this is old command
     66 + 
     67 +# Getting more related domains by searching for certificate info
     68 +echo 'example Inc' | metabigor related -s 'cert'
     69 +```
     70 + 
     71 +## Wrapper for running rustscan, masscan and nmap more efficient on IP/CIDR - `metabigor scan`
     72 + 
     73 +This command will require you to install `masscan`, `rustscan` and `nmap` first or at least the pre-scan result of them.
     74 + 
     75 +```bash
    40 76  # Only run masscan full ports
    41 77  echo '1.2.3.4/24' | metabigor scan -o result.txt
    42 78   
    43 79  # only run nmap detail scan based on pre-scan data
    44 80  echo '1.2.3.4:21' | metabigor scan -s -c 10
    45 81  echo '1.2.3.4:21' | metabigor scan --tmp /tmp/raw-result/ -s -o result.txt
     82 + 
     83 +# run nmap detail scan based on pre-scan data of rustscan
    46 84  echo '1.2.3.4 -> [80,443,2222]' | metabigor scan -R
    47 85   
    48 86  # only run scan with zmap
    49 87  cat ranges.txt | metabigor scan -p '443,80' -z
     88 +```
    50 89   
    51  -# certificate search info on crt.sh
    52  -echo 'Target' | metabigor cert
     90 +***
    53 91   
    54  -# find more root domains
    55  -echo 'Target Inc' | metabigor cert --json | jq -r '.Domain' | unfurl format %r.%t | sort -u
     92 +## Using Reverse Whois to find related domains
    56 93   
    57  -# Get Summary about IP address (powered by @thebl4ckturtle)
     94 +```bash
     95 +echo 'example.com' | metabigor related -s 'whois'
     96 +```
     97 + 
     98 +## Getting more related by searching for Google Analytics ID
     99 + 
     100 +```bash
     101 +# Get it directly from the URL
     102 +echo 'https://example.com' | metabigor related -s 'google-analytic'
     103 + 
     104 +# You can also search it directly from the UA ID too
     105 +metabigor tld -s 'google-analytic' -i 'UA-9152XXX' --debug
     106 +```
     107 + 
     108 +***
     109 + 
     110 +## Get Summary about IP address (powered by [**@thebl4ckturtle**](https://github.com/theblackturtle)) - `metabigor ipc`
     111 + 
     112 +This will show you the summary of the IP address provided like ASN, Organization, Country, etc.
     113 + 
     114 + 
     115 +```bash
    58 116  cat list_of_ips.txt | metabigor ipc --json
    59 117  ```
    60 118   
    61  -## Demo
     119 + 
     120 +## Extract Shodan IPInfo from internetdb.shodan.io
     121 + 
     122 +```bash
     123 +echo '1.2.3.4' | metabigor ip -open
     124 +1.2.3.4:80
     125 +1.2.3.4:443
     126 + 
     127 +# lookup CIDR range
     128 +echo '1.2.3.4/24' | metabigor ip -open -c 20
     129 +1.2.3.4:80
     130 +1.2.3.5:80
     131 + 
     132 +# get raw JSON response
     133 +echo '1.2.3.4' | metabigor ip -json
     134 +```
     135 + 
     136 + 
     137 +# Demo
    62 138   
    63 139  [![asciicast](https://asciinema.org/a/301745.svg)](https://asciinema.org/a/301745)
    64 140   
     141 +***
    65 142   
    66  -## Painless integrate Jaeles into your recon workflow?
     143 +# Painless integrate Jaeles into your recon workflow?
    67 144   
    68 145  <p align="center">
    69 146   <img alt="OsmedeusEngine" src="https://raw.githubusercontent.com/osmedeus/assets/main/logo-transparent.png" height="200" />
    skipped 2 lines
    72 149   </p>
    73 150  </p>
    74 151   
    75  - 
    76  -## Credits
     152 +# Credits
    77 153   
    78 154  Logo from [flaticon](https://image.flaticon.com/icons/svg/1789/1789851.svg)
    79 155  by [freepik](https://www.flaticon.com/authors/freepik)
    80 156   
    81  -## Disclaimer
     157 +# Disclaimer
    82 158   
    83 159  This tool is for educational purposes only. You are responsible for your own actions. If you mess something up or break
    84 160  any laws while using this software, it's your fault, and your fault only.
    85 161   
    86  -## License
     162 +# License
    87 163   
    88 164  `Metabigor` is made with ♥ by [@j3ssiejjj](https://twitter.com/j3ssiejjj) and it is released under the MIT license.
    89 165   
    90  -## Donation
     166 +# Donation
    91 167   
    92 168  [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://paypal.me/j3ssiejjj)
    93 169   
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    cmd/cert.go
    1 1  package cmd
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "os"
    6  - "strings"
    7  - "sync"
     4 + "fmt"
     5 + "strings"
     6 + "sync"
    8 7   
    9  - "github.com/j3ssie/metabigor/core"
    10  - "github.com/j3ssie/metabigor/modules"
    11  - "github.com/spf13/cobra"
     8 + "github.com/j3ssie/metabigor/core"
     9 + "github.com/j3ssie/metabigor/modules"
     10 + "github.com/panjf2000/ants"
     11 + 
     12 + "github.com/spf13/cobra"
    12 13  )
    13 14   
    14 15  func init() {
    15  - var certCmd = &cobra.Command{
    16  - Use: "cert",
    17  - Short: "Certificates search",
    18  - Long: fmt.Sprintf(`Metabigor - Intelligence Tool but without API key - %v by %v`, core.VERSION, core.AUTHOR),
    19  - RunE: runCert,
    20  - }
     16 + var certCmd = &cobra.Command{
     17 + Use: "cert",
     18 + Aliases: []string{"crt", "ctr"},
     19 + Short: "Certificates search",
     20 + Long: core.DESC,
     21 + RunE: runCert,
     22 + }
    21 23   
    22  - certCmd.Flags().StringSliceP("query", "q", []string{}, "Query to search (Multiple -q flags are accepted)")
    23  - certCmd.Flags().BoolVarP(&options.Cert.Clean, "clean", "C", false, "Auto clean the result")
    24  - certCmd.Flags().BoolVarP(&options.Cert.OnlyWildCard, "wildcard", "W", false, "Only get wildcard domain")
    25  - RootCmd.AddCommand(certCmd)
     24 + certCmd.Flags().BoolVarP(&options.Cert.Clean, "clean", "C", false, "Auto clean the result")
     25 + certCmd.Flags().BoolVarP(&options.Cert.OnlyWildCard, "wildcard", "W", false, "Only get wildcard domain")
     26 + RootCmd.AddCommand(certCmd)
    26 27  }
    27 28   
    28  -func runCert(cmd *cobra.Command, _ []string) error {
    29  - queries, _ := cmd.Flags().GetStringSlice("query")
     29 +func runCert(_ *cobra.Command, _ []string) error {
     30 + options.Timeout = options.Timeout * 3
    30 31   
    31  - // auto increase timeout
    32  - options.Timeout = 120
    33  - var inputs []string
     32 + var wg sync.WaitGroup
     33 + p, _ := ants.NewPoolWithFunc(options.Concurrency, func(i interface{}) {
     34 + job := i.(string)
     35 + searchResult := runCertSearch(job, options)
     36 + StoreData(searchResult, options)
     37 + wg.Done()
     38 + }, ants.WithPreAlloc(true))
     39 + defer p.Release()
    34 40   
    35  - if options.Input != "-" {
    36  - if strings.Contains(options.Input, "\n") {
    37  - inputs = append(inputs, strings.Split(options.Input, "\n")...)
    38  - } else {
    39  - inputs = append(inputs, options.Input)
    40  - }
    41  - }
     41 + for _, target := range options.Inputs {
     42 + wg.Add(1)
     43 + _ = p.Invoke(strings.TrimSpace(target))
     44 + }
    42 45   
    43  - if len(queries) > 0 {
    44  - inputs = append(inputs, queries...)
    45  - }
    46  - if len(inputs) == 0 {
    47  - core.ErrorF("No input found")
    48  - os.Exit(1)
    49  - }
    50  - 
    51  - var wg sync.WaitGroup
    52  - jobs := make(chan string)
    53  - 
    54  - for i := 0; i < options.Concurrency; i++ {
    55  - wg.Add(1)
    56  - go func() {
    57  - defer wg.Done()
    58  - // do real stuff here
    59  - for job := range jobs {
    60  - searchResult := runCertSearch(job, options)
    61  - StoreData(searchResult, options)
    62  - }
    63  - }()
    64  - }
    65  - 
    66  - for _, input := range inputs {
    67  - jobs <- input
    68  - }
    69  - 
    70  - close(jobs)
    71  - wg.Wait()
    72  - 
    73  - if !core.FileExists(options.Output) {
    74  - core.ErrorF("No data found")
    75  - }
    76  - core.DebugF("Unique Output: %v", options.Output)
    77  - core.Unique(options.Output)
    78  - return nil
     46 + wg.Wait()
     47 + core.Unique(options.Output)
     48 + return nil
    79 49  }
    80 50   
    81 51  func runCertSearch(input string, options core.Options) []string {
    82  - var data []string
    83  - core.BannerF(fmt.Sprintf("Search on %v for: ", "crt.sh"), input)
    84  - result := modules.CrtSHOrg(input, options)
    85  - data = append(data, result...)
    86  - 
    87  - return data
     52 + var data []string
     53 + core.BannerF(fmt.Sprintf("Search on %v for: ", "crt.sh"), input)
     54 + result := modules.CrtSHOrg(input, options)
     55 + data = append(data, result...)
     56 + return data
    88 57  }
    89 58   
  • ■ ■ ■ ■ ■ ■
    cmd/cve.go
    1  -package cmd
    2  - 
    3  -import (
    4  - "fmt"
    5  - "os"
    6  - "strings"
    7  - "sync"
    8  - 
    9  - "github.com/j3ssie/metabigor/core"
    10  - "github.com/j3ssie/metabigor/modules"
    11  - "github.com/spf13/cobra"
    12  -)
    13  - 
    14  -func init() {
    15  - var cveCmd = &cobra.Command{
    16  - Use: "cve",
    17  - Short: "CVE or Advisory Search",
    18  - Long: fmt.Sprintf(`Metabigor - Intelligence Tool but without API key - %v by %v`, core.VERSION, core.AUTHOR),
    19  - RunE: runCVE,
    20  - }
    21  - 
    22  - cveCmd.Flags().StringP("source", "s", "all", "Search Engine Select")
    23  - cveCmd.Flags().StringSliceP("query", "q", []string{}, "Query to search (Multiple -q flags are accepted)")
    24  - RootCmd.AddCommand(cveCmd)
    25  -}
    26  - 
    27  -func runCVE(cmd *cobra.Command, _ []string) error {
    28  - options.Search.Source, _ = cmd.Flags().GetString("source")
    29  - options.Search.Source = strings.ToLower(options.Search.Source)
    30  - queries, _ := cmd.Flags().GetStringSlice("query")
    31  - 
    32  - var inputs []string
    33  - if options.Input != "-" && options.Input != "" {
    34  - if strings.Contains(options.Input, "\n") {
    35  - inputs = strings.Split(options.Input, "\n")
    36  - } else {
    37  - inputs = append(inputs, options.Input)
    38  - }
    39  - }
    40  - if len(queries) > 0 {
    41  - inputs = append(inputs, queries...)
    42  - }
    43  - if len(inputs) == 0 {
    44  - core.ErrorF("No input found")
    45  - os.Exit(1)
    46  - }
    47  - 
    48  - var wg sync.WaitGroup
    49  - jobs := make(chan string)
    50  - 
    51  - for i := 0; i < options.Concurrency; i++ {
    52  - wg.Add(1)
    53  - go func() {
    54  - defer wg.Done()
    55  - // do real stuff here
    56  - for job := range jobs {
    57  - searchResult := runCVESingle(job, options)
    58  - StoreData(searchResult, options)
    59  - }
    60  - }()
    61  - }
    62  - 
    63  - for _, input := range inputs {
    64  - jobs <- input
    65  - }
    66  - 
    67  - close(jobs)
    68  - wg.Wait()
    69  - 
    70  - if !core.FileExists(options.Output) {
    71  - core.ErrorF("No data found")
    72  - }
    73  - core.DebugF("Unique Output: %v", options.Output)
    74  - core.Unique(options.Output)
    75  - return nil
    76  -}
    77  - 
    78  -func runCVESingle(input string, options core.Options) []string {
    79  - var data []string
    80  - core.BannerF(fmt.Sprintf("Search on %v for: ", options.Search.Source), input)
    81  - if options.Search.Source == "all" {
    82  - options.Search.Source = "vulners"
    83  - }
    84  - options.Search.Query = input
    85  - 
    86  - // select source
    87  - if strings.Contains(options.Search.Source, "vulner") {
    88  - data = append(data, modules.Vulners(options)...)
    89  - }
    90  - return data
    91  -}
    92  - 
  • ■ ■ ■ ■ ■ ■
    cmd/ip.go
    1 1  package cmd
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "os"
    6  - "strings"
    7  - "sync"
     4 + "fmt"
     5 + "github.com/j3ssie/metabigor/core"
     6 + "github.com/j3ssie/metabigor/modules"
     7 + jsoniter "github.com/json-iterator/go"
     8 + "github.com/panjf2000/ants"
     9 + "github.com/projectdiscovery/mapcidr"
     10 + "github.com/spf13/cobra"
     11 + "strings"
     12 + "sync"
    8 13   
    9  - "github.com/j3ssie/metabigor/core"
    10  - "github.com/j3ssie/metabigor/modules"
    11  - "github.com/spf13/cobra"
     14 + "net"
    12 15  )
    13 16   
     17 +var csvOutput = false
     18 +var onlyHost = false
     19 + 
    14 20  func init() {
    15  - var ipCmd = &cobra.Command{
    16  - Use: "ip",
    17  - Short: "IP OSINT Search",
    18  - Long: fmt.Sprintf(`Metabigor - Intelligence Tool but without API key - %v by %v`, core.VERSION, core.AUTHOR),
    19  - RunE: runIP,
    20  - }
    21  - 
    22  - ipCmd.Flags().StringP("source", "s", "all", "Search Engine Select")
    23  - ipCmd.Flags().StringSliceP("query", "q", []string{}, "Query to search (Multiple -q flags are accepted)")
    24  - RootCmd.AddCommand(ipCmd)
     21 + var ipCmd = &cobra.Command{
     22 + Use: "ip",
     23 + Short: "Extract Shodan IPInfo from internetdb.shodan.io",
     24 + Long: core.DESC,
     25 + RunE: runIP,
     26 + }
     27 + ipCmd.PersistentFlags().Bool("csv", true, "Show Output as CSV format")
     28 + ipCmd.PersistentFlags().Bool("open", false, "Show Output as format 'IP:Port' only")
     29 + RootCmd.AddCommand(ipCmd)
    25 30  }
    26 31   
    27 32  func runIP(cmd *cobra.Command, _ []string) error {
    28  - options.Search.Source, _ = cmd.Flags().GetString("source")
    29  - options.Search.Source = strings.ToLower(options.Search.Source)
    30  - options.Search.More, _ = cmd.Flags().GetBool("brute")
    31  - options.Search.Optimize, _ = cmd.Flags().GetBool("optimize")
    32  - queries, _ := cmd.Flags().GetStringSlice("query")
     33 + csvOutput, _ = cmd.Flags().GetBool("csv")
     34 + onlyHost, _ = cmd.Flags().GetBool("open")
    33 35   
    34  - var inputs []string
    35  - if options.Input != "-" && options.Input != "" {
    36  - if strings.Contains(options.Input, "\n") {
    37  - inputs = strings.Split(options.Input, "\n")
    38  - } else {
    39  - inputs = append(inputs, options.Input)
    40  - }
    41  - }
    42  - if len(queries) > 0 {
    43  - inputs = append(inputs, queries...)
    44  - }
    45  - if len(inputs) == 0 {
    46  - core.ErrorF("No input found")
    47  - os.Exit(1)
    48  - }
     36 + var wg sync.WaitGroup
     37 + p, _ := ants.NewPoolWithFunc(options.Concurrency, func(i interface{}) {
     38 + job := i.(string)
     39 + StartJob(job)
     40 + wg.Done()
     41 + }, ants.WithPreAlloc(true))
     42 + defer p.Release()
    49 43   
    50  - if options.Search.More {
    51  - inputs = addMoreQuery(inputs, options)
    52  - }
     44 + for _, target := range options.Inputs {
     45 + wg.Add(1)
     46 + _ = p.Invoke(strings.TrimSpace(target))
     47 + }
    53 48   
    54  - var wg sync.WaitGroup
    55  - jobs := make(chan string)
     49 + wg.Wait()
     50 + return nil
     51 +}
    56 52   
    57  - for i := 0; i < options.Concurrency; i++ {
    58  - wg.Add(1)
    59  - go func() {
    60  - defer wg.Done()
    61  - // do real stuff here
    62  - for job := range jobs {
    63  - searchResult := runIPSingle(job, options)
    64  - StoreData(searchResult, options)
    65  - }
    66  - }()
    67  - }
     53 +func StartJob(raw string) {
     54 + _, _, err := net.ParseCIDR(raw)
     55 + if err != nil {
     56 + GetShodanIPInfo(raw)
     57 + return
     58 + }
    68 59   
    69  - for _, input := range inputs {
    70  - jobs <- input
    71  - }
     60 + if ips, err := mapcidr.IPAddresses(raw); err == nil {
     61 + for _, ip := range ips {
     62 + GetShodanIPInfo(ip)
     63 + }
     64 + }
     65 +}
    72 66   
    73  - close(jobs)
    74  - wg.Wait()
     67 +type ShodanIPInfo struct {
     68 + Cpes []string `json:"cpes"`
     69 + Hostnames []string `json:"hostnames"`
     70 + IP string `json:"ip"`
     71 + Ports []int `json:"ports"`
     72 + Tags []string `json:"tags"`
     73 + Vulns []string `json:"vulns"`
     74 +}
    75 75   
    76  - if !core.FileExists(options.Output) {
    77  - core.ErrorF("No data found")
    78  - }
    79  - core.DebugF("Unique Output: %v", options.Output)
    80  - core.Unique(options.Output)
    81  - return nil
    82  -}
     76 +func GetShodanIPInfo(IP string) {
     77 + data := modules.InternetDB(IP)
     78 + if data == "" {
     79 + core.ErrorF("No data found for: %s", IP)
     80 + return
     81 + }
    83 82   
    84  -func runIPSingle(input string, options core.Options) []string {
    85  - var data []string
    86  - core.BannerF(fmt.Sprintf("Search on %v for: ", options.Search.Source), input)
    87  - if options.Search.Source == "all" {
    88  - options.Search.Source = "ony,shodan,trails"
    89  - }
    90  - options.Search.Query = input
     83 + if options.JsonOutput {
     84 + fmt.Println(data)
     85 + return
     86 + }
    91 87   
    92  - // select source
    93  - if strings.Contains(options.Search.Source, "ony") {
    94  - data = append(data, modules.Onyphe(options.Search.Query, options)...)
    95  - }
     88 + var shodanIPInfo ShodanIPInfo
     89 + if ok := jsoniter.Unmarshal([]byte(data), &shodanIPInfo); ok != nil {
     90 + return
     91 + }
    96 92   
    97  - if strings.Contains(options.Search.Source, "sho") {
    98  - data = append(data, modules.Shodan(options.Search.Query, options)...)
    99  - }
     93 + if csvOutput {
     94 + for _, port := range shodanIPInfo.Ports {
     95 + line := fmt.Sprintf("%s:%d", IP, port)
     96 + if onlyHost {
     97 + fmt.Println(line)
     98 + continue
     99 + }
    100 100   
    101  - return data
     101 + line = fmt.Sprintf("%s,%s,%s,%s,%s", line, strings.Join(shodanIPInfo.Hostnames, ";"), strings.Join(shodanIPInfo.Tags, ";"), strings.Join(shodanIPInfo.Cpes, ";"), strings.Join(shodanIPInfo.Vulns, ";"))
     102 + fmt.Println(line)
     103 + }
     104 + }
    102 105  }
    103 106   
  • ■ ■ ■ ■ ■ ■
    cmd/ipc.go
    1 1  package cmd
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "github.com/j3ssie/metabigor/core"
    6  - "github.com/j3ssie/metabigor/modules"
    7  - jsoniter "github.com/json-iterator/go"
    8  - "github.com/spf13/cobra"
    9  - "inet.af/netaddr"
    10  - "os"
    11  - "sort"
    12  - "strings"
     4 + "fmt"
     5 + "github.com/j3ssie/metabigor/core"
     6 + "github.com/j3ssie/metabigor/modules"
     7 + jsoniter "github.com/json-iterator/go"
     8 + "github.com/spf13/cobra"
     9 + "inet.af/netaddr"
     10 + "os"
     11 + "sort"
     12 + "strings"
    13 13  )
    14 14   
    15 15  func init() {
    16  - var netCmd = &cobra.Command{
    17  - Use: "ipc",
    18  - Short: "Summary about IP list (powered by @thebl4ckturtle)",
    19  - Long: fmt.Sprintf(`Metabigor - Intelligence Framework but without API key - %v by %v`, core.VERSION, core.AUTHOR),
    20  - RunE: runIPC,
    21  - }
    22  - RootCmd.AddCommand(netCmd)
     16 + var netCmd = &cobra.Command{
     17 + Use: "ipc",
     18 + Short: "Summary about IP list (powered by @thebl4ckturtle)",
     19 + Long: core.DESC,
     20 + RunE: runIPC,
     21 + }
     22 + RootCmd.AddCommand(netCmd)
    23 23  }
    24 24   
    25 25  func runIPC(_ *cobra.Command, _ []string) error {
    26  - // prepare input
    27  - var inputs []string
    28  - if strings.Contains(options.Input, "\n") {
    29  - inputs = strings.Split(options.Input, "\n")
    30  - } else {
    31  - inputs = append(inputs, options.Input)
    32  - }
     26 + // prepare input
     27 + var inputs []string
     28 + if strings.Contains(options.Input, "\n") {
     29 + inputs = strings.Split(options.Input, "\n")
     30 + } else {
     31 + inputs = append(inputs, options.Input)
     32 + }
    33 33   
    34  - var err error
    35  - ASNMap, err = modules.GetAsnMap()
    36  - if err != nil {
    37  - fmt.Fprintf(os.Stderr, "Error to generate asn info")
    38  - os.Exit(-1)
    39  - }
     34 + var err error
     35 + ASNMap, err = modules.GetAsnMap()
     36 + if err != nil {
     37 + fmt.Fprintf(os.Stderr, "Error to generate asn info")
     38 + os.Exit(-1)
     39 + }
    40 40   
    41  - summary := map[string]*modules.ASInfo{}
    42  - groupByAsn := map[int][]*modules.ASInfo{}
     41 + summary := map[string]*modules.ASInfo{}
     42 + groupByAsn := map[int][]*modules.ASInfo{}
    43 43   
    44  - // do real stuff here
    45  - for _, job := range inputs {
    46  - ip, err := netaddr.ParseIP(strings.TrimSpace(job))
    47  - if err != nil {
    48  - continue
    49  - }
    50  - if asn := ASNMap.ASofIP(ip); asn.AS != 0 {
    51  - if result, ok := summary[asn.CIDR]; ok {
    52  - result.Amount++
    53  - continue
    54  - } else {
    55  - summary[asn.CIDR] = &modules.ASInfo{
    56  - Amount: 1,
    57  - Number: asn.AS,
    58  - CountryCode: ASNMap.ASCountry(asn.AS),
    59  - Description: ASNMap.ASName(asn.AS),
    60  - CIDR: asn.CIDR,
    61  - }
    62  - }
    63  - }
    64  - }
     44 + // do real stuff here
     45 + for _, job := range inputs {
     46 + ip, err := netaddr.ParseIP(strings.TrimSpace(job))
     47 + if err != nil {
     48 + continue
     49 + }
     50 + if asn := ASNMap.ASofIP(ip); asn.AS != 0 {
     51 + if result, ok := summary[asn.CIDR]; ok {
     52 + result.Amount++
     53 + continue
     54 + } else {
     55 + summary[asn.CIDR] = &modules.ASInfo{
     56 + Amount: 1,
     57 + Number: asn.AS,
     58 + CountryCode: ASNMap.ASCountry(asn.AS),
     59 + Description: ASNMap.ASName(asn.AS),
     60 + CIDR: asn.CIDR,
     61 + }
     62 + }
     63 + }
     64 + }
    65 65   
    66  - for _, result := range summary {
    67  - if _, ok := groupByAsn[result.Number]; ok {
    68  - groupByAsn[result.Number] = append(groupByAsn[result.Number], result)
    69  - } else {
    70  - groupByAsn[result.Number] = []*modules.ASInfo{}
    71  - groupByAsn[result.Number] = append(groupByAsn[result.Number], result)
    72  - }
    73  - }
     66 + for _, result := range summary {
     67 + if _, ok := groupByAsn[result.Number]; ok {
     68 + groupByAsn[result.Number] = append(groupByAsn[result.Number], result)
     69 + } else {
     70 + groupByAsn[result.Number] = []*modules.ASInfo{}
     71 + groupByAsn[result.Number] = append(groupByAsn[result.Number], result)
     72 + }
     73 + }
    74 74   
    75  - // do summary here
    76  - var groupbyCIDR []AsnSummaryByCIDR
    77  - for asnNumber, asnInfos := range groupByAsn {
    78  - //fmt.Printf("AS: %d - %s\n", asnNumber, asnInfos[0].Description)
     75 + // do summary here
     76 + var groupbyCIDR []AsnSummaryByCIDR
     77 + for asnNumber, asnInfos := range groupByAsn {
     78 + //fmt.Printf("AS: %d - %s\n", asnNumber, asnInfos[0].Description)
    79 79   
    80  - sort.Slice(asnInfos, func(i, j int) bool {
    81  - return asnInfos[i].Amount > asnInfos[j].Amount
    82  - })
     80 + sort.Slice(asnInfos, func(i, j int) bool {
     81 + return asnInfos[i].Amount > asnInfos[j].Amount
     82 + })
    83 83   
    84  - //asnSum.Count +=
    85  - for _, as := range asnInfos {
    86  - //fmt.Printf("\t%-16s\t%-4d IPs\n", as.CIDR, as.Amount)
     84 + //asnSum.Count +=
     85 + for _, as := range asnInfos {
     86 + //fmt.Printf("\t%-16s\t%-4d IPs\n", as.CIDR, as.Amount)
    87 87   
    88  - var asnSum AsnSummaryByCIDR
    89  - asnSum.CIDR = as.CIDR
    90  - asnSum.Count = as.Amount
    91  - asnSum.Number = asnNumber
    92  - asnSum.CountryCode = as.CountryCode
    93  - asnSum.Description = asnInfos[0].Description
    94  - groupbyCIDR = append(groupbyCIDR, asnSum)
    95  - }
    96  - }
     88 + var asnSum AsnSummaryByCIDR
     89 + asnSum.CIDR = as.CIDR
     90 + asnSum.Count = as.Amount
     91 + asnSum.Number = asnNumber
     92 + asnSum.CountryCode = as.CountryCode
     93 + asnSum.Description = asnInfos[0].Description
     94 + groupbyCIDR = append(groupbyCIDR, asnSum)
     95 + }
     96 + }
    97 97   
    98  - // print the output here
    99  - var contents []string
    100  - for _, asnSum := range groupbyCIDR {
    101  - if options.JsonOutput {
    102  - if data, err := jsoniter.MarshalToString(asnSum); err == nil {
    103  - contents = append(contents, data)
    104  - }
    105  - continue
    106  - }
     98 + // print the output here
     99 + var contents []string
     100 + for _, asnSum := range groupbyCIDR {
     101 + if options.JsonOutput {
     102 + if data, err := jsoniter.MarshalToString(asnSum); err == nil {
     103 + contents = append(contents, data)
     104 + }
     105 + continue
     106 + }
    107 107   
    108  - data := fmt.Sprintf("%d - %s - %d", asnSum.Number, asnSum.CIDR, asnSum.Count)
    109  - contents = append(contents, data)
    110  - }
    111  - StoreData(contents, options)
     108 + data := fmt.Sprintf("%d - %s - %d", asnSum.Number, asnSum.CIDR, asnSum.Count)
     109 + contents = append(contents, data)
     110 + }
     111 + StoreData(contents, options)
    112 112   
    113  - if !core.FileExists(options.Output) {
    114  - core.ErrorF("No data found")
    115  - }
    116  - return nil
     113 + if !core.FileExists(options.Output) {
     114 + core.ErrorF("No data found")
     115 + }
     116 + return nil
    117 117  }
    118 118   
    119 119  type AsnSummaryByCIDR struct {
    120  - Number int
    121  - Description string
    122  - CountryCode string
    123  - CIDR string
    124  - Count int
     120 + Number int
     121 + Description string
     122 + CountryCode string
     123 + CIDR string
     124 + Count int
    125 125  }
    126 126   
  • ■ ■ ■ ■ ■ ■
    cmd/net.go
    1 1  package cmd
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "github.com/j3ssie/metabigor/core"
    6  - "github.com/j3ssie/metabigor/modules"
    7  - jsoniter "github.com/json-iterator/go"
    8  - "github.com/spf13/cast"
    9  - "github.com/spf13/cobra"
    10  - "inet.af/netaddr"
    11  - "net"
    12  - "os"
    13  - "strings"
    14  - "sync"
     4 + "fmt"
     5 + "github.com/j3ssie/metabigor/core"
     6 + "github.com/j3ssie/metabigor/modules"
     7 + jsoniter "github.com/json-iterator/go"
     8 + "github.com/panjf2000/ants"
     9 + "github.com/spf13/cast"
     10 + "github.com/spf13/cobra"
     11 + "github.com/thoas/go-funk"
     12 + "inet.af/netaddr"
     13 + "net"
     14 + "os"
     15 + "strings"
     16 + "sync"
    15 17  )
    16 18   
    17 19  func init() {
    18  - var netCmd = &cobra.Command{
    19  - Use: "net",
    20  - Short: "Discover Network Information about targets (same with net command but use static data)",
    21  - Long: fmt.Sprintf(`Metabigor - Intelligence Framework but without API key - %v by %v`, core.VERSION, core.AUTHOR),
    22  - RunE: runNet,
    23  - }
     20 + var netCmd = &cobra.Command{
     21 + Use: "net",
     22 + Short: "Discover Network Information about targets (same with net command but use static data)",
     23 + Long: fmt.Sprintf(`Metabigor - Intelligence Framework but without API key - %v by %v`, core.VERSION, core.AUTHOR),
     24 + RunE: runNet,
     25 + }
    24 26   
    25  - netCmd.Flags().Bool("asn", false, "Take input as ASN")
    26  - netCmd.Flags().Bool("org", false, "Take input as Organization")
    27  - netCmd.Flags().Bool("ip", false, "Take input as a single IP address")
    28  - netCmd.Flags().Bool("domain", false, "Take input as a domain")
    29  - netCmd.Flags().BoolVarP(&options.Net.ExactMatch, "exact", "x", false, "Only get from highly trusted source")
    30  - RootCmd.AddCommand(netCmd)
     27 + netCmd.Flags().Bool("asn", false, "Take input as ASN")
     28 + netCmd.Flags().Bool("org", false, "Take input as Organization")
     29 + netCmd.Flags().Bool("ip", false, "Take input as a single IP address")
     30 + netCmd.Flags().Bool("domain", false, "Take input as a domain")
     31 + netCmd.Flags().BoolVarP(&options.Net.ExactMatch, "exact", "x", false, "Only get from highly trusted source")
     32 + RootCmd.AddCommand(netCmd)
     33 + 
     34 + var netdCmd = &cobra.Command{
     35 + Use: "netd",
     36 + Short: "Discover Network Information about targets (similar with 'net' command but use 3rd data)",
     37 + Long: fmt.Sprintf(`Metabigor - Intelligence Framework but without API key - %v by %v`, core.VERSION, core.AUTHOR),
     38 + RunE: runNetD,
     39 + }
     40 + 
     41 + netdCmd.Flags().Bool("asn", false, "Take input as ASN")
     42 + netdCmd.Flags().Bool("org", false, "Take input as Organization")
     43 + netdCmd.Flags().Bool("ip", false, "Take input as a single IP address")
     44 + netdCmd.Flags().Bool("domain", false, "Take input as a domain")
     45 + netdCmd.Flags().BoolP("accurate", "x", false, "Only get from highly trusted source")
     46 + RootCmd.AddCommand(netdCmd)
    31 47  }
    32 48   
    33 49  var ASNMap modules.AsnMap
    34 50   
    35 51  func runNet(cmd *cobra.Command, _ []string) error {
    36  - asn, _ := cmd.Flags().GetBool("asn")
    37  - org, _ := cmd.Flags().GetBool("org")
    38  - ip, _ := cmd.Flags().GetBool("ip")
    39  - domain, _ := cmd.Flags().GetBool("domain")
     52 + asn, _ := cmd.Flags().GetBool("asn")
     53 + org, _ := cmd.Flags().GetBool("org")
     54 + ip, _ := cmd.Flags().GetBool("ip")
     55 + domain, _ := cmd.Flags().GetBool("domain")
    40 56   
    41  - // prepare input
    42  - var inputs []string
    43  - if strings.Contains(options.Input, "\n") {
    44  - inputs = strings.Split(options.Input, "\n")
    45  - } else {
    46  - inputs = append(inputs, options.Input)
    47  - }
     57 + if asn {
     58 + options.Net.SearchType = "asn"
     59 + } else if org {
     60 + options.Net.SearchType = "org"
     61 + } else if ip {
     62 + options.Net.SearchType = "ip"
     63 + } else if domain {
     64 + options.Net.SearchType = "domain"
     65 + }
     66 + if options.Net.SearchType == "" {
     67 + fmt.Fprintf(os.Stderr, "You need to specify search type with one of these flag: --asn, --org or --ip")
     68 + os.Exit(-1)
     69 + }
    48 70   
    49  - if asn {
    50  - options.Net.SearchType = "asn"
    51  - } else if org {
    52  - options.Net.SearchType = "org"
    53  - } else if ip {
    54  - options.Net.SearchType = "ip"
    55  - } else if domain {
    56  - options.Net.SearchType = "domain"
    57  - }
    58  - if options.Net.SearchType == "" {
    59  - fmt.Fprintf(os.Stderr, "You need to specify search type with one of these flag: --asn, --org or --ip")
    60  - os.Exit(-1)
    61  - }
     71 + var err error
     72 + ASNMap, err = modules.GetAsnMap()
     73 + if err != nil {
     74 + fmt.Fprintf(os.Stderr, "Error to generate asn info")
     75 + os.Exit(-1)
     76 + }
    62 77   
    63  - var err error
    64  - ASNMap, err = modules.GetAsnMap()
    65  - if err != nil {
    66  - fmt.Fprintf(os.Stderr, "Error to generate asn info")
    67  - os.Exit(-1)
    68  - }
    69  - 
    70  - var wg sync.WaitGroup
    71  - jobs := make(chan string)
    72  - 
    73  - for i := 0; i < options.Concurrency; i++ {
    74  - wg.Add(1)
    75  - go func() {
    76  - defer wg.Done()
    77  - // do real stuff here
    78  - for job := range jobs {
    79  - var osintResult []string
    80  - osintResult = runNetJob(job, options)
    81  - StoreData(osintResult, options)
    82  - }
    83  - }()
    84  - }
    85  - 
    86  - for _, input := range inputs {
    87  - jobs <- input
    88  - }
     78 + var wg sync.WaitGroup
     79 + p, _ := ants.NewPoolWithFunc(options.Concurrency, func(i interface{}) {
     80 + job := i.(string)
     81 + var osintResult []string
     82 + osintResult = runNetJob(job, options)
     83 + StoreData(osintResult, options)
     84 + wg.Done()
     85 + }, ants.WithPreAlloc(true))
     86 + defer p.Release()
    89 87   
    90  - close(jobs)
    91  - wg.Wait()
     88 + for _, target := range options.Inputs {
     89 + wg.Add(1)
     90 + _ = p.Invoke(strings.TrimSpace(target))
     91 + }
     92 + wg.Wait()
    92 93   
    93  - if !core.FileExists(options.Output) {
    94  - core.ErrorF("No data found")
    95  - }
    96  - return nil
     94 + if options.Output != "" && !core.FileExists(options.Output) {
     95 + core.ErrorF("No data found")
     96 + }
     97 + return nil
    97 98  }
    98 99   
    99 100  func runNetJob(input string, options core.Options) []string {
    100  - var data []string
    101  - var asnInfos []modules.ASInfo
     101 + var data []string
     102 + var asnInfos []modules.ASInfo
    102 103   
    103  - if !options.Net.ExactMatch {
    104  - input = strings.ToLower(input)
     104 + if !options.Net.ExactMatch {
     105 + input = strings.ToLower(input)
    105 106   
    106  - }
     107 + }
    107 108   
    108  - switch options.Net.SearchType {
    109  - case "asn":
    110  - input = strings.ToLower(input)
    111  - if strings.Contains(input, "as") {
    112  - input = strings.ReplaceAll(input, "as", "")
    113  - }
    114  - asInfos := ASNMap.ASInfo(cast.ToInt(input))
    115  - if len(asInfos) > 0 {
    116  - asnInfos = append(asnInfos, asInfos...)
    117  - }
     109 + switch options.Net.SearchType {
     110 + case "asn":
     111 + input = strings.ToLower(input)
     112 + if strings.Contains(input, "as") {
     113 + input = strings.ReplaceAll(input, "as", "")
     114 + }
     115 + asInfos := ASNMap.ASInfo(cast.ToInt(input))
     116 + if len(asInfos) > 0 {
     117 + asnInfos = append(asnInfos, asInfos...)
     118 + }
    118 119   
    119  - case "org":
    120  - asnNums := ASNMap.ASDesc(input)
    121  - if len(asnNums) > 0 {
    122  - for _, asnNum := range asnNums {
    123  - asnInfos = append(asnInfos, ASNMap.ASInfo(asnNum)...)
    124  - }
    125  - }
     120 + case "org":
     121 + asnNums := ASNMap.ASDesc(input)
     122 + if len(asnNums) > 0 {
     123 + for _, asnNum := range asnNums {
     124 + asnInfos = append(asnInfos, ASNMap.ASInfo(asnNum)...)
     125 + }
     126 + }
    126 127   
    127  - case "ip":
    128  - asnInfos = append(asnInfos, searchByIP(input)...)
     128 + case "ip":
     129 + asnInfos = append(asnInfos, searchByIP(input)...)
    129 130   
    130  - case "domain":
    131  - ips, err := net.LookupHost(input)
    132  - if err == nil {
    133  - for _, ip := range ips {
    134  - asnInfos = append(asnInfos, searchByIP(ip)...)
    135  - }
    136  - }
    137  - }
     131 + case "domain":
     132 + ips, err := net.LookupHost(input)
     133 + if err == nil {
     134 + for _, ip := range ips {
     135 + asnInfos = append(asnInfos, searchByIP(ip)...)
     136 + }
     137 + }
     138 + }
    138 139   
    139  - if len(asnInfos) == 0 {
    140  - core.ErrorF("No result found for: %s", input)
    141  - return data
    142  - }
     140 + if len(asnInfos) == 0 {
     141 + core.ErrorF("No result found for: %s", input)
     142 + return data
     143 + }
    143 144   
    144  - for _, asnInfo := range asnInfos {
    145  - line := genOutput(asnInfo)
    146  - data = append(data, line)
    147  - }
     145 + for _, asnInfo := range asnInfos {
     146 + line := genOutput(asnInfo)
     147 + data = append(data, line)
     148 + }
    148 149   
    149  - return data
     150 + return data
    150 151  }
    151 152   
    152 153  func genOutput(asnInfo modules.ASInfo) string {
    153  - var line string
    154  - if options.JsonOutput {
    155  - if content, err := jsoniter.MarshalToString(asnInfo); err == nil {
    156  - return content
    157  - }
    158  - return line
    159  - }
    160  - if options.Verbose {
    161  - line = fmt.Sprintf("%d - %s - %s - %s", asnInfo.Number, asnInfo.CIDR, asnInfo.Description, asnInfo.CountryCode)
    162  - } else {
    163  - line = asnInfo.CIDR
    164  - }
    165  - return line
     154 + var line string
     155 + if options.JsonOutput {
     156 + if content, err := jsoniter.MarshalToString(asnInfo); err == nil {
     157 + return content
     158 + }
     159 + return line
     160 + }
     161 + if options.Verbose {
     162 + line = fmt.Sprintf("%d - %s - %s - %s", asnInfo.Number, asnInfo.CIDR, asnInfo.Description, asnInfo.CountryCode)
     163 + } else {
     164 + line = asnInfo.CIDR
     165 + }
     166 + return line
    166 167  }
    167 168   
    168 169  func searchByIP(input string) []modules.ASInfo {
    169  - var asnInfo []modules.ASInfo
     170 + var asnInfo []modules.ASInfo
     171 + 
     172 + ip, err := netaddr.ParseIP(input)
     173 + if err != nil {
     174 + return asnInfo
     175 + }
     176 + 
     177 + if asn := ASNMap.ASofIP(ip); asn.AS != 0 {
     178 + return ASNMap.ASInfo(asn.AS)
     179 + }
     180 + return asnInfo
     181 +}
     182 + 
     183 +/////////// netd command
     184 + 
     185 +func runNetD(cmd *cobra.Command, _ []string) error {
     186 + asn, _ := cmd.Flags().GetBool("asn")
     187 + org, _ := cmd.Flags().GetBool("org")
     188 + ip, _ := cmd.Flags().GetBool("ip")
     189 + domain, _ := cmd.Flags().GetBool("domain")
     190 + options.Net.Optimize, _ = cmd.Flags().GetBool("accurate")
     191 + 
     192 + var wg sync.WaitGroup
     193 + p, _ := ants.NewPoolWithFunc(options.Concurrency, func(i interface{}) {
     194 + job := i.(string)
     195 + var osintResult []string
     196 + if asn {
     197 + osintResult = runASN(job, options)
     198 + } else if org {
     199 + osintResult = runOrg(job, options)
     200 + } else if ip {
     201 + options.Net.IP = job
     202 + osintResult = runSingle(job, options)
     203 + } else if domain {
     204 + options.Net.Domain = job
     205 + osintResult = runSingle(job, options)
     206 + }
     207 + StoreData(osintResult, options)
     208 + 
     209 + wg.Done()
     210 + }, ants.WithPreAlloc(true))
     211 + defer p.Release()
     212 + 
     213 + for _, target := range options.Inputs {
     214 + wg.Add(1)
     215 + _ = p.Invoke(strings.TrimSpace(target))
     216 + }
    170 217   
    171  - ip, err := netaddr.ParseIP(input)
    172  - if err != nil {
    173  - return asnInfo
    174  - }
     218 + wg.Wait()
    175 219   
    176  - if asn := ASNMap.ASofIP(ip); asn.AS != 0 {
    177  - return ASNMap.ASInfo(asn.AS)
    178  - }
    179  - return asnInfo
     220 + if options.Output != "" && !core.FileExists(options.Output) {
     221 + core.ErrorF("No data found")
     222 + }
     223 + return nil
     224 +}
     225 + 
     226 +func runSingle(input string, options core.Options) []string {
     227 + core.BannerF("Starting get ASN from: ", input)
     228 + var data []string
     229 + ans := modules.ASNFromIP(options)
     230 + 
     231 + // get more IP by result ASN
     232 + for _, item := range ans {
     233 + if strings.HasPrefix(strings.ToLower(item), "as") {
     234 + data = append(data, runASN(item, options)...)
     235 + }
     236 + }
     237 + return data
     238 +}
     239 + 
     240 +func runASN(input string, options core.Options) []string {
     241 + core.BannerF("Starting get IP Info from ASN: ", input)
     242 + options.Net.Asn = input
     243 + var data []string
     244 + var wg sync.WaitGroup
     245 + 
     246 + wg.Add(1)
     247 + go func() {
     248 + data = append(data, modules.GetIPInfo(options)...)
     249 + wg.Done()
     250 + }()
     251 + 
     252 + wg.Wait()
     253 + return data
     254 +}
     255 + 
     256 +func runOrg(input string, options core.Options) []string {
     257 + core.BannerF("Starting get IP Info for Organization: ", input)
     258 + options.Net.Org = input
     259 + var data []string
     260 + var wg sync.WaitGroup
     261 + wg.Add(1)
     262 + go func() {
     263 + data = append(data, modules.OrgBgpDotNet(options)...)
     264 + wg.Done()
     265 + }()
     266 + 
     267 + wg.Add(1)
     268 + go func() {
     269 + data = append(data, modules.OrgBgbView(options)...)
     270 + wg.Done()
     271 + }()
     272 + 
     273 + // disable when enable trusted source
     274 + if !options.Net.Optimize {
     275 + wg.Add(1)
     276 + go func() {
     277 + data = append(data, modules.ASNLookup(options)...)
     278 + wg.Done()
     279 + }()
     280 + }
     281 + wg.Wait()
     282 + 
     283 + var cidrs []string
     284 + // get more IP by result ASN
     285 + for _, item := range data {
     286 + // get more range from ASN
     287 + if strings.HasPrefix(strings.ToLower(item), "as") {
     288 + wg.Add(1)
     289 + go func(item string) {
     290 + cidrs = append(cidrs, runASN(item, options)...)
     291 + wg.Done()
     292 + }(item)
     293 + continue
     294 + } else if core.StartWithNum(item) {
     295 + cidrs = append(cidrs, item)
     296 + }
     297 + }
     298 + wg.Wait()
     299 + return funk.Uniq(cidrs).([]string)
     300 +}
     301 + 
     302 +// StoreData store data to output
     303 +func StoreData(data []string, options core.Options) {
     304 + if len(data) == 0 {
     305 + core.ErrorF("Empty data to write")
     306 + return
     307 + }
     308 + 
     309 + fmt.Println(strings.Join(data, "\n"))
     310 + _, err := core.AppendToContent(options.Output, strings.Join(data, "\n"))
     311 + if err == nil {
     312 + core.InforF("Write output to: %v", options.Output)
     313 + }
    180 314  }
    181 315   
  • ■ ■ ■ ■ ■ ■
    cmd/netd.go
    1  -package cmd
    2  - 
    3  -import (
    4  - "fmt"
    5  - "os"
    6  - "strings"
    7  - "sync"
    8  - 
    9  - "github.com/j3ssie/metabigor/core"
    10  - "github.com/j3ssie/metabigor/modules"
    11  - "github.com/spf13/cobra"
    12  - "github.com/thoas/go-funk"
    13  -)
    14  - 
    15  -func init() {
    16  - var netCmd = &cobra.Command{
    17  - Use: "netd",
    18  - Short: "Discover Network Information about targets (similar with 'net' command but use 3rd data)",
    19  - Long: fmt.Sprintf(`Metabigor - Intelligence Framework but without API key - %v by %v`, core.VERSION, core.AUTHOR),
    20  - RunE: runNetD,
    21  - }
    22  - 
    23  - netCmd.Flags().Bool("asn", false, "Take input as ASN")
    24  - netCmd.Flags().Bool("org", false, "Take input as Organization")
    25  - netCmd.Flags().Bool("ip", false, "Take input as a single IP address")
    26  - netCmd.Flags().Bool("domain", false, "Take input as a domain")
    27  - netCmd.Flags().BoolP("accurate", "x", false, "Only get from highly trusted source")
    28  - 
    29  - RootCmd.AddCommand(netCmd)
    30  -}
    31  - 
    32  -func runNetD(cmd *cobra.Command, _ []string) error {
    33  - asn, _ := cmd.Flags().GetBool("asn")
    34  - org, _ := cmd.Flags().GetBool("org")
    35  - ip, _ := cmd.Flags().GetBool("ip")
    36  - domain, _ := cmd.Flags().GetBool("domain")
    37  - options.Net.Optimize, _ = cmd.Flags().GetBool("accurate")
    38  - 
    39  - var inputs []string
    40  - 
    41  - if options.Input == "-" || options.Input == "" {
    42  - core.ErrorF("No input found")
    43  - os.Exit(1)
    44  - }
    45  - 
    46  - if strings.Contains(options.Input, "\n") {
    47  - inputs = strings.Split(options.Input, "\n")
    48  - } else {
    49  - inputs = append(inputs, options.Input)
    50  - }
    51  - 
    52  - var wg sync.WaitGroup
    53  - jobs := make(chan string)
    54  - 
    55  - for i := 0; i < options.Concurrency; i++ {
    56  - wg.Add(1)
    57  - go func() {
    58  - defer wg.Done()
    59  - // do real stuff here
    60  - for job := range jobs {
    61  - var osintResult []string
    62  - if asn {
    63  - osintResult = runASN(job, options)
    64  - } else if org {
    65  - osintResult = runOrg(job, options)
    66  - } else if ip {
    67  - options.Net.IP = job
    68  - osintResult = runSingle(job, options)
    69  - } else if domain {
    70  - options.Net.Domain = job
    71  - osintResult = runSingle(job, options)
    72  - }
    73  - StoreData(osintResult, options)
    74  - }
    75  - }()
    76  - }
    77  - 
    78  - for _, input := range inputs {
    79  - jobs <- input
    80  - }
    81  - 
    82  - close(jobs)
    83  - wg.Wait()
    84  - 
    85  - if !core.FileExists(options.Output) {
    86  - core.ErrorF("No data found")
    87  - }
    88  - return nil
    89  -}
    90  - 
    91  -func runSingle(input string, options core.Options) []string {
    92  - core.BannerF("Starting get ASN from: ", input)
    93  - var data []string
    94  - ans := modules.ASNFromIP(options)
    95  - 
    96  - // get more IP by result ASN
    97  - for _, item := range ans {
    98  - if strings.HasPrefix(strings.ToLower(item), "as") {
    99  - data = append(data, runASN(item, options)...)
    100  - }
    101  - }
    102  - return data
    103  -}
    104  - 
    105  -func runASN(input string, options core.Options) []string {
    106  - core.BannerF("Starting get IP Info from ASN: ", input)
    107  - options.Net.Asn = input
    108  - var data []string
    109  - var wg sync.WaitGroup
    110  - 
    111  - //wg.Add(1)
    112  - //go func() {
    113  - // data = append(data, modules.ASNBgpDotNet(options)...)
    114  - // wg.Done()
    115  - //}()
    116  - 
    117  - wg.Add(1)
    118  - go func() {
    119  - data = append(data, modules.GetIPInfo(options)...)
    120  - wg.Done()
    121  - }()
    122  - 
    123  - wg.Wait()
    124  - return data
    125  -}
    126  - 
    127  -func runOrg(input string, options core.Options) []string {
    128  - core.BannerF("Starting get IP Info for Organization: ", input)
    129  - options.Net.Org = input
    130  - var data []string
    131  - var wg sync.WaitGroup
    132  - wg.Add(1)
    133  - go func() {
    134  - data = append(data, modules.OrgBgpDotNet(options)...)
    135  - wg.Done()
    136  - }()
    137  - 
    138  - wg.Add(1)
    139  - go func() {
    140  - data = append(data, modules.OrgBgbView(options)...)
    141  - wg.Done()
    142  - }()
    143  - 
    144  - // disable when enable trusted source
    145  - if !options.Net.Optimize {
    146  - wg.Add(1)
    147  - go func() {
    148  - data = append(data, modules.ASNLookup(options)...)
    149  - wg.Done()
    150  - }()
    151  - }
    152  - wg.Wait()
    153  - 
    154  - var cidrs []string
    155  - // get more IP by result ASN
    156  - for _, item := range data {
    157  - // get more range from ASN
    158  - if strings.HasPrefix(strings.ToLower(item), "as") {
    159  - wg.Add(1)
    160  - go func(item string) {
    161  - cidrs = append(cidrs, runASN(item, options)...)
    162  - wg.Done()
    163  - }(item)
    164  - continue
    165  - } else if core.StartWithNum(item) {
    166  - cidrs = append(cidrs, item)
    167  - }
    168  - }
    169  - wg.Wait()
    170  - return funk.Uniq(cidrs).([]string)
    171  -}
    172  - 
    173  -// StoreData store data to output
    174  -func StoreData(data []string, options core.Options) {
    175  - if len(data) == 0 {
    176  - core.ErrorF("Empty data to write")
    177  - return
    178  - }
    179  - 
    180  - fmt.Println(strings.Join(data, "\n"))
    181  - _, err := core.AppendToContent(options.Output, strings.Join(data, "\n"))
    182  - if err == nil {
    183  - core.InforF("Write output to: %v", options.Output)
    184  - }
    185  -}
    186  - 
  • ■ ■ ■ ■ ■ ■
    cmd/related.go
     1 +package cmd
     2 + 
     3 +import (
     4 + "fmt"
     5 + "github.com/j3ssie/metabigor/core"
     6 + "github.com/j3ssie/metabigor/modules"
     7 + jsoniter "github.com/json-iterator/go"
     8 + "github.com/panjf2000/ants"
     9 + "github.com/spf13/cobra"
     10 + "strings"
     11 + "sync"
     12 +)
     13 + 
     14 +func init() {
     15 + var tldCmd = &cobra.Command{
     16 + Use: "related",
     17 + Short: "Finding more related domains of the target by applying various techniques",
     18 + Long: fmt.Sprintf(`Metabigor - Intelligence Tool but without API key - %v by %v`, core.VERSION, core.AUTHOR),
     19 + RunE: runTLD,
     20 + }
     21 + tldCmd.Flags().StringVarP(&options.Tld.Source, "src", "s", "all", "Source for gathering TLD")
     22 + RootCmd.AddCommand(tldCmd)
     23 +}
     24 + 
     25 +func runTLD(_ *cobra.Command, _ []string) error {
     26 + var wg sync.WaitGroup
     27 + p, _ := ants.NewPoolWithFunc(options.Concurrency, func(i interface{}) {
     28 + job := i.(string)
     29 + TLDJob(job)
     30 + wg.Done()
     31 + }, ants.WithPreAlloc(true))
     32 + defer p.Release()
     33 + 
     34 + for _, target := range options.Inputs {
     35 + wg.Add(1)
     36 + _ = p.Invoke(strings.TrimSpace(target))
     37 + }
     38 + 
     39 + wg.Wait()
     40 + return nil
     41 +}
     42 + 
     43 +func TLDJob(raw string) {
     44 + var results []core.RelatedDomain
     45 + switch options.Tld.Source {
     46 + case "all":
     47 + results = append(results, modules.CrtSH(raw, options)...)
     48 + results = append(results, modules.ReverseWhois(raw, options)...)
     49 + results = append(results, modules.GoogleAnalytic(raw, options)...)
     50 + case "crt", "cert":
     51 + results = append(results, modules.CrtSH(raw, options)...)
     52 + case "whois", "who":
     53 + results = append(results, modules.ReverseWhois(raw, options)...)
     54 + case "ua", "gtm", "google-analytic":
     55 + results = append(results, modules.GoogleAnalytic(raw, options)...)
     56 + }
     57 + 
     58 + for _, item := range results {
     59 + if options.JsonOutput {
     60 + if data, err := jsoniter.MarshalToString(item); err == nil {
     61 + fmt.Println(data)
     62 + }
     63 + continue
     64 + }
     65 + 
     66 + if options.Verbose {
     67 + fmt.Println(item.Output)
     68 + } else {
     69 + fmt.Println(item.Domain)
     70 + }
     71 + }
     72 +}
     73 + 
  • ■ ■ ■ ■ ■ ■
    cmd/root.go
    1 1  package cmd
    2 2   
    3 3  import (
    4  - "bufio"
    5  - "fmt"
    6  - "os"
    7  - "strings"
     4 + "bufio"
     5 + "fmt"
     6 + "os"
     7 + "strings"
    8 8   
    9  - "github.com/j3ssie/metabigor/core"
    10  - "github.com/spf13/cobra"
     9 + "github.com/j3ssie/metabigor/core"
     10 + "github.com/spf13/cobra"
    11 11  )
    12 12   
    13 13  var options = core.Options{}
    14 14   
    15 15  var RootCmd = &cobra.Command{
    16  - Use: "metabigor",
    17  - Short: fmt.Sprintf(`Metabigor - Intelligence Tool but without API key - %v by %v`, core.VERSION, core.AUTHOR),
    18  - Long: fmt.Sprintf(`Metabigor - Intelligence Tool but without API key - %v by %v`, core.VERSION, core.AUTHOR),
     16 + Use: "metabigor",
     17 + Long: core.DESC,
    19 18  }
    20 19   
    21 20  // Execute main function
    22 21  func Execute() {
    23  - if err := RootCmd.Execute(); err != nil {
    24  - fmt.Println(err)
    25  - os.Exit(1)
    26  - }
     22 + if err := RootCmd.Execute(); err != nil {
     23 + fmt.Println(err)
     24 + os.Exit(1)
     25 + }
    27 26  }
    28 27   
    29 28  func init() {
    30  - cobra.OnInitialize(initConfig)
    31  - RootCmd.PersistentFlags().StringVarP(&options.Scan.TmpOutput, "tmp", "T", "", "Temp Output folder")
    32  - RootCmd.PersistentFlags().StringVar(&options.Proxy, "proxy", "", "Proxy for doing request")
    33  - RootCmd.PersistentFlags().IntVarP(&options.Concurrency, "concurrency", "c", 5, "concurrency")
    34  - RootCmd.PersistentFlags().IntVar(&options.Timeout, "timeout", 40, "timeout")
    35  - RootCmd.PersistentFlags().StringVarP(&options.Input, "input", "i", "-", "input as a string, file or from stdin")
    36  - RootCmd.PersistentFlags().StringVarP(&options.InputFile, "inputFile", "I", "-", "Input file")
     29 + cobra.OnInitialize(initConfig)
     30 + RootCmd.PersistentFlags().StringVar(&options.Proxy, "proxy", "", "Proxy for doing request")
     31 + RootCmd.PersistentFlags().IntVarP(&options.Concurrency, "concurrency", "c", 5, "concurrency")
     32 + RootCmd.PersistentFlags().IntVar(&options.Timeout, "timeout", 40, "timeout")
     33 + RootCmd.PersistentFlags().IntVar(&options.Retry, "retry", 3, "Retry")
     34 + 
     35 + RootCmd.PersistentFlags().StringSliceVarP(&options.Inputs, "input", "i", []string{}, "Input to run")
     36 + RootCmd.PersistentFlags().StringVarP(&options.InputFile, "inputFile", "I", "", "Input file")
     37 + 
     38 + RootCmd.PersistentFlags().StringVarP(&options.Output, "output", "o", "", "Output File")
     39 + RootCmd.PersistentFlags().StringVarP(&options.Scan.TmpOutput, "tmp", "T", "", "Temp Output folder")
     40 + RootCmd.PersistentFlags().BoolVarP(&options.JsonOutput, "json", "J", false, "Output as JSON")
     41 + RootCmd.PersistentFlags().BoolVarP(&options.Verbose, "verbose", "v", false, "Verbose")
     42 + RootCmd.PersistentFlags().BoolVarP(&options.Quiet, "quiet", "q", false, "Show only essential information")
    37 43   
    38  - RootCmd.PersistentFlags().StringVarP(&options.Output, "output", "o", "out.txt", "output name")
    39  - RootCmd.PersistentFlags().BoolVar(&options.Debug, "debug", false, "Debug")
    40  - RootCmd.PersistentFlags().BoolVarP(&options.JsonOutput, "json", "j", false, "Output as JSON")
    41  - RootCmd.PersistentFlags().BoolVarP(&options.Verbose, "verbose", "v", false, "Verbose")
    42  - RootCmd.SetHelpFunc(RootMessage)
     44 + RootCmd.PersistentFlags().BoolVar(&options.Debug, "debug", false, "Debug")
     45 + RootCmd.SetHelpFunc(RootMessage)
    43 46  }
    44 47   
    45 48  // initConfig reads in config file and ENV variables if set.
    46 49  func initConfig() {
    47  - if options.Debug {
    48  - options.Verbose = true
    49  - }
    50  - core.InitLog(&options)
     50 + if options.Debug {
     51 + options.Verbose = true
     52 + options.Quiet = false
     53 + }
     54 + core.InitLog(&options)
     55 + 
     56 + if options.Scan.TmpOutput != "" && !core.FolderExists(options.Scan.TmpOutput) {
     57 + core.InforF("Create new temp folder: %v", options.Scan.TmpOutput)
     58 + os.MkdirAll(options.Scan.TmpOutput, 0750)
     59 + }
    51 60   
    52  - if options.Scan.TmpOutput != "" && !core.FolderExists(options.Scan.TmpOutput) {
    53  - core.InforF("Create new temp folder: %v", options.Scan.TmpOutput)
    54  - os.MkdirAll(options.Scan.TmpOutput, 0750)
    55  - }
     61 + // detect if anything came from stdin
     62 + stat, _ := os.Stdin.Stat()
     63 + if (stat.Mode() & os.ModeCharDevice) == 0 {
     64 + sc := bufio.NewScanner(os.Stdin)
     65 + for sc.Scan() {
     66 + target := strings.TrimSpace(sc.Text())
     67 + if err := sc.Err(); err == nil && target != "" {
     68 + options.Inputs = append(options.Inputs, target)
     69 + }
     70 + }
     71 + }
    56 72   
    57  - // got input from stdin
    58  - if options.Input == "-" {
    59  - stat, _ := os.Stdin.Stat()
    60  - if (stat.Mode() & os.ModeCharDevice) == 0 {
    61  - var data []string
    62  - sc := bufio.NewScanner(os.Stdin)
    63  - for sc.Scan() {
    64  - input := strings.TrimSpace(sc.Text())
    65  - if err := sc.Err(); err == nil && input != "" {
    66  - data = append(data, input)
    67  - }
    68  - }
    69  - options.Input = strings.Join(data, "\n")
    70  - }
    71  - } else {
    72  - // get input from a file or just a string
    73  - if core.FileExists(options.Input) {
    74  - options.Input = core.GetFileContent(options.Input)
    75  - }
    76  - }
     73 + if core.FileExists(options.InputFile) {
     74 + options.Input = core.GetFileContent(options.Input)
     75 + }
    77 76   
    78  - // get input from a file or just a string
    79  - if core.FileExists(options.InputFile) {
    80  - options.Input = core.GetFileContent(options.InputFile)
    81  - }
     77 + // get input from a file or just a string
     78 + if core.FileExists(options.InputFile) {
     79 + options.Input = core.GetFileContent(options.InputFile)
     80 + }
    82 81   
    83  - core.InforF("Metabigor %v by %v", core.VERSION, core.AUTHOR)
    84  - core.InforF(fmt.Sprintf("Store log file to: %v", options.LogFile))
     82 + core.InforF("Metabigor %v by %v", core.VERSION, core.AUTHOR)
     83 + core.InforF(fmt.Sprintf("Store log file to: %v", options.LogFile))
    85 84  }
    86 85   
    87 86  // RootMessage print help message
    88 87  func RootMessage(cmd *cobra.Command, _ []string) {
    89  - fmt.Printf(cmd.UsageString())
    90  - h := `
     88 + fmt.Printf(cmd.UsageString())
     89 + h := `
    91 90  Examples Commands
    92 91  =================
    93 92   
    skipped 16 lines
    110 109  # Only run scan with zmap
    111 110  cat ranges.txt | metabigor scan -p '443,80' -z
    112 111   
    113  -# certificate search info on crt.sh
    114  -echo 'Target' | metabigor cert
    115  - 
    116 112  # Get Summary about IP address (powered by @thebl4ckturtle)
    117 113  cat list_of_ips.txt | metabigor ipc --json
    118 114   
     115 +# Finding more related domains of the target by applying various techniques
     116 + 
     117 +## Getting more related domains by searching for certificate info
     118 +echo 'example.com' | metabigor related -s 'cert'
     119 + 
     120 +## Getting more related by searching for whois info
     121 +echo 'example.com' | metabigor related -s 'whois'
     122 + 
     123 +## Getting more related by searching for google analytics ID
     124 +echo 'https://example.com' | metabigor related -s 'google-analytic'
     125 +metabigor tld -s 'google-analytic' -i 'UA-9152XXX' --debug
    119 126  `
    120  - fmt.Printf(h)
     127 + fmt.Printf(h)
    121 128  }
    122 129   
  • ■ ■ ■ ■ ■ ■
    cmd/scan.go
    1 1  package cmd
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "github.com/thoas/go-funk"
    6  - "io/ioutil"
    7  - "os"
    8  - "strings"
    9  - "sync"
     4 + "fmt"
     5 + "github.com/thoas/go-funk"
     6 + "io/ioutil"
     7 + "os"
     8 + "strings"
     9 + "sync"
    10 10   
    11  - "github.com/j3ssie/metabigor/core"
    12  - "github.com/j3ssie/metabigor/modules"
    13  - "github.com/spf13/cobra"
     11 + "github.com/j3ssie/metabigor/core"
     12 + "github.com/j3ssie/metabigor/modules"
     13 + "github.com/spf13/cobra"
    14 14  )
    15 15   
    16 16  func init() {
    17  - var scanCmd = &cobra.Command{
    18  - Use: "scan",
    19  - Short: "Wrapper to run scan from input",
    20  - Long: fmt.Sprintf(`Metabigor - Intelligence Tool but without API key - %v by %v`, core.VERSION, core.AUTHOR),
    21  - RunE: runScan,
    22  - }
    23  - // scan options
    24  - scanCmd.Flags().StringVarP(&options.Scan.Ports, "ports", "p", "0-65535", "Port range for previous command")
    25  - scanCmd.Flags().StringVarP(&options.Scan.Rate, "rate", "r", "3000", "rate limit for masscan command")
    26  - scanCmd.Flags().BoolVarP(&options.Scan.All, "join", "A", false, "Join all inputs to a file first then do a scan")
    27  - // scan strategy option
    28  - scanCmd.Flags().BoolVarP(&options.Scan.Flat, "flat", "f", true, "format output like this: 1.2.3.4:443")
    29  - scanCmd.Flags().BoolVarP(&options.Scan.NmapOverview, "nmap", "n", false, "Use nmap instead of masscan for overview scan")
    30  - scanCmd.Flags().BoolVarP(&options.Scan.ZmapOverview, "zmap", "z", false, "Only scan range with zmap")
    31  - scanCmd.Flags().BoolVarP(&options.Scan.SkipOverview, "skip-masscan", "s", false, "run nmap from input format like this: 1.2.3.4:443")
    32  - scanCmd.Flags().BoolVarP(&options.Scan.InputFromRustScan, "rstd", "R", false, "run nmap from rustscan input format like: 1.2.3.4 -> [80,443,8080,8443,8880]")
    33  - // more nmap options
    34  - scanCmd.Flags().StringVarP(&options.Scan.NmapScripts, "script", "S", "", "nmap scripts")
    35  - scanCmd.Flags().StringVar(&options.Scan.NmapTemplate, "nmap-command", "nmap -sSV -sC -p {{.ports}} {{.input}} {{.script}} -T4 --open -oA {{.output}}", "Nmap template command to run")
    36  - scanCmd.Flags().StringVar(&options.Scan.GrepString, "grep", "", "match string to confirm script success")
    37  - scanCmd.Flags().String("result-folder", "", "Result folder")
    38  - scanCmd.Flags().BoolVar(&options.Scan.IPv4, "4", true, "Filter input to only get ipv4")
    39  - scanCmd.Flags().BoolVar(&options.Scan.Skip80And443, "8", false, "Skip ports 80 and 443. Useful when you want to look for service behind the list of pre-scanned data")
    40  - //scanCmd.Flags().Bool("6", false, "Filter input to only get ipv4")
    41  - scanCmd.Flags().BoolP("detail", "D", false, "Do Nmap scan based on previous output")
    42  - scanCmd.Flags().Bool("uniq", true, "Unique input first")
    43  - scanCmd.SetHelpFunc(ScanHelp)
    44  - RootCmd.AddCommand(scanCmd)
     17 + var scanCmd = &cobra.Command{
     18 + Use: "scan",
     19 + Short: "Wrapper to run port scan from provided input",
     20 + Long: core.DESC,
     21 + RunE: runScan,
     22 + }
     23 + // scan options
     24 + scanCmd.Flags().StringVarP(&options.Scan.Ports, "ports", "p", "0-65535", "Port range for previous command")
     25 + scanCmd.Flags().StringVarP(&options.Scan.Rate, "rate", "r", "3000", "rate limit for masscan command")
     26 + scanCmd.Flags().BoolVarP(&options.Scan.All, "join", "A", false, "Join all inputs to a file first then do a scan")
     27 + // scan strategy option
     28 + scanCmd.Flags().BoolVarP(&options.Scan.Flat, "flat", "f", true, "format output like this: 1.2.3.4:443")
     29 + scanCmd.Flags().BoolVarP(&options.Scan.NmapOverview, "nmap", "n", false, "Use nmap instead of masscan for overview scan")
     30 + scanCmd.Flags().BoolVarP(&options.Scan.ZmapOverview, "zmap", "z", false, "Only scan range with zmap")
     31 + scanCmd.Flags().BoolVarP(&options.Scan.SkipOverview, "skip-masscan", "s", false, "run nmap from input format like this: 1.2.3.4:443")
     32 + scanCmd.Flags().BoolVarP(&options.Scan.InputFromRustScan, "rstd", "R", false, "run nmap from rustscan input format like: 1.2.3.4 -> [80,443,8080,8443,8880]")
     33 + // more nmap options
     34 + scanCmd.Flags().StringVarP(&options.Scan.NmapScripts, "script", "S", "", "nmap scripts")
     35 + scanCmd.Flags().StringVar(&options.Scan.NmapTemplate, "nmap-command", "nmap -sSV -sC -p {{.ports}} {{.input}} {{.script}} -T4 --open -oA {{.output}}", "Nmap template command to run")
     36 + scanCmd.Flags().StringVar(&options.Scan.GrepString, "grep", "", "match string to confirm script success")
     37 + scanCmd.Flags().String("result-folder", "", "Result folder")
     38 + scanCmd.Flags().BoolVar(&options.Scan.IPv4, "4", true, "Filter input to only get ipv4")
     39 + scanCmd.Flags().BoolVar(&options.Scan.Skip80And443, "8", false, "Skip ports 80 and 443. Useful when you want to look for service behind the list of pre-scanned data")
     40 + //scanCmd.Flags().Bool("6", false, "Filter input to only get ipv4")
     41 + scanCmd.Flags().BoolP("detail", "D", false, "Do Nmap scan based on previous output")
     42 + scanCmd.Flags().Bool("uniq", true, "Unique input first")
     43 + scanCmd.SetHelpFunc(ScanHelp)
     44 + RootCmd.AddCommand(scanCmd)
    45 45  }
    46 46   
    47 47  func runScan(cmd *cobra.Command, _ []string) error {
    48  - // only parse result
    49  - resultFolder, _ := cmd.Flags().GetString("result-folder")
    50  - uniq, _ := cmd.Flags().GetBool("uniq")
    51  - if resultFolder != "" {
    52  - parseResult(resultFolder, options)
    53  - os.Exit(0)
    54  - }
     48 + // only parse result
     49 + resultFolder, _ := cmd.Flags().GetString("result-folder")
     50 + uniq, _ := cmd.Flags().GetBool("uniq")
     51 + if resultFolder != "" {
     52 + parseResult(resultFolder, options)
     53 + os.Exit(0)
     54 + }
    55 55   
    56  - if options.Scan.InputFromRustScan {
    57  - options.Scan.SkipOverview = true
    58  - }
     56 + if options.Scan.InputFromRustScan {
     57 + options.Scan.SkipOverview = true
     58 + }
    59 59   
    60  - if options.Input == "-" || options.Input == "" {
    61  - core.ErrorF("No input found")
    62  - os.Exit(1)
    63  - }
     60 + if options.Input == "-" || options.Input == "" {
     61 + core.ErrorF("No input found")
     62 + os.Exit(1)
     63 + }
    64 64   
    65  - var inputs []string
    66  - if strings.Contains(options.Input, "\n") {
    67  - inputs = strings.Split(options.Input, "\n")
    68  - } else {
    69  - inputs = append(inputs, options.Input)
    70  - }
     65 + var inputs []string
     66 + if strings.Contains(options.Input, "\n") {
     67 + inputs = strings.Split(options.Input, "\n")
     68 + } else {
     69 + inputs = append(inputs, options.Input)
     70 + }
    71 71   
    72  - // make sure input is valid
    73  - if options.Scan.IPv4 {
    74  - // only filter when run zmap
    75  - if !options.Scan.SkipOverview {
    76  - inputs = core.FilterIpv4(inputs)
    77  - }
    78  - }
    79  - if uniq {
    80  - inputs = funk.UniqString(inputs)
    81  - }
    82  - if len(inputs) == 0 {
    83  - core.ErrorF("No input provided")
    84  - os.Exit(1)
    85  - }
     72 + // make sure input is valid
     73 + if options.Scan.IPv4 {
     74 + // only filter when run zmap
     75 + if !options.Scan.SkipOverview {
     76 + inputs = core.FilterIpv4(inputs)
     77 + }
     78 + }
     79 + if uniq {
     80 + inputs = funk.UniqString(inputs)
     81 + }
     82 + if len(inputs) == 0 {
     83 + core.ErrorF("No input provided")
     84 + os.Exit(1)
     85 + }
    86 86   
    87  - var result []string
    88  - var wg sync.WaitGroup
    89  - jobs := make(chan string)
     87 + var result []string
     88 + var wg sync.WaitGroup
     89 + jobs := make(chan string)
    90 90   
    91  - if options.Scan.All || options.Scan.ZmapOverview {
    92  - options.Scan.InputFile = StoreTmpInput(inputs, options)
    93  - core.DebugF("Store temp input in: %v", options.Scan.InputFile)
     91 + if options.Scan.All || options.Scan.ZmapOverview {
     92 + options.Scan.InputFile = StoreTmpInput(inputs, options)
     93 + core.DebugF("Store temp input in: %v", options.Scan.InputFile)
    94 94   
    95  - if options.Scan.ZmapOverview {
    96  - ports := core.GenPorts(options.Scan.Ports)
    97  - core.DebugF("Run port scan with: %v", strings.Trim(strings.Join(ports, ","), ","))
    98  - if options.Scan.InputFile == "" || len(ports) == 0 {
    99  - core.ErrorF("Error gen input or ports")
    100  - return nil
    101  - }
    102  - for i := 0; i < options.Concurrency; i++ {
    103  - wg.Add(1)
    104  - go func() {
    105  - defer wg.Done()
    106  - for job := range jobs {
    107  - // do real stuff here
    108  - core.BannerF("Run zmap scan on port ", job)
    109  - result = modules.RunZmap(options.Scan.InputFile, job, options)
    110  - StoreData(result, options)
    111  - }
    112  - }()
    113  - }
    114  - for _, port := range ports {
    115  - jobs <- port
    116  - }
    117  - close(jobs)
    118  - wg.Wait()
    119  - return nil
    120  - }
     95 + if options.Scan.ZmapOverview {
     96 + ports := core.GenPorts(options.Scan.Ports)
     97 + core.DebugF("Run port scan with: %v", strings.Trim(strings.Join(ports, ","), ","))
     98 + if options.Scan.InputFile == "" || len(ports) == 0 {
     99 + core.ErrorF("Error gen input or ports")
     100 + return nil
     101 + }
     102 + for i := 0; i < options.Concurrency; i++ {
     103 + wg.Add(1)
     104 + go func() {
     105 + defer wg.Done()
     106 + for job := range jobs {
     107 + // do real stuff here
     108 + core.BannerF("Run zmap scan on port ", job)
     109 + result = modules.RunZmap(options.Scan.InputFile, job, options)
     110 + StoreData(result, options)
     111 + }
     112 + }()
     113 + }
     114 + for _, port := range ports {
     115 + jobs <- port
     116 + }
     117 + close(jobs)
     118 + wg.Wait()
     119 + return nil
     120 + }
    121 121   
    122  - core.BannerF("Run overview scan on port ", options.Scan.InputFile)
    123  - if options.Scan.NmapOverview {
    124  - result = modules.RunNmap(options.Scan.InputFile, "", options)
    125  - } else {
    126  - result = modules.RunMasscan(options.Scan.InputFile, options)
    127  - }
    128  - StoreData(result, options)
    129  - return nil
     122 + core.BannerF("Run overview scan on port ", options.Scan.InputFile)
     123 + if options.Scan.NmapOverview {
     124 + result = modules.RunNmap(options.Scan.InputFile, "", options)
     125 + } else {
     126 + result = modules.RunMasscan(options.Scan.InputFile, options)
     127 + }
     128 + StoreData(result, options)
     129 + return nil
     130 + }
    130 131   
    131  - }
     132 + for i := 0; i < options.Concurrency; i++ {
     133 + wg.Add(1)
     134 + go func() {
     135 + defer wg.Done()
     136 + // do real stuff here
     137 + for job := range jobs {
     138 + if options.Scan.SkipOverview {
     139 + result = directDetail(job, options)
     140 + } else {
     141 + result = runRoutine(job, options)
     142 + }
     143 + StoreData(result, options)
     144 + }
     145 + }()
     146 + }
    132 147   
    133  - for i := 0; i < options.Concurrency; i++ {
    134  - wg.Add(1)
    135  - go func() {
    136  - defer wg.Done()
    137  - // do real stuff here
    138  - for job := range jobs {
    139  - if options.Scan.SkipOverview {
    140  - result = directDetail(job, options)
    141  - } else {
    142  - result = runRoutine(job, options)
    143  - }
    144  - StoreData(result, options)
    145  - }
    146  - }()
    147  - }
     148 + for _, input := range inputs {
     149 + jobs <- input
     150 + }
    148 151   
    149  - for _, input := range inputs {
    150  - jobs <- input
    151  - }
    152  - 
    153  - close(jobs)
    154  - wg.Wait()
     152 + close(jobs)
     153 + wg.Wait()
    155 154   
    156  - return nil
     155 + return nil
    157 156  }
    158 157   
    159 158  func runRoutine(input string, options core.Options) []string {
    160  - var data []string
    161  - core.BannerF("Run overview scan on: ", input)
    162  - if options.Scan.NmapOverview {
    163  - data = append(data, modules.RunNmap(input, "", options)...)
    164  - } else {
    165  - data = append(data, modules.RunMasscan(input, options)...)
    166  - }
     159 + var data []string
     160 + core.BannerF("Run overview scan on: ", input)
     161 + if options.Scan.NmapOverview {
     162 + data = append(data, modules.RunNmap(input, "", options)...)
     163 + } else {
     164 + data = append(data, modules.RunMasscan(input, options)...)
     165 + }
    167 166   
    168  - if !options.Scan.Detail {
    169  - return data
    170  - }
     167 + if !options.Scan.Detail {
     168 + return data
     169 + }
    171 170   
    172  - var wg sync.WaitGroup
    173  - var realData []string
    174  - for _, item := range data {
    175  - wg.Add(1)
    176  - go func(item string) {
    177  - realData = append(realData, runDetail(item, options)...)
    178  - wg.Done()
    179  - }(item)
    180  - }
    181  - wg.Wait()
    182  - return realData
     171 + var wg sync.WaitGroup
     172 + var realData []string
     173 + for _, item := range data {
     174 + wg.Add(1)
     175 + go func(item string) {
     176 + realData = append(realData, runDetail(item, options)...)
     177 + wg.Done()
     178 + }(item)
     179 + }
     180 + wg.Wait()
     181 + return realData
    183 182  }
    184 183   
    185 184  func runDetail(input string, options core.Options) []string {
    186  - if options.Scan.Flat {
    187  - return directDetail(input, options)
    188  - }
    189  - if input == "" {
    190  - return []string{}
    191  - }
    192  - if len(strings.Split(input, " - ")) == 1 {
    193  - return []string{}
    194  - }
     185 + if options.Scan.Flat {
     186 + return directDetail(input, options)
     187 + }
     188 + if input == "" {
     189 + return []string{}
     190 + }
     191 + if len(strings.Split(input, " - ")) == 1 {
     192 + return []string{}
     193 + }
    195 194   
    196  - host := strings.Split(input, " - ")[0]
    197  - ports := strings.Split(input, " - ")[1]
    198  - core.BannerF("Run detail scan on: ", fmt.Sprintf("%v:%v", host, ports))
    199  - return modules.RunNmap(host, ports, options)
     195 + host := strings.Split(input, " - ")[0]
     196 + ports := strings.Split(input, " - ")[1]
     197 + core.BannerF("Run detail scan on: ", fmt.Sprintf("%v:%v", host, ports))
     198 + return modules.RunNmap(host, ports, options)
    200 199  }
    201 200   
    202 201  func directDetail(input string, options core.Options) []string {
    203  - var out []string
    204  - if options.Scan.Skip80And443 {
    205  - if strings.HasSuffix(input, ":80") && strings.HasSuffix(input, ":443") {
    206  - return out
    207  - }
    208  - }
     202 + var out []string
     203 + if options.Scan.Skip80And443 {
     204 + if strings.HasSuffix(input, ":80") && strings.HasSuffix(input, ":443") {
     205 + return out
     206 + }
     207 + }
    209 208   
    210  - if input == "" {
    211  - return out
    212  - }
    213  - var host, ports string
     209 + if input == "" {
     210 + return out
     211 + }
     212 + var host, ports string
    214 213   
    215  - if options.Scan.InputFromRustScan {
    216  - // 1.1.1.1 -> [80,443,2095,2096,8080,8443,8880]
    217  - if !strings.Contains(input, "->") {
    218  - return out
    219  - }
    220  - host = strings.Split(input, " -> ")[0]
    221  - ports = strings.Split(input, " -> ")[1]
    222  - ports = strings.TrimLeft(strings.TrimRight(ports, "]"), "[")
    223  - } else {
    224  - if len(strings.Split(input, ":")) == 1 {
    225  - return out
    226  - }
    227  - host = strings.Split(input, ":")[0]
    228  - ports = strings.Split(input, ":")[1]
    229  - }
     214 + if options.Scan.InputFromRustScan {
     215 + // 1.1.1.1 -> [80,443,2095,2096,8080,8443,8880]
     216 + if !strings.Contains(input, "->") {
     217 + return out
     218 + }
     219 + host = strings.Split(input, " -> ")[0]
     220 + ports = strings.Split(input, " -> ")[1]
     221 + ports = strings.TrimLeft(strings.TrimRight(ports, "]"), "[")
     222 + } else {
     223 + if len(strings.Split(input, ":")) == 1 {
     224 + return out
     225 + }
     226 + host = strings.Split(input, ":")[0]
     227 + ports = strings.Split(input, ":")[1]
     228 + }
    230 229   
    231  - core.BannerF("Run detail scan on: ", fmt.Sprintf("%v:%v", host, ports))
    232  - out = modules.RunNmap(host, ports, options)
    233  - return out
     230 + core.BannerF("Run detail scan on: ", fmt.Sprintf("%v:%v", host, ports))
     231 + out = modules.RunNmap(host, ports, options)
     232 + return out
    234 233  }
    235 234   
    236 235  // only parse result
    237 236  func parseResult(resultFolder string, options core.Options) {
    238  - if !core.FolderExists(resultFolder) {
    239  - core.ErrorF("Result Folder not found: ", resultFolder)
    240  - return
    241  - }
    242  - core.BannerF("Reading result from: ", fmt.Sprintf("%v", resultFolder))
    243  - Files, err := ioutil.ReadDir(resultFolder)
    244  - if err != nil {
    245  - return
    246  - }
     237 + if !core.FolderExists(resultFolder) {
     238 + core.ErrorF("Result Folder not found: ", resultFolder)
     239 + return
     240 + }
     241 + core.BannerF("Reading result from: ", fmt.Sprintf("%v", resultFolder))
     242 + Files, err := ioutil.ReadDir(resultFolder)
     243 + if err != nil {
     244 + return
     245 + }
    247 246   
    248  - if options.Scan.Detail {
    249  - // nmap
    250  - for _, file := range Files {
    251  - filename := file.Name()
    252  - core.DebugF("Reading: %v", filename)
    253  - if strings.HasSuffix(file.Name(), "xml") && strings.HasPrefix(filename, "nmap") {
    254  - data := core.GetFileContent(filename)
    255  - result := modules.ParseNmap(data, options)
    256  - if len(result) > 0 {
    257  - fmt.Printf(strings.Join(result, "\n"))
    258  - }
    259  - }
    260  - }
    261  - return
    262  - }
     247 + if options.Scan.Detail {
     248 + // nmap
     249 + for _, file := range Files {
     250 + filename := file.Name()
     251 + core.DebugF("Reading: %v", filename)
     252 + if strings.HasSuffix(file.Name(), "xml") && strings.HasPrefix(filename, "nmap") {
     253 + data := core.GetFileContent(filename)
     254 + result := modules.ParseNmap(data, options)
     255 + if len(result) > 0 {
     256 + fmt.Printf(strings.Join(result, "\n"))
     257 + }
     258 + }
     259 + }
     260 + return
     261 + }
    263 262   
    264  - // masscan
    265  - for _, file := range Files {
    266  - filename := file.Name()
    267  - core.DebugF("Reading: %v", filename)
    268  - if strings.HasPrefix(filename, "masscan") {
    269  - data := core.GetFileContent(filename)
    270  - fmt.Println(data)
    271  - rawResult := modules.ParsingMasscan(data)
    272  - fmt.Println(rawResult)
    273  - for k, v := range rawResult {
    274  - for _, port := range v {
    275  - fmt.Printf("%v:%v\n", k, port)
    276  - }
    277  - }
    278  - }
    279  - }
     263 + // masscan
     264 + for _, file := range Files {
     265 + filename := file.Name()
     266 + core.DebugF("Reading: %v", filename)
     267 + if strings.HasPrefix(filename, "masscan") {
     268 + data := core.GetFileContent(filename)
     269 + fmt.Println(data)
     270 + rawResult := modules.ParsingMasscan(data)
     271 + fmt.Println(rawResult)
     272 + for k, v := range rawResult {
     273 + for _, port := range v {
     274 + fmt.Printf("%v:%v\n", k, port)
     275 + }
     276 + }
     277 + }
     278 + }
    280 279  }
    281 280   
    282 281  // StoreTmpInput store list of string to tmp file
    283 282  func StoreTmpInput(raw []string, options core.Options) string {
    284  - tmpDest := options.Scan.TmpOutput
    285  - tmpFile, _ := ioutil.TempFile(options.Scan.TmpOutput, "joined-*.txt")
    286  - if tmpDest != "" {
    287  - tmpFile, _ = ioutil.TempFile(tmpDest, "joined-input-*.txt")
    288  - }
    289  - tmpDest = tmpFile.Name()
    290  - core.WriteToFile(tmpDest, strings.Join(raw, "\n"))
    291  - return tmpDest
     283 + tmpDest := options.Scan.TmpOutput
     284 + tmpFile, _ := ioutil.TempFile(options.Scan.TmpOutput, "joined-*.txt")
     285 + if tmpDest != "" {
     286 + tmpFile, _ = ioutil.TempFile(tmpDest, "joined-input-*.txt")
     287 + }
     288 + tmpDest = tmpFile.Name()
     289 + core.WriteToFile(tmpDest, strings.Join(raw, "\n"))
     290 + return tmpDest
    292 291  }
    293 292   
    294 293  // ScanHelp print help message
    295 294  func ScanHelp(cmd *cobra.Command, _ []string) {
    296  - fmt.Println(cmd.UsageString())
    297  - h := "\nExample Commands:\n"
    298  - h += " # Only run masscan full ports\n"
    299  - h += " echo '1.2.3.4/24' | metabigor scan -o result.txt\n\n"
    300  - h += " # Only run nmap detail scan\n"
    301  - h += " echo '1.2.3.4:21' | metabigor scan -s -c 10\n"
    302  - h += " echo '1.2.3.4:21' | metabigor scan --tmp /tmp/raw-result/ -s -o result.txt\n\n"
    303  - h += " # Only run scan with zmap \n"
    304  - h += " cat ranges.txt | metabigor scan -p '443,80' -z\n"
    305  - h += "\n"
    306  - fmt.Printf(h)
     295 + fmt.Println(cmd.UsageString())
     296 + h := "\nExample Commands:\n"
     297 + h += " # Run Nmap with output from rustscan\n"
     298 + h += " echo '1.2.3.4 -> [80,443,2222]' | metabigor scan -R\n"
     299 + h += " # Only run masscan full ports\n"
     300 + h += " echo '1.2.3.4/24' | metabigor scan -o result.txt\n\n"
     301 + h += " # Only run nmap detail scan\n"
     302 + h += " echo '1.2.3.4:21' | metabigor scan -s -c 10\n"
     303 + h += " echo '1.2.3.4:21' | metabigor scan --tmp /tmp/raw-result/ -s -o result.txt\n\n"
     304 + h += " # Only run scan with zmap \n"
     305 + h += " cat ranges.txt | metabigor scan -p '443,80' -z\n"
     306 + h += "\n"
     307 + fmt.Printf(h)
    307 308  }
    308 309   
  • ■ ■ ■ ■ ■ ■
    cmd/search.go
    1  -package cmd
    2  - 
    3  -import (
    4  - "fmt"
    5  - "os"
    6  - "strings"
    7  - "sync"
    8  - 
    9  - "github.com/j3ssie/metabigor/core"
    10  - "github.com/j3ssie/metabigor/modules"
    11  - "github.com/spf13/cobra"
    12  -)
    13  - 
    14  -func init() {
    15  - var searchCmd = &cobra.Command{
    16  - Use: "search",
    17  - Short: "Do Search on popular search engine",
    18  - Long: fmt.Sprintf(`Metabigor - Intelligence Tool but without API key - %v by %v`, core.VERSION, core.AUTHOR),
    19  - RunE: runSearch,
    20  - }
    21  - 
    22  - searchCmd.Flags().StringP("source", "s", "fofa", "Search Engine")
    23  - searchCmd.Flags().StringSliceP("query", "q", []string{}, "Query to search (Multiple -q flags are accepted)")
    24  - searchCmd.Flags().BoolP("brute", "b", false, "Enable Brute Force")
    25  - searchCmd.Flags().BoolP("optimize", "x", false, "Enable Optimize Query")
    26  - RootCmd.AddCommand(searchCmd)
    27  -}
    28  - 
    29  -func runSearch(cmd *cobra.Command, _ []string) error {
    30  - options.Search.Source, _ = cmd.Flags().GetString("source")
    31  - options.Search.Source = strings.ToLower(options.Search.Source)
    32  - options.Search.More, _ = cmd.Flags().GetBool("brute")
    33  - options.Search.Optimize, _ = cmd.Flags().GetBool("optimize")
    34  - queries, _ := cmd.Flags().GetStringSlice("query")
    35  - 
    36  - var inputs []string
    37  - if options.Input != "-" && options.Input != "" {
    38  - if strings.Contains(options.Input, "\n") {
    39  - inputs = strings.Split(options.Input, "\n")
    40  - } else {
    41  - inputs = append(inputs, options.Input)
    42  - }
    43  - }
    44  - if len(queries) > 0 {
    45  - inputs = append(inputs, queries...)
    46  - }
    47  - if len(inputs) == 0 {
    48  - core.ErrorF("No input found")
    49  - os.Exit(1)
    50  - }
    51  - 
    52  - if options.Search.More {
    53  - inputs = addMoreQuery(inputs, options)
    54  - }
    55  - 
    56  - var wg sync.WaitGroup
    57  - jobs := make(chan string)
    58  - 
    59  - for i := 0; i < options.Concurrency; i++ {
    60  - wg.Add(1)
    61  - go func() {
    62  - defer wg.Done()
    63  - // do real stuff here
    64  - for job := range jobs {
    65  - searchResult := runSearchSingle(job, options)
    66  - StoreData(searchResult, options)
    67  - }
    68  - }()
    69  - }
    70  - 
    71  - for _, input := range inputs {
    72  - jobs <- input
    73  - }
    74  - 
    75  - close(jobs)
    76  - wg.Wait()
    77  - 
    78  - if !core.FileExists(options.Output) {
    79  - core.ErrorF("No data found")
    80  - }
    81  - core.DebugF("Unique Output: %v", options.Output)
    82  - core.Unique(options.Output)
    83  - return nil
    84  -}
    85  - 
    86  -func runSearchSingle(input string, options core.Options) []string {
    87  - var data []string
    88  - core.BannerF(fmt.Sprintf("Search on %v for: ", options.Search.Source), input)
    89  - options.Search.Query = input
    90  - 
    91  - switch options.Search.Source {
    92  - case "fofa":
    93  - data = append(data, modules.FoFaSearch(options)...)
    94  - break
    95  - case "ip":
    96  - data = append(data, modules.IPSearch(options)...)
    97  - break
    98  - }
    99  - 
    100  - return data
    101  -}
    102  - 
    103  -// add more query by add the country code with original query
    104  -func addMoreQuery(inputs []string, options core.Options) []string {
    105  - var moreQueries []string
    106  - ContriesCode := []string{"AF̵", "AL", "DZ", "AS", "AD", "AO", "AI", "AQ", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BA", "BW", "BV", "BR", "IO", "BN", "BG", "BF", "BI", "KH", "CM", "CA", "CV", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CG", "CD", "CK", "CR", "CI", "HR", "CU", "CY", "CZ", "DK", "DJ", "DM", "DO", "EC", "EG", "EH", "SV", "GQ", "ER", "EE", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GN", "GW", "GY", "HT", "HM", "HN", "HK", "HU", "IS", "IN", "ID", "IR", "IQ", "IE", "IL", "IT", "JM", "JP", "JO", "KZ", "KE", "KI", "KP", "KR", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MK", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "AN", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MP", "NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "RE", "RO", "RU", "RW", "SH", "KN", "LC", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "CS", "SC", "SL", "SG", "SK", "SI", "SB", "SO", "ZA", "GS", "ES", "LK", "SD", "SR", "SJ", "SZ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC", "TV", "UG", "UA", "AE", "GB", "US", "UM", "UY", "UZ", "VE", "VU", "VN", "VG", "VI", "WF", "YE", "ZW"}
    107  - 
    108  - for _, input := range inputs {
    109  - options.Search.Query = input
    110  - switch options.Search.Source {
    111  - case "fofa":
    112  - for _, country := range ContriesCode {
    113  - newQuery := fmt.Sprintf(`%v && country="%v"`, input, country)
    114  - moreQueries = append(moreQueries, newQuery)
    115  - }
    116  - break
    117  - }
    118  - }
    119  - 
    120  - return moreQueries
    121  -}
    122  - 
  • ■ ■ ■ ■ ■ ■
    core/chrome.go
    1 1  package core
    2 2   
    3 3  import (
    4  - "context"
    5  - "log"
    6  - "os"
    7  - "path"
    8  - "path/filepath"
    9  - "time"
     4 + "context"
     5 + "log"
     6 + "os"
     7 + "path"
     8 + "path/filepath"
     9 + "time"
    10 10   
    11  - "github.com/chromedp/chromedp"
     11 + "github.com/chromedp/chromedp"
    12 12  )
    13 13   
    14 14  // RequestWithChrome Do request with real browser
    15 15  func RequestWithChrome(url string, contentID string, timeout int) string {
    16  - // prepare the chrome options
    17  - opts := append(chromedp.DefaultExecAllocatorOptions[:],
    18  - chromedp.Flag("headless", true),
    19  - chromedp.Flag("ignore-certificate-errors", true),
    20  - chromedp.Flag("disable-gpu", true),
    21  - chromedp.Flag("enable-automation", true),
    22  - chromedp.Flag("disable-extensions", true),
    23  - chromedp.Flag("disable-setuid-sandbox", true),
    24  - chromedp.Flag("disable-web-security", true),
    25  - chromedp.Flag("no-first-run", true),
    26  - chromedp.Flag("no-default-browser-check", true),
    27  - )
     16 + // prepare the chrome options
     17 + opts := append(chromedp.DefaultExecAllocatorOptions[:],
     18 + chromedp.Flag("headless", true),
     19 + chromedp.Flag("ignore-certificate-errors", true),
     20 + chromedp.Flag("disable-gpu", true),
     21 + chromedp.Flag("enable-automation", true),
     22 + chromedp.Flag("disable-extensions", true),
     23 + chromedp.Flag("disable-setuid-sandbox", true),
     24 + chromedp.Flag("disable-web-security", true),
     25 + chromedp.Flag("no-first-run", true),
     26 + chromedp.Flag("no-default-browser-check", true),
     27 + )
    28 28   
    29  - allocCtx, bcancel := chromedp.NewExecAllocator(context.Background(), opts...)
    30  - defer bcancel()
     29 + allocCtx, bcancel := chromedp.NewExecAllocator(context.Background(), opts...)
     30 + defer bcancel()
    31 31   
    32  - ctx, cancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
    33  - ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
    34  - defer cancel()
     32 + ctx, cancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
     33 + ctx, cancel = context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
     34 + defer cancel()
    35 35   
    36  - // run task list
    37  - var data string
    38  - err := chromedp.Run(ctx,
    39  - chromedp.Navigate(url),
    40  - chromedp.OuterHTML(contentID, &data, chromedp.NodeVisible, chromedp.ByID),
    41  - )
    42  - DebugF(data)
     36 + // run task list
     37 + var data string
     38 + err := chromedp.Run(ctx,
     39 + chromedp.Navigate(url),
     40 + chromedp.OuterHTML(contentID, &data, chromedp.NodeVisible, chromedp.ByID),
     41 + )
     42 + DebugF(data)
    43 43   
    44  - // clean chromedp-runner folder
    45  - cleanUp()
     44 + // clean chromedp-runner folder
     45 + cleanUp()
    46 46   
    47  - if err != nil {
    48  - InforF("[ERRR] %v", err)
    49  - return ""
    50  - }
    51  - return data
     47 + if err != nil {
     48 + InforF("[ERRR] %v", err)
     49 + return ""
     50 + }
     51 + return data
    52 52  }
    53 53   
    54 54  func cleanUp() {
    55  - tmpFolder := path.Join(os.TempDir(), "chromedp-runner*")
    56  - if _, err := os.Stat("/tmp/"); !os.IsNotExist(err) {
    57  - tmpFolder = path.Join("/tmp/", "chromedp-runner*")
    58  - }
    59  - junks, err := filepath.Glob(tmpFolder)
    60  - if err != nil {
    61  - return
    62  - }
    63  - for _, junk := range junks {
    64  - os.RemoveAll(junk)
    65  - }
     55 + tmpFolder := path.Join(os.TempDir(), "chromedp-runner*")
     56 + if _, err := os.Stat("/tmp/"); !os.IsNotExist(err) {
     57 + tmpFolder = path.Join("/tmp/", "chromedp-runner*")
     58 + }
     59 + junks, err := filepath.Glob(tmpFolder)
     60 + if err != nil {
     61 + return
     62 + }
     63 + for _, junk := range junks {
     64 + os.RemoveAll(junk)
     65 + }
    66 66  }
    67 67   
  • ■ ■ ■ ■ ■ ■
    core/common.go
    1 1  package core
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "io"
    6  - "io/ioutil"
    7  - "os"
    8  - "path"
     4 + "fmt"
     5 + "io"
     6 + "io/ioutil"
     7 + "os"
     8 + "path"
    9 9   
    10  - // "github.com/Sirupsen/logrus"
    11  - "github.com/fatih/color"
    12  - "github.com/sirupsen/logrus"
    13  - prefixed "github.com/x-cray/logrus-prefixed-formatter"
     10 + // "github.com/Sirupsen/logrus"
     11 + "github.com/fatih/color"
     12 + "github.com/sirupsen/logrus"
     13 + prefixed "github.com/x-cray/logrus-prefixed-formatter"
    14 14  )
    15 15   
    16 16  var logger = logrus.New()
    17 17   
    18 18  // InitLog init log
    19 19  func InitLog(options *Options) {
    20  - if options.Scan.TmpOutput == "" {
    21  - options.Scan.TmpOutput = path.Join(os.TempDir(), "mtg-log")
    22  - }
    23  - if !FolderExists(options.Scan.TmpOutput) {
    24  - os.MkdirAll(options.Scan.TmpOutput, 0755)
    25  - }
    26  - options.LogFile = path.Join(options.Scan.TmpOutput, fmt.Sprintf("metabigor-%s.log", GetTS()))
    27  - f, err := os.OpenFile(options.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    28  - if err != nil {
    29  - logger.Error("error opening file: %v", err)
    30  - }
     20 + if options.Scan.TmpOutput == "" {
     21 + options.Scan.TmpOutput = path.Join(os.TempDir(), "mtg-log")
     22 + }
     23 + if !FolderExists(options.Scan.TmpOutput) {
     24 + os.MkdirAll(options.Scan.TmpOutput, 0755)
     25 + }
     26 + options.LogFile = path.Join(options.Scan.TmpOutput, fmt.Sprintf("metabigor-%s.log", GetTS()))
     27 + f, err := os.OpenFile(options.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
     28 + if err != nil {
     29 + logger.Error("error opening file: %v", err)
     30 + }
    31 31   
    32  - mwr := io.MultiWriter(os.Stderr, f)
     32 + mwr := io.MultiWriter(os.Stderr, f)
    33 33   
    34  - logger.SetLevel(logrus.InfoLevel)
    35  - logger = &logrus.Logger{
    36  - Out: mwr,
    37  - Level: logrus.InfoLevel,
    38  - Formatter: &prefixed.TextFormatter{
    39  - ForceColors: true,
    40  - ForceFormatting: true,
    41  - },
    42  - }
     34 + logger.SetLevel(logrus.InfoLevel)
     35 + logger = &logrus.Logger{
     36 + Out: mwr,
     37 + Level: logrus.InfoLevel,
     38 + Formatter: &prefixed.TextFormatter{
     39 + ForceColors: true,
     40 + ForceFormatting: true,
     41 + },
     42 + }
    43 43   
    44  - if options.Debug == true {
    45  - logger.SetOutput(mwr)
    46  - logger.SetLevel(logrus.DebugLevel)
    47  - } else if options.Verbose == true {
    48  - logger.SetOutput(mwr)
    49  - logger.SetLevel(logrus.InfoLevel)
    50  - } else {
    51  - logger.SetOutput(ioutil.Discard)
    52  - }
     44 + if options.Debug == true {
     45 + logger.SetOutput(mwr)
     46 + logger.SetLevel(logrus.DebugLevel)
     47 + } else if options.Verbose == true {
     48 + logger.SetOutput(mwr)
     49 + logger.SetLevel(logrus.InfoLevel)
     50 + } else {
     51 + logger.SetOutput(ioutil.Discard)
     52 + }
    53 53  }
    54 54   
    55 55  // GoodF print good message
    56 56  func GoodF(format string, args ...interface{}) {
    57  - good := color.HiGreenString("[+]")
    58  - fmt.Fprintf(os.Stderr, "%s %s\n", good, fmt.Sprintf(format, args...))
     57 + good := color.HiGreenString("[+]")
     58 + fmt.Fprintf(os.Stderr, "%s %s\n", good, fmt.Sprintf(format, args...))
    59 59  }
    60 60   
    61 61  // BannerF print info message
    62 62  func BannerF(format string, data string) {
    63  - banner := color.BlueString("[*] %v", format)
    64  - logger.Info(fmt.Sprintf("%v%v", banner, color.HiGreenString(data)))
     63 + banner := color.BlueString("[*] %v", format)
     64 + logger.Info(fmt.Sprintf("%v%v", banner, color.HiGreenString(data)))
    65 65  }
    66 66   
    67 67  // InforF print info message
    68 68  func InforF(format string, args ...interface{}) {
    69  - logger.Info(fmt.Sprintf(format, args...))
     69 + logger.Info(fmt.Sprintf(format, args...))
    70 70  }
    71 71   
    72 72  // WarningF print good message
    73 73  func WarningF(format string, args ...interface{}) {
    74  - good := color.YellowString("[!]")
    75  - fmt.Fprintf(os.Stderr, "%s %s\n", good, fmt.Sprintf(format, args...))
     74 + good := color.YellowString("[!]")
     75 + fmt.Fprintf(os.Stderr, "%s %s\n", good, fmt.Sprintf(format, args...))
    76 76  }
    77 77   
    78 78  // DebugF print debug message
    79 79  func DebugF(format string, args ...interface{}) {
    80  - logger.Debug(fmt.Sprintf(format, args...))
     80 + logger.Debug(fmt.Sprintf(format, args...))
    81 81  }
    82 82   
    83 83  // ErrorF print good message
    84 84  func ErrorF(format string, args ...interface{}) {
    85  - logger.Error(fmt.Sprintf(format, args...))
     85 + logger.Error(fmt.Sprintf(format, args...))
    86 86  }
    87 87   
  • ■ ■ ■ ■ ■ ■
    core/config_test.go
    1 1  package core
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "testing"
     4 + "fmt"
     5 + "testing"
    6 6  )
    7 7   
    8 8  func TestGetCred(t *testing.T) {
    9  - var options Options
    10  - options.Debug = true
    11  - options.ConfigFile = "~/.metabigor/config.yaml"
    12  - cred := GetCred("fofa", options)
    13  - fmt.Println(cred)
    14  - if cred == "" {
    15  - t.Errorf("Error GetCred")
    16  - }
     9 + var options Options
     10 + options.Debug = true
     11 + options.ConfigFile = "~/.metabigor/config.yaml"
     12 + cred := GetCred("fofa", options)
     13 + fmt.Println(cred)
     14 + if cred == "" {
     15 + t.Errorf("Error GetCred")
     16 + }
    17 17  }
    18 18  func TestSaveSess(t *testing.T) {
    19  - var options Options
    20  - options.Debug = true
    21  - options.ConfigFile = "~/.metabigor/config.yaml"
    22  - cred := SaveSess("fofa", "_fofapro_ars_session=e059371a4bad81d3c47ce6290240aee4", options)
    23  - fmt.Println(cred)
    24  - if cred == "" {
    25  - t.Errorf("Error SaveSess")
    26  - }
     19 + var options Options
     20 + options.Debug = true
     21 + options.ConfigFile = "~/.metabigor/config.yaml"
     22 + cred := SaveSess("fofa", "_fofapro_ars_session=e059371a4bad81d3c47ce6290240aee4", options)
     23 + fmt.Println(cred)
     24 + if cred == "" {
     25 + t.Errorf("Error SaveSess")
     26 + }
    27 27  }
    28 28   
  • ■ ■ ■ ■ ■ ■
    core/filter.go
    skipped 3 lines
    4 4   
    5 5  // FilterIpv4 only get Ipv4
    6 6  func FilterIpv4(raw []string) []string {
    7  - var result []string
    8  - var re = regexp.MustCompile(`(?m)^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$`)
    9  - for _, input := range raw {
    10  - match := re.MatchString(input)
    11  - if match {
    12  - result = append(result, input)
    13  - }
    14  - }
    15  - return result
     7 + var result []string
     8 + var re = regexp.MustCompile(`(?m)^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$`)
     9 + for _, input := range raw {
     10 + match := re.MatchString(input)
     11 + if match {
     12 + result = append(result, input)
     13 + }
     14 + }
     15 + return result
    16 16  }
    17 17   
    18 18  // FilterIpv6 only get Ipv6
    19 19  func FilterIpv6(raw []string) []string {
    20  - var result []string
    21  - var re = regexp.MustCompile(`^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$`)
    22  - for _, input := range raw {
    23  - match := re.MatchString(input)
    24  - if match {
    25  - result = append(result, input)
    26  - }
    27  - }
    28  - return result
     20 + var result []string
     21 + var re = regexp.MustCompile(`^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$`)
     22 + for _, input := range raw {
     23 + match := re.MatchString(input)
     24 + if match {
     25 + result = append(result, input)
     26 + }
     27 + }
     28 + return result
    29 29  }
    30 30   
  • ■ ■ ■ ■ ■ ■
    core/helper.go
    1 1  package core
    2 2   
    3 3  import (
    4  - "archive/zip"
    5  - "bufio"
    6  - "crypto/sha1"
    7  - "encoding/base64"
    8  - "encoding/json"
    9  - "fmt"
    10  - "io"
    11  - "io/ioutil"
    12  - "net/url"
    13  - "os"
    14  - "path/filepath"
    15  - "regexp"
    16  - "strconv"
    17  - "strings"
    18  - "time"
     4 + "archive/zip"
     5 + "bufio"
     6 + "crypto/sha1"
     7 + "encoding/base64"
     8 + "encoding/json"
     9 + "fmt"
     10 + "io"
     11 + "io/ioutil"
     12 + "net/url"
     13 + "os"
     14 + "path/filepath"
     15 + "regexp"
     16 + "strconv"
     17 + "strings"
     18 + "time"
    19 19   
    20  - "github.com/mitchellh/go-homedir"
     20 + "github.com/mitchellh/go-homedir"
    21 21  )
    22 22   
    23 23  // GetFileContent Reading file and return content of it
    24 24  func GetFileContent(filename string) string {
    25  - var result string
    26  - if strings.Contains(filename, "~") {
    27  - filename, _ = homedir.Expand(filename)
    28  - }
    29  - file, err := os.Open(filename)
    30  - if err != nil {
    31  - return result
    32  - }
    33  - defer file.Close()
    34  - b, err := ioutil.ReadAll(file)
    35  - if err != nil {
    36  - return result
    37  - }
    38  - return string(b)
     25 + var result string
     26 + if strings.Contains(filename, "~") {
     27 + filename, _ = homedir.Expand(filename)
     28 + }
     29 + file, err := os.Open(filename)
     30 + if err != nil {
     31 + return result
     32 + }
     33 + defer file.Close()
     34 + b, err := ioutil.ReadAll(file)
     35 + if err != nil {
     36 + return result
     37 + }
     38 + return string(b)
    39 39  }
    40 40   
    41 41  // ReadingFile Reading file and return content as []string
    42 42  func ReadingFile(filename string) []string {
    43  - var result []string
    44  - if strings.HasPrefix(filename, "~") {
    45  - filename, _ = homedir.Expand(filename)
    46  - }
    47  - file, err := os.Open(filename)
    48  - defer file.Close()
    49  - if err != nil {
    50  - return result
    51  - }
     43 + var result []string
     44 + if strings.HasPrefix(filename, "~") {
     45 + filename, _ = homedir.Expand(filename)
     46 + }
     47 + file, err := os.Open(filename)
     48 + defer file.Close()
     49 + if err != nil {
     50 + return result
     51 + }
    52 52   
    53  - scanner := bufio.NewScanner(file)
    54  - for scanner.Scan() {
    55  - val := scanner.Text()
    56  - result = append(result, val)
    57  - }
     53 + scanner := bufio.NewScanner(file)
     54 + for scanner.Scan() {
     55 + val := scanner.Text()
     56 + result = append(result, val)
     57 + }
    58 58   
    59  - if err := scanner.Err(); err != nil {
    60  - return result
    61  - }
    62  - return result
     59 + if err := scanner.Err(); err != nil {
     60 + return result
     61 + }
     62 + return result
    63 63  }
    64 64   
    65 65  // ReadingFileUnique Reading file and return content as []string
    66 66  func ReadingFileUnique(filename string) []string {
    67  - var result []string
    68  - if strings.Contains(filename, "~") {
    69  - filename, _ = homedir.Expand(filename)
    70  - }
    71  - file, err := os.Open(filename)
    72  - defer file.Close()
    73  - if err != nil {
    74  - return result
    75  - }
     67 + var result []string
     68 + if strings.Contains(filename, "~") {
     69 + filename, _ = homedir.Expand(filename)
     70 + }
     71 + file, err := os.Open(filename)
     72 + defer file.Close()
     73 + if err != nil {
     74 + return result
     75 + }
    76 76   
    77  - unique := true
    78  - seen := make(map[string]bool)
     77 + unique := true
     78 + seen := make(map[string]bool)
    79 79   
    80  - scanner := bufio.NewScanner(file)
    81  - for scanner.Scan() {
    82  - val := scanner.Text()
    83  - // unique stuff
    84  - if val == "" {
    85  - continue
    86  - }
    87  - val = strings.TrimSpace(val)
    88  - if seen[val] && unique {
    89  - continue
    90  - }
     80 + scanner := bufio.NewScanner(file)
     81 + for scanner.Scan() {
     82 + val := scanner.Text()
     83 + // unique stuff
     84 + if val == "" {
     85 + continue
     86 + }
     87 + val = strings.TrimSpace(val)
     88 + if seen[val] && unique {
     89 + continue
     90 + }
    91 91   
    92  - if unique {
    93  - seen[val] = true
    94  - result = append(result, val)
    95  - }
    96  - }
     92 + if unique {
     93 + seen[val] = true
     94 + result = append(result, val)
     95 + }
     96 + }
    97 97   
    98  - if err := scanner.Err(); err != nil {
    99  - return result
    100  - }
    101  - return result
     98 + if err := scanner.Err(); err != nil {
     99 + return result
     100 + }
     101 + return result
    102 102  }
    103 103   
    104 104  // WriteToFile write string to a file
    105 105  func WriteToFile(filename string, data string) (string, error) {
    106  - file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
    107  - if err != nil {
    108  - return "", err
    109  - }
    110  - defer file.Close()
     106 + file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
     107 + if err != nil {
     108 + return "", err
     109 + }
     110 + defer file.Close()
    111 111   
    112  - _, err = io.WriteString(file, data+"\n")
    113  - if err != nil {
    114  - return "", err
    115  - }
    116  - return filename, file.Sync()
     112 + _, err = io.WriteString(file, data+"\n")
     113 + if err != nil {
     114 + return "", err
     115 + }
     116 + return filename, file.Sync()
    117 117  }
    118 118   
    119 119  // Unique unique content of a file and remove blank line
    120 120  func Unique(filename string) {
    121  - data := ReadingFileUnique(filename)
    122  - WriteToFile(filename, strings.Join(data, "\n"))
     121 + if filename == "" {
     122 + return
     123 + }
     124 + DebugF("Unique Output: %v", filename)
     125 + data := ReadingFileUnique(filename)
     126 + WriteToFile(filename, strings.Join(data, "\n"))
    123 127  }
    124 128   
    125 129  // AppendToContent append string to a file
    126 130  func AppendToContent(filename string, data string) (string, error) {
    127  - // If the file doesn't exist, create it, or append to the file
    128  - f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    129  - if err != nil {
    130  - return "", err
    131  - }
    132  - if _, err := f.Write([]byte(data + "\n")); err != nil {
    133  - return "", err
    134  - }
    135  - if err := f.Close(); err != nil {
    136  - return "", err
    137  - }
    138  - return filename, nil
     131 + // If the file doesn't exist, create it, or append to the file
     132 + f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
     133 + if err != nil {
     134 + return "", err
     135 + }
     136 + if _, err := f.Write([]byte(data + "\n")); err != nil {
     137 + return "", err
     138 + }
     139 + if err := f.Close(); err != nil {
     140 + return "", err
     141 + }
     142 + return filename, nil
    139 143  }
    140 144   
    141 145  // FileExists check if file is exist or not
    142 146  func FileExists(filename string) bool {
    143  - info, err := os.Stat(filename)
    144  - if os.IsNotExist(err) {
    145  - return false
    146  - }
    147  - return !info.IsDir()
     147 + info, err := os.Stat(filename)
     148 + if os.IsNotExist(err) {
     149 + return false
     150 + }
     151 + return !info.IsDir()
    148 152  }
    149 153   
    150 154  // FolderExists check if file is exist or not
    151 155  func FolderExists(foldername string) bool {
    152  - if _, err := os.Stat(foldername); os.IsNotExist(err) {
    153  - return false
    154  - }
    155  - return true
     156 + if _, err := os.Stat(foldername); os.IsNotExist(err) {
     157 + return false
     158 + }
     159 + return true
    156 160  }
    157 161   
    158 162  // GetFileNames get all file name with extension
    159 163  func GetFileNames(dir string, ext string) []string {
    160  - if _, err := os.Stat(dir); os.IsNotExist(err) {
    161  - return nil
    162  - }
     164 + if _, err := os.Stat(dir); os.IsNotExist(err) {
     165 + return nil
     166 + }
    163 167   
    164  - var files []string
    165  - filepath.Walk(dir, func(path string, f os.FileInfo, _ error) error {
    166  - if !f.IsDir() {
    167  - if strings.HasSuffix(f.Name(), ext) {
    168  - filename, _ := filepath.Abs(path)
    169  - files = append(files, filename)
    170  - }
    171  - }
    172  - return nil
    173  - })
    174  - return files
     168 + var files []string
     169 + filepath.Walk(dir, func(path string, f os.FileInfo, _ error) error {
     170 + if !f.IsDir() {
     171 + if strings.HasSuffix(f.Name(), ext) {
     172 + filename, _ := filepath.Abs(path)
     173 + files = append(files, filename)
     174 + }
     175 + }
     176 + return nil
     177 + })
     178 + return files
    175 179  }
    176 180   
    177 181  // IsJSON check if string is JSON or not
    178 182  func IsJSON(str string) bool {
    179  - var js json.RawMessage
    180  - return json.Unmarshal([]byte(str), &js) == nil
     183 + var js json.RawMessage
     184 + return json.Unmarshal([]byte(str), &js) == nil
    181 185  }
    182 186   
    183 187  // GetTS get current timestamp and return a string
    184 188  func GetTS() string {
    185  - return strconv.FormatInt(time.Now().Unix(), 10)
     189 + return strconv.FormatInt(time.Now().Unix(), 10)
    186 190  }
    187 191   
    188 192  // GenHash gen SHA1 hash from string
    189 193  func GenHash(text string) string {
    190  - h := sha1.New()
    191  - h.Write([]byte(text))
    192  - hashed := h.Sum(nil)
    193  - return fmt.Sprintf("%x", hashed)
     194 + h := sha1.New()
     195 + h.Write([]byte(text))
     196 + hashed := h.Sum(nil)
     197 + return fmt.Sprintf("%x", hashed)
    194 198  }
    195 199   
    196 200  // Unzip will decompress a zip archive, moving all files and folders
    197 201  // within the zip file (parameter 1) to an output directory (parameter 2).
    198 202  func Unzip(src string, dest string) ([]string, error) {
    199 203   
    200  - var filenames []string
     204 + var filenames []string
    201 205   
    202  - r, err := zip.OpenReader(src)
    203  - if err != nil {
    204  - return filenames, err
    205  - }
    206  - defer r.Close()
     206 + r, err := zip.OpenReader(src)
     207 + if err != nil {
     208 + return filenames, err
     209 + }
     210 + defer r.Close()
    207 211   
    208  - for _, f := range r.File {
     212 + for _, f := range r.File {
    209 213   
    210  - // Store filename/path for returning and using later on
    211  - fpath := filepath.Join(dest, f.Name)
     214 + // Store filename/path for returning and using later on
     215 + fpath := filepath.Join(dest, f.Name)
    212 216   
    213  - if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
    214  - return filenames, fmt.Errorf("%s: illegal file path", fpath)
    215  - }
     217 + if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
     218 + return filenames, fmt.Errorf("%s: illegal file path", fpath)
     219 + }
    216 220   
    217  - filenames = append(filenames, fpath)
     221 + filenames = append(filenames, fpath)
    218 222   
    219  - if f.FileInfo().IsDir() {
    220  - // Make Folder
    221  - os.MkdirAll(fpath, os.ModePerm)
    222  - continue
    223  - }
     223 + if f.FileInfo().IsDir() {
     224 + // Make Folder
     225 + os.MkdirAll(fpath, os.ModePerm)
     226 + continue
     227 + }
    224 228   
    225  - // Make File
    226  - if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
    227  - return filenames, err
    228  - }
     229 + // Make File
     230 + if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
     231 + return filenames, err
     232 + }
    229 233   
    230  - outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
    231  - if err != nil {
    232  - return filenames, err
    233  - }
     234 + outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
     235 + if err != nil {
     236 + return filenames, err
     237 + }
    234 238   
    235  - rc, err := f.Open()
    236  - if err != nil {
    237  - return filenames, err
    238  - }
     239 + rc, err := f.Open()
     240 + if err != nil {
     241 + return filenames, err
     242 + }
    239 243   
    240  - _, err = io.Copy(outFile, rc)
     244 + _, err = io.Copy(outFile, rc)
    241 245   
    242  - // Close the file without defer to close before next iteration of loop
    243  - outFile.Close()
    244  - rc.Close()
     246 + // Close the file without defer to close before next iteration of loop
     247 + outFile.Close()
     248 + rc.Close()
    245 249   
    246  - if err != nil {
    247  - return filenames, err
    248  - }
    249  - }
    250  - return filenames, nil
     250 + if err != nil {
     251 + return filenames, err
     252 + }
     253 + }
     254 + return filenames, nil
    251 255  }
    252 256   
    253 257  // ExpandLength make slice to length
    254 258  func ExpandLength(list []string, length int) []string {
    255  - c := []string{}
    256  - for i := 1; i <= length; i++ {
    257  - c = append(c, list[i%len(list)])
    258  - }
    259  - return c
     259 + c := []string{}
     260 + for i := 1; i <= length; i++ {
     261 + c = append(c, list[i%len(list)])
     262 + }
     263 + return c
    260 264  }
    261 265   
    262 266  // StartWithNum check if string start with number
    263 267  func StartWithNum(raw string) bool {
    264  - r, err := regexp.Compile("^[0-9].*")
    265  - if err != nil {
    266  - return false
    267  - }
    268  - return r.MatchString(raw)
     268 + r, err := regexp.Compile("^[0-9].*")
     269 + if err != nil {
     270 + return false
     271 + }
     272 + return r.MatchString(raw)
    269 273  }
    270 274   
    271 275  // StripPath just strip some invalid string path
    272 276  func StripPath(raw string) string {
    273  - raw = strings.Replace(raw, "/", "_", -1)
    274  - raw = strings.Replace(raw, " ", "_", -1)
    275  - return raw
     277 + raw = strings.Replace(raw, "/", "_", -1)
     278 + raw = strings.Replace(raw, " ", "_", -1)
     279 + return raw
    276 280  }
    277 281   
    278 282  // Base64Encode just Base64 Encode
    279 283  func Base64Encode(raw string) string {
    280  - return base64.StdEncoding.EncodeToString([]byte(raw))
     284 + return base64.StdEncoding.EncodeToString([]byte(raw))
    281 285  }
    282 286   
    283 287  // Base64Decode just Base64 Encode
    284 288  func Base64Decode(raw string) string {
    285  - data, err := base64.StdEncoding.DecodeString(raw)
    286  - if err != nil {
    287  - return raw
    288  - }
    289  - return string(data)
     289 + data, err := base64.StdEncoding.DecodeString(raw)
     290 + if err != nil {
     291 + return raw
     292 + }
     293 + return string(data)
    290 294  }
    291 295   
    292 296  // URLDecode decode url
    293 297  func URLDecode(raw string) string {
    294  - decodedValue, err := url.QueryUnescape(raw)
    295  - if err != nil {
    296  - return raw
    297  - }
    298  - return decodedValue
     298 + decodedValue, err := url.QueryUnescape(raw)
     299 + if err != nil {
     300 + return raw
     301 + }
     302 + return decodedValue
    299 303  }
    300 304   
    301 305  // URLEncode Encode query
    302 306  func URLEncode(raw string) string {
    303  - decodedValue := url.QueryEscape(raw)
    304  - return decodedValue
     307 + decodedValue := url.QueryEscape(raw)
     308 + return decodedValue
    305 309  }
    306 310   
    307 311  // GenPorts gen list of ports based on input
    308 312  func GenPorts(raw string) []string {
    309  - var ports []string
    310  - if strings.Contains(raw, ",") {
    311  - items := strings.Split(raw, ",")
    312  - for _, item := range items {
    313  - if strings.Contains(item, "-") {
    314  - min, err := strconv.Atoi(strings.Split(item, "-")[0])
    315  - if err != nil {
    316  - continue
    317  - }
    318  - max, err := strconv.Atoi(strings.Split(item, "-")[1])
    319  - if err != nil {
    320  - continue
    321  - }
    322  - for i := min; i <= max; i++ {
    323  - ports = append(ports, fmt.Sprintf("%v", i))
    324  - }
    325  - } else {
    326  - ports = append(ports, item)
    327  - }
    328  - }
    329  - } else {
    330  - if strings.Contains(raw, "-") {
    331  - min, err := strconv.Atoi(strings.Split(raw, "-")[0])
    332  - if err != nil {
    333  - return ports
    334  - }
    335  - max, err := strconv.Atoi(strings.Split(raw, "-")[1])
    336  - if err != nil {
    337  - return ports
    338  - }
    339  - for i := min; i <= max; i++ {
    340  - ports = append(ports, fmt.Sprintf("%v", i))
    341  - }
    342  - } else {
    343  - ports = append(ports, raw)
    344  - }
    345  - }
     313 + var ports []string
     314 + if strings.Contains(raw, ",") {
     315 + items := strings.Split(raw, ",")
     316 + for _, item := range items {
     317 + if strings.Contains(item, "-") {
     318 + min, err := strconv.Atoi(strings.Split(item, "-")[0])
     319 + if err != nil {
     320 + continue
     321 + }
     322 + max, err := strconv.Atoi(strings.Split(item, "-")[1])
     323 + if err != nil {
     324 + continue
     325 + }
     326 + for i := min; i <= max; i++ {
     327 + ports = append(ports, fmt.Sprintf("%v", i))
     328 + }
     329 + } else {
     330 + ports = append(ports, item)
     331 + }
     332 + }
     333 + } else {
     334 + if strings.Contains(raw, "-") {
     335 + min, err := strconv.Atoi(strings.Split(raw, "-")[0])
     336 + if err != nil {
     337 + return ports
     338 + }
     339 + max, err := strconv.Atoi(strings.Split(raw, "-")[1])
     340 + if err != nil {
     341 + return ports
     342 + }
     343 + for i := min; i <= max; i++ {
     344 + ports = append(ports, fmt.Sprintf("%v", i))
     345 + }
     346 + } else {
     347 + ports = append(ports, raw)
     348 + }
     349 + }
    346 350   
    347  - return ports
     351 + return ports
    348 352  }
    349 353   
  • ■ ■ ■ ■ ■ ■
    core/options.go
    skipped 1 lines
    2 2   
    3 3  // Options global options
    4 4  type Options struct {
    5  - Input string
    6  - InputFile string
    7  - Output string
    8  - TmpOutput string
    9  - ConfigFile string
    10  - LogFile string
    11  - Proxy string
     5 + Input string
     6 + InputFile string
    12 7   
    13  - Concurrency int
    14  - Delay int
    15  - SaveRaw bool
    16  - Timeout int
    17  - JsonOutput bool
    18  - Verbose bool
    19  - Debug bool
    20  - Scan ScanOptions
    21  - Net NetOptions
    22  - Search SearchOptions
    23  - CVE CVEOptions
    24  - Cert CertOptions
     8 + Inputs []string
     9 + Output string
     10 + TmpOutput string
     11 + ConfigFile string
     12 + LogFile string
     13 + Proxy string
     14 + 
     15 + Concurrency int
     16 + Delay int
     17 + SaveRaw bool
     18 + Timeout int
     19 + Retry int
     20 + JsonOutput bool
     21 + Verbose bool
     22 + Quiet bool
     23 + Debug bool
     24 + Scan ScanOptions
     25 + Net NetOptions
     26 + Search SearchOptions
     27 + CVE CVEOptions
     28 + Cert CertOptions
     29 + Tld TldOptions
     30 +}
     31 + 
     32 +// TldOptions options for tld command
     33 +type TldOptions struct {
     34 + Source string
    25 35  }
    26 36   
    27  -// CertOptions options for net command
     37 +// CertOptions options for cert command
    28 38  type CertOptions struct {
    29  - Clean bool
    30  - OnlyWildCard bool
     39 + Clean bool
     40 + OnlyWildCard bool
    31 41  }
    32 42   
    33 43  // ScanOptions options for net command
    34 44  type ScanOptions struct {
    35  - Ports string
    36  - Rate string
    37  - NmapTemplate string
    38  - NmapOverview bool
    39  - ZmapOverview bool
    40  - Detail bool
    41  - Flat bool
    42  - All bool
    43  - IPv4 bool
    44  - IPv6 bool
    45  - Skip80And443 bool
    46  - SkipOverview bool
    47  - InputFromRustScan bool
    48  - TmpOutput string
    49  - NmapScripts string
    50  - GrepString string
    51  - InputFile string
     45 + Ports string
     46 + Rate string
     47 + NmapTemplate string
     48 + NmapOverview bool
     49 + ZmapOverview bool
     50 + Detail bool
     51 + Flat bool
     52 + All bool
     53 + IPv4 bool
     54 + IPv6 bool
     55 + Skip80And443 bool
     56 + SkipOverview bool
     57 + InputFromRustScan bool
     58 + TmpOutput string
     59 + NmapScripts string
     60 + GrepString string
     61 + InputFile string
    52 62  }
    53 63   
    54 64  // NetOptions options for net command
    55 65  type NetOptions struct {
    56  - Asn string
    57  - Org string
    58  - IP string
    59  - Domain string
    60  - SearchType string
    61  - Optimize bool
    62  - ExactMatch bool
     66 + Asn string
     67 + Org string
     68 + IP string
     69 + Domain string
     70 + SearchType string
     71 + Optimize bool
     72 + ExactMatch bool
    63 73  }
    64 74   
    65 75  // SearchOptions options for net command
    66 76  type SearchOptions struct {
    67  - Source string
    68  - Query string
    69  - Optimize bool
    70  - More bool
     77 + Source string
     78 + Query string
     79 + Optimize bool
     80 + More bool
    71 81  }
    72 82   
    73 83  // CVEOptions options for cve command
    74 84  type CVEOptions struct {
    75  - Software string
    76  - Version string
     85 + Software string
     86 + Version string
    77 87  }
    78 88   
    79 89  // Request all information about request
    80 90  type Request struct {
    81  - Timeout int
    82  - Repeat int
    83  - Scheme string
    84  - Host string
    85  - Port string
    86  - Path string
    87  - URL string
    88  - Proxy string
    89  - Method string
    90  - Redirect bool
    91  - Headers []map[string]string
    92  - Body string
    93  - Beautify string
     91 + Timeout int
     92 + Repeat int
     93 + Scheme string
     94 + Host string
     95 + Port string
     96 + Path string
     97 + URL string
     98 + Proxy string
     99 + Method string
     100 + Redirect bool
     101 + Headers []map[string]string
     102 + Body string
     103 + Beautify string
    94 104  }
    95 105   
    96 106  // Response all information about response
    97 107  type Response struct {
    98  - HasPopUp bool
    99  - StatusCode int
    100  - Status string
    101  - Headers []map[string]string
    102  - Body string
    103  - ResponseTime float64
    104  - Length int
    105  - Beautify string
    106  - BeautifyHeader string
     108 + HasPopUp bool
     109 + StatusCode int
     110 + Status string
     111 + Headers []map[string]string
     112 + Body string
     113 + ResponseTime float64
     114 + Length int
     115 + Beautify string
     116 + BeautifyHeader string
     117 +}
     118 + 
     119 +type RelatedDomain struct {
     120 + Domain string
     121 + RawData string
     122 + Technique string
     123 + Source string
     124 + Output string
    107 125  }
    108 126   
  • ■ ■ ■ ■ ■ ■
    core/request.go
    1 1  package core
    2 2   
    3 3  import (
    4  - "crypto/tls"
    5  - "fmt"
    6  - "io/ioutil"
    7  - "net"
    8  - "net/http"
    9  - "strconv"
    10  - "strings"
    11  - "time"
     4 + "crypto/tls"
     5 + "fmt"
     6 + "io/ioutil"
     7 + "net"
     8 + "net/http"
     9 + "strconv"
     10 + "strings"
     11 + "time"
    12 12   
    13  - "github.com/go-resty/resty/v2"
    14  - "github.com/sirupsen/logrus"
     13 + "github.com/go-resty/resty/v2"
     14 + "github.com/sirupsen/logrus"
    15 15  )
    16 16   
    17 17  var headers map[string]string
    18 18   
    19 19  // SendGET just send GET request
    20 20  func SendGET(url string, options Options) string {
    21  - headers = map[string]string{
    22  - "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36",
    23  - "Accept-Encoding": "*/*",
    24  - "Accept-Language": "en-US,en;q=0.8",
    25  - }
    26  - resp, _ := JustSend(options, "GET", url, headers, "")
    27  - return resp.Body
     21 + headers = map[string]string{
     22 + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36",
     23 + "Accept-Encoding": "*/*",
     24 + "Accept-Language": "en-US,en;q=0.8",
     25 + }
     26 + resp, _ := JustSend(options, "GET", url, headers, "")
     27 + return resp.Body
     28 +}
     29 + 
     30 +func GetResponse(baseUrl string, options Options) (string, error) {
     31 + content, err := getResponse(baseUrl, options)
     32 + // simple retry if something went wrong
     33 + for i := 0; i < options.Retry; i++ {
     34 + if err != nil {
     35 + content, err = getResponse(baseUrl, options)
     36 + } else {
     37 + return content, err
     38 + }
     39 + }
     40 + 
     41 + if err != nil {
     42 + content, err = getResponse(baseUrl, options)
     43 + }
     44 + return content, err
    28 45  }
    29 46   
    30  -func BigResponseReq(baseUrl string, options Options) string {
    31  - client := &http.Client{
    32  - Timeout: time.Duration(options.Timeout*3) * time.Second,
    33  - Transport: &http.Transport{
    34  - DialContext: (&net.Dialer{
    35  - Timeout: time.Second * 60,
    36  - }).DialContext,
    37  - MaxIdleConns: 1000,
    38  - MaxIdleConnsPerHost: 500,
    39  - MaxConnsPerHost: 500,
    40  - TLSClientConfig: &tls.Config{InsecureSkipVerify: true, Renegotiation: tls.RenegotiateOnceAsClient},
    41  - },
    42  - CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse },
    43  - }
     47 +func getResponse(baseUrl string, options Options) (string, error) {
     48 + client := &http.Client{
     49 + Timeout: time.Duration(options.Timeout*3) * time.Second,
     50 + Transport: &http.Transport{
     51 + DialContext: (&net.Dialer{
     52 + Timeout: time.Second * 60,
     53 + }).DialContext,
     54 + MaxIdleConns: 1000,
     55 + MaxIdleConnsPerHost: 500,
     56 + MaxConnsPerHost: 500,
     57 + TLSClientConfig: &tls.Config{InsecureSkipVerify: true, Renegotiation: tls.RenegotiateOnceAsClient},
     58 + },
     59 + CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse },
     60 + }
    44 61   
    45  - req, _ := http.NewRequest("GET", baseUrl, nil)
    46  - req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36")
    47  - resp, err := client.Do(req)
    48  - if err != nil {
    49  - ErrorF("%v", err)
    50  - return ""
    51  - }
    52  - defer resp.Body.Close()
     62 + req, _ := http.NewRequest("GET", baseUrl, nil)
     63 + req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36")
     64 + resp, err := client.Do(req)
     65 + if err != nil {
     66 + ErrorF("%v", err)
     67 + return "", err
     68 + }
     69 + defer resp.Body.Close()
    53 70   
    54  - content, err := ioutil.ReadAll(resp.Body)
    55  - if err != nil {
    56  - // do something with the error
    57  - ErrorF("%v", err)
    58  - return ""
    59  - }
    60  - return string(content)
     71 + content, err := ioutil.ReadAll(resp.Body)
     72 + if err != nil {
     73 + // do something with the error
     74 + ErrorF("%v", err)
     75 + return "", err
     76 + }
     77 + return string(content), nil
    61 78  }
    62 79   
    63 80  // SendPOST just send POST request
    64 81  func SendPOST(url string, options Options) string {
    65  - resp, _ := JustSend(options, "POST", url, headers, "")
    66  - return resp.Body
     82 + resp, _ := JustSend(options, "POST", url, headers, "")
     83 + return resp.Body
    67 84  }
    68 85   
    69 86  // JustSend just sending request
    70 87  func JustSend(options Options, method string, url string, headers map[string]string, body string) (res Response, err error) {
    71  - timeout := options.Timeout
     88 + timeout := options.Timeout
    72 89   
    73  - // disable log when retry
    74  - logger := logrus.New()
    75  - if !options.Debug {
    76  - logger.Out = ioutil.Discard
    77  - }
     90 + // disable log when retry
     91 + logger := logrus.New()
     92 + if !options.Debug {
     93 + logger.Out = ioutil.Discard
     94 + }
    78 95   
    79  - client := resty.New()
    80  - client.SetLogger(logger)
    81  - client.SetTransport(&http.Transport{
    82  - MaxIdleConns: 100,
    83  - MaxConnsPerHost: 1000,
    84  - IdleConnTimeout: time.Duration(timeout) * time.Second,
    85  - ExpectContinueTimeout: time.Duration(timeout) * time.Second,
    86  - ResponseHeaderTimeout: time.Duration(timeout) * time.Second,
    87  - TLSHandshakeTimeout: time.Duration(timeout) * time.Second,
    88  - DisableCompression: true,
    89  - TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    90  - })
     96 + client := resty.New()
     97 + client.SetLogger(logger)
     98 + client.SetTransport(&http.Transport{
     99 + MaxIdleConns: 100,
     100 + MaxConnsPerHost: 1000,
     101 + IdleConnTimeout: time.Duration(timeout) * time.Second,
     102 + ExpectContinueTimeout: time.Duration(timeout) * time.Second,
     103 + ResponseHeaderTimeout: time.Duration(timeout) * time.Second,
     104 + TLSHandshakeTimeout: time.Duration(timeout) * time.Second,
     105 + DisableCompression: true,
     106 + TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
     107 + })
    91 108   
    92  - client.SetHeaders(headers)
    93  - client.SetCloseConnection(true)
     109 + client.SetHeaders(headers)
     110 + client.SetCloseConnection(true)
    94 111   
    95  - client.SetTimeout(time.Duration(timeout) * time.Second)
    96  - client.SetRetryWaitTime(time.Duration(timeout/2) * time.Second)
    97  - client.SetRetryMaxWaitTime(time.Duration(timeout) * time.Second)
     112 + client.SetTimeout(time.Duration(timeout) * time.Second)
     113 + client.SetRetryWaitTime(time.Duration(timeout/2) * time.Second)
     114 + client.SetRetryMaxWaitTime(time.Duration(timeout) * time.Second)
    98 115   
    99  - if options.Proxy != "" {
    100  - client.SetProxy(options.Proxy)
    101  - }
     116 + if options.Proxy != "" {
     117 + client.SetProxy(options.Proxy)
     118 + }
    102 119   
    103  - var resp *resty.Response
    104  - // really sending things here
    105  - method = strings.ToLower(strings.TrimSpace(method))
    106  - switch method {
    107  - case "get":
    108  - resp, err = client.R().
    109  - Get(url)
    110  - break
    111  - case "post":
    112  - resp, err = client.R().
    113  - SetBody([]byte(body)).
    114  - Post(url)
    115  - break
    116  - }
     120 + var resp *resty.Response
     121 + // really sending things here
     122 + method = strings.ToLower(strings.TrimSpace(method))
     123 + switch method {
     124 + case "get":
     125 + resp, err = client.R().
     126 + Get(url)
     127 + break
     128 + case "post":
     129 + resp, err = client.R().
     130 + SetBody([]byte(body)).
     131 + Post(url)
     132 + break
     133 + }
    117 134   
    118  - // in case we want to get redirect stuff
    119  - if res.StatusCode != 0 {
    120  - return res, nil
    121  - }
     135 + // in case we want to get redirect stuff
     136 + if res.StatusCode != 0 {
     137 + return res, nil
     138 + }
    122 139   
    123  - if err != nil || resp == nil {
    124  - ErrorF("%v %v", url, err)
    125  - return res, err
    126  - }
     140 + if err != nil || resp == nil {
     141 + ErrorF("%v %v", url, err)
     142 + return res, err
     143 + }
    127 144   
    128  - return ParseResponse(*resp), nil
     145 + return ParseResponse(*resp), nil
    129 146  }
    130 147   
    131 148  // ParseResponse field to Response
    132 149  func ParseResponse(resp resty.Response) (res Response) {
    133  - // var res libs.Response
    134  - resLength := len(string(resp.Body()))
    135  - // format the headers
    136  - var resHeaders []map[string]string
    137  - for k, v := range resp.RawResponse.Header {
    138  - element := make(map[string]string)
    139  - element[k] = strings.Join(v[:], "")
    140  - resLength += len(fmt.Sprintf("%s: %s\n", k, strings.Join(v[:], "")))
    141  - resHeaders = append(resHeaders, element)
    142  - }
    143  - // response time in second
    144  - resTime := float64(resp.Time()) / float64(time.Second)
    145  - resHeaders = append(resHeaders,
    146  - map[string]string{"Total Length": strconv.Itoa(resLength)},
    147  - map[string]string{"Response Time": fmt.Sprintf("%f", resTime)},
    148  - )
     150 + // var res libs.Response
     151 + resLength := len(string(resp.Body()))
     152 + // format the headers
     153 + var resHeaders []map[string]string
     154 + for k, v := range resp.RawResponse.Header {
     155 + element := make(map[string]string)
     156 + element[k] = strings.Join(v[:], "")
     157 + resLength += len(fmt.Sprintf("%s: %s\n", k, strings.Join(v[:], "")))
     158 + resHeaders = append(resHeaders, element)
     159 + }
     160 + // response time in second
     161 + resTime := float64(resp.Time()) / float64(time.Second)
     162 + resHeaders = append(resHeaders,
     163 + map[string]string{"Total Length": strconv.Itoa(resLength)},
     164 + map[string]string{"Response Time": fmt.Sprintf("%f", resTime)},
     165 + )
    149 166   
    150  - // set some variable
    151  - res.Headers = resHeaders
    152  - res.StatusCode = resp.StatusCode()
    153  - res.Status = fmt.Sprintf("%v %v", resp.Status(), resp.RawResponse.Proto)
    154  - res.Body = string(resp.Body())
    155  - res.ResponseTime = resTime
    156  - res.Length = resLength
    157  - // beautify
    158  - res.Beautify = BeautifyResponse(res)
    159  - res.BeautifyHeader = BeautifyHeaders(res)
    160  - return res
     167 + // set some variable
     168 + res.Headers = resHeaders
     169 + res.StatusCode = resp.StatusCode()
     170 + res.Status = fmt.Sprintf("%v %v", resp.Status(), resp.RawResponse.Proto)
     171 + res.Body = string(resp.Body())
     172 + res.ResponseTime = resTime
     173 + res.Length = resLength
     174 + // beautify
     175 + res.Beautify = BeautifyResponse(res)
     176 + res.BeautifyHeader = BeautifyHeaders(res)
     177 + return res
    161 178  }
    162 179   
    163 180  // BeautifyHeaders beautify response headers
    164 181  func BeautifyHeaders(res Response) string {
    165  - beautifyHeader := fmt.Sprintf("%v \n", res.Status)
    166  - for _, header := range res.Headers {
    167  - for key, value := range header {
    168  - beautifyHeader += fmt.Sprintf("%v: %v\n", key, value)
    169  - }
    170  - }
    171  - return beautifyHeader
     182 + beautifyHeader := fmt.Sprintf("%v \n", res.Status)
     183 + for _, header := range res.Headers {
     184 + for key, value := range header {
     185 + beautifyHeader += fmt.Sprintf("%v: %v\n", key, value)
     186 + }
     187 + }
     188 + return beautifyHeader
    172 189  }
    173 190   
    174 191  // BeautifyResponse beautify response
    175 192  func BeautifyResponse(res Response) string {
    176  - var beautifyRes string
    177  - beautifyRes += fmt.Sprintf("%v \n", res.Status)
     193 + var beautifyRes string
     194 + beautifyRes += fmt.Sprintf("%v \n", res.Status)
    178 195   
    179  - for _, header := range res.Headers {
    180  - for key, value := range header {
    181  - beautifyRes += fmt.Sprintf("%v: %v\n", key, value)
    182  - }
    183  - }
     196 + for _, header := range res.Headers {
     197 + for key, value := range header {
     198 + beautifyRes += fmt.Sprintf("%v: %v\n", key, value)
     199 + }
     200 + }
    184 201   
    185  - beautifyRes += fmt.Sprintf("\n%v\n", res.Body)
    186  - return beautifyRes
     202 + beautifyRes += fmt.Sprintf("\n%v\n", res.Body)
     203 + return beautifyRes
    187 204  }
    188 205   
  • ■ ■ ■ ■ ■ ■
    core/version.go
    1 1  package core
    2 2   
     3 +import "fmt"
     4 + 
    3 5  const (
    4  - // VERSION current Metabigor version
    5  - VERSION = "beta v1.10"
    6  - // AUTHOR author of this
    7  - AUTHOR = "@j3ssiejjj"
     6 + // VERSION current version of this project
     7 + VERSION = "v1.2"
     8 + // AUTHOR of this project
     9 + AUTHOR = "@j3ssiejjj"
    8 10  )
    9 11   
     12 +var DESC = fmt.Sprintf(`Metabigor - Intelligence Tool but without API key - %v by %v`, VERSION, AUTHOR)
     13 + 
  • ■ ■ ■ ■ ■ ■
    go.mod
    1 1  module github.com/j3ssie/metabigor
    2 2   
    3  -go 1.16
     3 +go 1.17
    4 4   
    5 5  require (
    6  - github.com/PuerkitoBio/goquery v1.7.0
    7  - github.com/chromedp/chromedp v0.7.3
     6 + github.com/PuerkitoBio/goquery v1.8.0
     7 + github.com/chromedp/chromedp v0.8.1
    8 8   github.com/davecgh/go-spew v1.1.1
    9  - github.com/fatih/color v1.12.0
    10  - github.com/genkiroid/cert v0.0.0-20191007122723-897560fbbe50
    11  - github.com/go-resty/resty/v2 v2.6.0
    12  - github.com/json-iterator/go v1.1.11
     9 + github.com/fatih/color v1.13.0
     10 + github.com/go-resty/resty/v2 v2.7.0
     11 + github.com/json-iterator/go v1.1.12
    13 12   github.com/markbates/pkger v0.17.1
    14  - github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
    15 13   github.com/mitchellh/go-homedir v1.1.0
    16  - github.com/onsi/ginkgo v1.16.4 // indirect
    17  - github.com/onsi/gomega v1.13.0 // indirect
     14 + github.com/panjf2000/ants v1.3.0
     15 + github.com/projectdiscovery/mapcidr v0.0.9
    18 16   github.com/sirupsen/logrus v1.8.1
    19  - github.com/spf13/cast v1.3.1
    20  - github.com/spf13/cobra v1.1.3
    21  - github.com/thoas/go-funk v0.8.0
     17 + github.com/spf13/cast v1.5.0
     18 + github.com/spf13/cobra v1.4.0
     19 + github.com/thoas/go-funk v0.9.2
    22 20   github.com/x-cray/logrus-prefixed-formatter v0.5.2
    23  - go4.org/mem v0.0.0-20201119185036-c04c5a6ff174
    24  - inet.af/netaddr v0.0.0-20210603230628-bf05d8b52dda
     21 + go4.org/mem v0.0.0-20220409205537-d9185028b2dc
     22 + inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6
     23 +)
     24 + 
     25 +require (
     26 + github.com/andybalholm/cascadia v1.3.1 // indirect
     27 + github.com/chromedp/cdproto v0.0.0-20220428002153-285dfb42699c // indirect
     28 + github.com/chromedp/sysutil v1.0.0 // indirect
     29 + github.com/gobuffalo/here v0.6.0 // indirect
     30 + github.com/gobwas/httphead v0.1.0 // indirect
     31 + github.com/gobwas/pool v0.2.1 // indirect
     32 + github.com/gobwas/ws v1.1.0 // indirect
     33 + github.com/inconshreveable/mousetrap v1.0.0 // indirect
     34 + github.com/josharian/intern v1.0.0 // indirect
     35 + github.com/mailru/easyjson v0.7.7 // indirect
     36 + github.com/mattn/go-colorable v0.1.9 // indirect
     37 + github.com/mattn/go-isatty v0.0.14 // indirect
     38 + github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
     39 + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
     40 + github.com/modern-go/reflect2 v1.0.2 // indirect
     41 + github.com/onsi/ginkgo v1.7.0 // indirect
     42 + github.com/onsi/gomega v1.4.3 // indirect
     43 + github.com/projectdiscovery/blackrock v0.0.0-20210415162320-b38689ae3a2e // indirect
     44 + github.com/spf13/pflag v1.0.5 // indirect
     45 + github.com/stretchr/testify v1.7.0 // indirect
     46 + go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
     47 + go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37 // indirect
     48 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
     49 + golang.org/x/net v0.0.0-20211029224645-99673261e6eb // indirect
     50 + golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
     51 + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
    25 52  )
    26 53   
  • ■ ■ ■ ■ ■
    go.sum
    1  -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
    2  -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
    3  -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
    4  -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
    5  -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
    6  -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
    7  -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
    8  -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
    9  -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
    10  -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
    11  -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
    12  -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
    13  -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
    14  -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
    15  -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
    16  -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
    17  -github.com/PuerkitoBio/goquery v1.7.0 h1:O5SP3b9JWqMSVMG69zMfj577zwkSNpxrFf7ybS74eiw=
    18  -github.com/PuerkitoBio/goquery v1.7.0/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
    19  -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
    20  -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
    21  -github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
    22  -github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
    23  -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
    24  -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
    25  -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
    26  -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
    27  -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
    28  -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
    29  -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
    30  -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
    31  -github.com/chromedp/cdproto v0.0.0-20210526005521-9e51b9051fd0 h1:aIcgRshD5I1MfJfB92KBDKpaXrYqj3fkqI8bHdtP3zA=
    32  -github.com/chromedp/cdproto v0.0.0-20210526005521-9e51b9051fd0/go.mod h1:At5TxYYdxkbQL0TSefRjhLE3Q0lgvqKKMSFUglJ7i1U=
    33  -github.com/chromedp/chromedp v0.7.3 h1:FvgJICfjvXtDX+miuMUY0NHuY8zQvjS/TcEQEG6Ldzs=
    34  -github.com/chromedp/chromedp v0.7.3/go.mod h1:9gC521Yzgrk078Ulv6KIgG7hJ2x9aWrxMBBobTFk30A=
     1 +github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
     2 +github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
     3 +github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
     4 +github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
     5 +github.com/chromedp/cdproto v0.0.0-20220428002153-285dfb42699c h1:9VfguIWKAk161/xCyWLV23cJQmL3pDXKJHUSySQxT3s=
     6 +github.com/chromedp/cdproto v0.0.0-20220428002153-285dfb42699c/go.mod h1:5Y4sD/eXpwrChIuxhSr/G20n9CdbCmoerOHnuAf0Zr0=
     7 +github.com/chromedp/chromedp v0.8.1 h1:tZT0PNV9War7z6y3TS15NgBsP3J0AJcVRjABmdaBCmc=
     8 +github.com/chromedp/chromedp v0.8.1/go.mod h1:qGzgSh6g5c2HYHwK5UMEA+1LIV/EKheZNALSDBcg4ag=
    35 9  github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
    36 10  github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
    37  -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
    38  -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
    39  -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
    40  -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
    41  -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
    42  -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
    43  -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
     11 +github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4=
     12 +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
     13 +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
    44 14  github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
    45 15  github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
    46 16  github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
    47  -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
    48  -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
    49 17  github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
    50  -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
    51  -github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
    52  -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
     18 +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
     19 +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
     20 +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
     21 +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
    53 22  github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
    54  -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
    55  -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
    56  -github.com/genkiroid/cert v0.0.0-20191007122723-897560fbbe50 h1:vLwmYBduhnWWqShoUGbVgDulhcLdanoYtCQxYMzwaqQ=
    57  -github.com/genkiroid/cert v0.0.0-20191007122723-897560fbbe50/go.mod h1:Pb7nyGYAfDyE/IkU6AJeRshIFko0wJC9cOqeYzYQffk=
    58  -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
    59  -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
    60  -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
    61  -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
    62  -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
    63  -github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKYS4=
    64  -github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q=
    65  -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
    66  -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
     23 +github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
     24 +github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
    67 25  github.com/gobuffalo/here v0.6.0 h1:hYrd0a6gDmWxBM4TnrGw8mQg24iSVoIkHEk7FodQcBI=
    68 26  github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
    69 27  github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
    70 28  github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
    71 29  github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
    72 30  github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
    73  -github.com/gobwas/ws v1.1.0-rc.5 h1:QOAag7FoBaBYYHRqzqkhhd8fq5RTubvI4v3Ft/gDVVQ=
    74  -github.com/gobwas/ws v1.1.0-rc.5/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
    75  -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
    76  -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
    77  -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
    78  -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
    79  -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
    80  -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
    81  -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
     31 +github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
     32 +github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
    82 33  github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
    83  -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
    84  -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
    85  -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
    86  -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
    87  -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
    88  -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
    89  -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
    90  -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
    91  -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
    92  -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
    93  -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
    94  -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
    95  -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
    96  -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
    97  -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
    98  -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
    99  -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
     34 +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
     35 +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
     36 +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
     37 +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
    100 38  github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
    101  -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
    102  -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
    103  -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
    104  -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
    105  -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
    106  -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
    107  -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
    108  -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
    109  -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
    110  -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
    111  -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
    112  -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
    113  -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
    114  -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
    115  -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
    116  -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
    117  -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
    118  -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
    119  -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
    120  -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
    121  -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
    122  -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
    123  -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
    124  -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
    125  -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
    126  -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
    127  -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
    128  -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
    129  -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
    130  -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
    131  -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
     39 +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
    132 40  github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
    133 41  github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
    134 42  github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
    135  -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
    136 43  github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
    137 44  github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
    138  -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
    139  -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
     45 +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
    140 46  github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
    141  -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
    142  -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
    143  -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
    144  -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
    145  -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
    146  -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
    147  -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
     47 +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
     48 +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
    148 49  github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
     50 +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
     51 +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
     52 +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
    149 53  github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
    150 54  github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
    151  -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
     55 +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
     56 +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
     57 +github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
     58 +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
    152 59  github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
    153 60  github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
    154 61  github.com/markbates/pkger v0.17.1 h1:/MKEtWqtc0mZvu9OinB9UzVN9iYCwLWuyUv4Bw+PCno=
    155 62  github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
    156  -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
    157  -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
    158  -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
    159  -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
    160  -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
     63 +github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
     64 +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
    161 65  github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
    162  -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
     66 +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
     67 +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
    163 68  github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
    164 69  github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
    165  -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
    166  -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
    167  -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
    168 70  github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
    169 71  github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
    170  -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
    171  -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
    172  -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
    173  -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
    174  -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
    175 72  github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
    176 73  github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
    177 74  github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
    178 75  github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
    179  -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
    180 76  github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
    181  -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
    182  -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
    183  -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
    184  -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
    185  -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
     77 +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
     78 +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
    186 79  github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
    187  -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
    188  -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
    189  -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
    190  -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
    191  -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
    192  -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
    193  -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
    194  -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
    195  -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
    196  -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
    197  -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
    198  -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
     80 +github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
     81 +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
     82 +github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
     83 +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
     84 +github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5 h1:1SoBaSPudixRecmlHXb/GxmaD3fLMtHIDN13QujwQuc=
     85 +github.com/orisano/pixelmatch v0.0.0-20210112091706-4fa4c7ba91d5/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
     86 +github.com/panjf2000/ants v1.3.0 h1:8pQ+8leaLc9lys2viEEr8md0U4RN6uOSUCE9bOYjQ9M=
     87 +github.com/panjf2000/ants v1.3.0/go.mod h1:AaACblRPzq35m1g3enqYcxspbbiOJJYaxU2wMpm1cXY=
     88 +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
    199 89  github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
    200 90  github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
    201  -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
    202  -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
    203  -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
    204  -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
    205  -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
    206  -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
    207  -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
    208  -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
    209  -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
    210  -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
    211  -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
    212  -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
    213  -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
    214  -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
    215  -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
    216  -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
    217  -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
     91 +github.com/projectdiscovery/blackrock v0.0.0-20210415162320-b38689ae3a2e h1:7bwaFH1jvtOo5ndhTQgoA349ozhX+1dc4b6tbaPnBOA=
     92 +github.com/projectdiscovery/blackrock v0.0.0-20210415162320-b38689ae3a2e/go.mod h1:/IsapnEYiWG+yEDPXp0e8NWj3npzB9Ccy9lXEUJwMZs=
     93 +github.com/projectdiscovery/goflags v0.0.7/go.mod h1:Jjwsf4eEBPXDSQI2Y+6fd3dBumJv/J1U0nmpM+hy2YY=
     94 +github.com/projectdiscovery/gologger v1.0.1/go.mod h1:Ok+axMqK53bWNwDSU1nTNwITLYMXMdZtRc8/y1c7sWE=
     95 +github.com/projectdiscovery/gologger v1.1.4/go.mod h1:Bhb6Bdx2PV1nMaFLoXNBmHIU85iROS9y1tBuv7T5pMY=
     96 +github.com/projectdiscovery/hmap v0.0.1/go.mod h1:VDEfgzkKQdq7iGTKz8Ooul0NuYHQ8qiDs6r8bPD1Sb0=
     97 +github.com/projectdiscovery/ipranger v0.0.2/go.mod h1:kcAIk/lo5rW+IzUrFkeYyXnFJ+dKwYooEOHGVPP/RWE=
     98 +github.com/projectdiscovery/mapcidr v0.0.4/go.mod h1:ALOIj6ptkWujNoX8RdQwB2mZ+kAmKuLJBq9T5gR5wG0=
     99 +github.com/projectdiscovery/mapcidr v0.0.9 h1:PIa09fMHdghlmkUeTgHP9bwYnb3k2wXXM2f6LMj26zg=
     100 +github.com/projectdiscovery/mapcidr v0.0.9/go.mod h1:zgsrc+UXwcLcBopUNboiI4tpTICbfdTyJZiBi2tx+NI=
     101 +github.com/projectdiscovery/stringsutil v0.0.0-20210804142656-fd3c28dbaafe/go.mod h1:oTRc18WBv9t6BpaN9XBY+QmG28PUpsyDzRht56Qf49I=
     102 +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
     103 +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
     104 +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
    218 105  github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
    219 106  github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
    220  -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
    221  -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
    222  -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
    223  -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
    224  -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
    225  -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
    226  -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
    227  -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
    228  -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
    229  -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
    230  -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
    231  -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
     107 +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
     108 +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
     109 +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
     110 +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
    232 111  github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
    233 112  github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
    234  -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
    235 113  github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
    236  -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
    237 114  github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
    238 115  github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
    239 116  github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
    240  -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
    241 117  github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
    242  -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
    243  -github.com/thoas/go-funk v0.8.0 h1:JP9tKSvnpFVclYgDM0Is7FD9M4fhPvqA0s0BsXmzSRQ=
    244  -github.com/thoas/go-funk v0.8.0/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
    245  -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
     118 +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
     119 +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
     120 +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
     121 +github.com/thoas/go-funk v0.9.2 h1:oKlNYv0AY5nyf9g+/GhMgS/UO2ces0QRdPKwkhY3VCk=
     122 +github.com/thoas/go-funk v0.9.2/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
    246 123  github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
    247 124  github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
    248  -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
     125 +github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
    249 126  github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
    250  -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
    251  -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
    252  -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
    253  -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
    254  -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
    255  -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
    256  -go4.org/intern v0.0.0-20210108033219-3eb7198706b2 h1:VFTf+jjIgsldaz/Mr00VaCSswHJrI2hIjQygE/W4IMg=
    257  -go4.org/intern v0.0.0-20210108033219-3eb7198706b2/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
    258  -go4.org/mem v0.0.0-20201119185036-c04c5a6ff174 h1:vSug/WNOi2+4jrKdivxayTN/zd8EA1UrStjpWvvo1jk=
    259  -go4.org/mem v0.0.0-20201119185036-c04c5a6ff174/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
    260  -go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
    261  -go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 h1:1tk03FUNpulq2cuWpXZWj649rwJpk0d20rxWiopKRmc=
    262  -go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
    263  -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
    264  -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
     127 +go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=
     128 +go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA=
     129 +go4.org/mem v0.0.0-20220409205537-d9185028b2dc h1:4dJN4Zx/OR6xg5DQZ5rpd2plCsL7Y9aSY0+qJoaIuG4=
     130 +go4.org/mem v0.0.0-20220409205537-d9185028b2dc/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
     131 +go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37 h1:Tx9kY6yUkLge/pFG7IEMwDZy6CS2ajFc9TvQdPCW0uA=
     132 +go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
    265 133  golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
    266  -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
    267  -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
    268 134  golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
    269 135  golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
    270 136  golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
    271  -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
    272  -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
    273  -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
    274  -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
    275  -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
    276  -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
    277  -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
    278  -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
    279  -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
    280  -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
    281  -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
    282  -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
    283  -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
    284  -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
    285  -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
    286  -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
    287  -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
    288  -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
    289 137  golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
    290  -golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    291  -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    292  -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    293 138  golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    294  -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    295  -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    296  -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    297  -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    298  -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    299  -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    300  -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
    301 139  golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
    302  -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
    303  -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
    304  -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
    305 140  golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    306  -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    307  -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
    308 141  golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
    309  -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
    310  -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
    311  -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
    312  -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
    313  -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
    314  -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
     142 +golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
     143 +golang.org/x/net v0.0.0-20211029224645-99673261e6eb h1:pirldcYWx7rx7kE5r+9WsOXPXK0+WH5+uZ7uPmJ44uM=
     144 +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
    315 145  golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    316  -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    317  -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    318  -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    319 146  golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    320 147  golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    321  -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    322  -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    323  -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    324 148  golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    325  -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    326  -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    327  -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    328 149  golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    329  -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    330 150  golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    331  -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    332  -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    333  -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    334  -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    335  -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    336  -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    337 151  golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    338  -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    339 152  golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    340 153  golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    341  -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    342 154  golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    343 155  golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    344 156  golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    345  -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    346 157  golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    347  -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    348 158  golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    349  -golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea h1:+WiDlPBBaO+h9vPNZi8uJ3k4BkKQB7Iow3aqwHVA5hI=
    350  -golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
     159 +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
     160 +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
     161 +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    351 162  golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
    352 163  golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
    353  -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
    354  -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
    355 164  golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
    356 165  golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
    357 166  golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
    358  -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
    359  -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
    360  -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
    361 167  golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
    362  -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
    363  -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
    364  -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
    365  -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
    366  -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
    367  -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
    368  -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
    369  -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
    370  -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
    371  -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
    372  -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
    373  -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    374  -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    375  -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    376  -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    377 168  golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    378  -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
    379 169  golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
    380 170  golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    381 171  golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    382 172  golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
     173 +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
    383 174  golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    384  -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
    385  -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
    386  -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
    387  -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
    388  -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
    389  -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
    390  -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
    391  -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
    392  -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
    393  -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
    394  -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
    395  -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
    396  -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
    397  -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
    398  -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
    399  -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
    400  -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
    401  -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
    402  -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
    403  -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
    404  -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
    405  -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
    406  -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
    407  -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
    408  -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
    409  -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
    410  -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
    411  -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
    412  -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
    413  -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
    414 175  gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
    415 176  gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
     177 +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
    416 178  gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
     179 +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
    417 180  gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
    418  -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
    419  -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
    420 181  gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
    421 182  gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
    422  -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
    423 183  gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
    424 184  gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
    425  -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
    426 185  gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
    427  -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
    428 186  gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
    429 187  gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
    430  -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
    431  -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
    432  -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
    433  -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
    434  -inet.af/netaddr v0.0.0-20210603230628-bf05d8b52dda h1:N1UNOTFyoz00Zw10uv9elxer4zdyqqhsMOOqAFPVTfM=
    435  -inet.af/netaddr v0.0.0-20210603230628-bf05d8b52dda/go.mod h1:z0nx+Dh+7N7CC8V5ayHtHGpZpxLQZZxkIaaz6HN65Ls=
    436  -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
     188 +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
     189 +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
     190 +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
     191 +inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 h1:acCzuUSQ79tGsM/O50VRFySfMm19IoMKL+sZztZkCxw=
     192 +inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6/go.mod h1:y3MGhcFMlh0KZPMuXXow8mpjxxAk3yoDNsp4cQz54i8=
    437 193   
  • ■ ■ ■ ■
    main.go
    skipped 2 lines
    3 3  import "github.com/j3ssie/metabigor/cmd"
    4 4   
    5 5  func main() {
    6  - cmd.Execute()
     6 + cmd.Execute()
    7 7  }
    8 8   
  • ■ ■ ■ ■ ■ ■
    modules/asn.go
    1 1  package modules
    2 2   
    3 3  import (
    4  - "bufio"
    5  - "bytes"
    6  - "compress/gzip"
    7  - "fmt"
    8  - "github.com/markbates/pkger"
    9  - "go4.org/mem"
    10  - "inet.af/netaddr"
    11  - "io"
    12  - "math/big"
    13  - "net"
    14  - "sort"
    15  - "strconv"
    16  - "strings"
     4 + "bufio"
     5 + "bytes"
     6 + "compress/gzip"
     7 + "fmt"
     8 + "github.com/markbates/pkger"
     9 + "go4.org/mem"
     10 + "inet.af/netaddr"
     11 + "io"
     12 + "math/big"
     13 + "net"
     14 + "sort"
     15 + "strconv"
     16 + "strings"
    17 17  )
    18 18   
    19 19  // Most of file literally copied from @thebl4ckturtle code
    20 20   
    21 21  type ASInfo struct {
    22  - Amount int
    23  - Number int
    24  - CountryCode string
    25  - Description string
    26  - CIDR string
     22 + Amount int
     23 + Number int
     24 + CountryCode string
     25 + Description string
     26 + CIDR string
    27 27  }
    28 28   
    29 29  func GetAsnMap() (AsnMap, error) {
    30  - //var asnAsnMap AsnMap
    31  - f, err := pkger.Open("/static/ip2asn-combined.tsv.gz")
    32  - if err != nil {
    33  - return AsnMap{}, err
    34  - }
    35  - asnAsnMap, err := GenAsnData(f)
    36  - if err != nil {
    37  - return AsnMap{}, err
    38  - }
    39  - return *asnAsnMap, nil
     30 + //var asnAsnMap AsnMap
     31 + f, err := pkger.Open("/static/ip2asn-combined.tsv.gz")
     32 + if err != nil {
     33 + return AsnMap{}, err
     34 + }
     35 + asnAsnMap, err := GenAsnData(f)
     36 + if err != nil {
     37 + return AsnMap{}, err
     38 + }
     39 + return *asnAsnMap, nil
    40 40  }
    41 41   
    42 42  type IPInfo struct {
    43  - AS int
    44  - CIDR string
     43 + AS int
     44 + CIDR string
    45 45  }
    46 46   
    47 47  type AsnMap struct {
    48  - asName map[int]string
    49  - asCountry map[int]string
    50  - asDesc map[string]int
    51  - recs []rec
     48 + asName map[int]string
     49 + asCountry map[int]string
     50 + asDesc map[string]int
     51 + recs []rec
    52 52  }
    53 53   
    54 54  type rec struct {
    55  - startIP, endIP netaddr.IP
    56  - asn int
     55 + startIP, endIP netaddr.IP
     56 + asn int
    57 57  }
    58 58   
    59 59  func (m *AsnMap) ASName(as int) string { return m.asName[as] }
    60 60  func (m *AsnMap) ASCountry(as int) string { return m.asCountry[as] }
    61 61  func (m *AsnMap) ASDesc(name string) (AsnNum []int) {
    62  - name = strings.ToLower(name)
    63  - for k, v := range m.asDesc {
    64  - if strings.Contains(strings.ToLower(k), name) {
    65  - AsnNum = append(AsnNum, v)
    66  - }
    67  - }
    68  - return AsnNum
     62 + name = strings.ToLower(name)
     63 + for k, v := range m.asDesc {
     64 + if strings.Contains(strings.ToLower(k), name) {
     65 + AsnNum = append(AsnNum, v)
     66 + }
     67 + }
     68 + return AsnNum
    69 69  }
    70 70   
    71 71  // ASInfo returns 0 on unknown.
    72 72  func (m *AsnMap) ASInfo(asnNum int) []ASInfo {
    73  - var asnInfos []ASInfo
    74  - if asnNum == 0 {
    75  - return asnInfos
    76  - }
     73 + var asnInfos []ASInfo
     74 + if asnNum == 0 {
     75 + return asnInfos
     76 + }
    77 77   
    78  - for _, rec := range m.recs {
    79  - if rec.asn == asnNum {
    80  - var asnInfo ASInfo
    81  - as := IPInfo{AS: rec.asn, CIDR: Range2CIDR(net.ParseIP(rec.startIP.String()), net.ParseIP(rec.endIP.String())).String()}
    82  - asnInfo.Number = asnNum
    83  - asnInfo.CIDR = as.CIDR
    84  - asnInfo.CountryCode = m.ASCountry(asnNum)
    85  - asnInfo.Description = m.ASName(asnNum)
    86  - asnInfos = append(asnInfos, asnInfo)
    87  - }
    88  - }
    89  - return asnInfos
     78 + for _, rec := range m.recs {
     79 + if rec.asn == asnNum {
     80 + var asnInfo ASInfo
     81 + as := IPInfo{AS: rec.asn, CIDR: Range2CIDR(net.ParseIP(rec.startIP.String()), net.ParseIP(rec.endIP.String())).String()}
     82 + asnInfo.Number = asnNum
     83 + asnInfo.CIDR = as.CIDR
     84 + asnInfo.CountryCode = m.ASCountry(asnNum)
     85 + asnInfo.Description = m.ASName(asnNum)
     86 + asnInfos = append(asnInfos, asnInfo)
     87 + }
     88 + }
     89 + return asnInfos
    90 90  }
    91 91   
    92 92  // ASofIP returns 0 on unknown.
    93 93  func (m *AsnMap) ASofIP(ip netaddr.IP) IPInfo {
    94  - cand := sort.Search(len(m.recs), func(i int) bool {
    95  - return ip.Less(m.recs[i].startIP)
    96  - })
    97  - return m.recIndexHasIP(cand-1, ip)
     94 + cand := sort.Search(len(m.recs), func(i int) bool {
     95 + return ip.Less(m.recs[i].startIP)
     96 + })
     97 + return m.recIndexHasIP(cand-1, ip)
    98 98  }
    99 99   
    100 100  // recIndexHasIP returns the AS number of m.rec[i] if i is in range and
    101 101  // the record contains the given IP address.
    102 102  func (m *AsnMap) recIndexHasIP(i int, ip netaddr.IP) (as IPInfo) {
    103  - if i < 0 {
    104  - return IPInfo{AS: 0}
    105  - }
    106  - rec := &m.recs[i]
    107  - if rec.endIP.Less(ip) {
    108  - return IPInfo{AS: 0}
    109  - }
    110  - if ip.Less(rec.startIP) {
    111  - return IPInfo{AS: 0}
    112  - }
    113  - return IPInfo{AS: rec.asn, CIDR: Range2CIDR(net.ParseIP(rec.startIP.String()), net.ParseIP(rec.endIP.String())).String()}
     103 + if i < 0 {
     104 + return IPInfo{AS: 0}
     105 + }
     106 + rec := &m.recs[i]
     107 + if rec.endIP.Less(ip) {
     108 + return IPInfo{AS: 0}
     109 + }
     110 + if ip.Less(rec.startIP) {
     111 + return IPInfo{AS: 0}
     112 + }
     113 + return IPInfo{AS: rec.asn, CIDR: Range2CIDR(net.ParseIP(rec.startIP.String()), net.ParseIP(rec.endIP.String())).String()}
    114 114  }
    115 115   
    116 116  func GenAsnData(r io.Reader) (*AsnMap, error) {
    117  - br := bufio.NewReader(r)
    118  - magic, err := br.Peek(2)
    119  - if err != nil {
    120  - return nil, err
    121  - }
    122  - if string(magic) == "\x1f\x8b" {
    123  - zr, err := gzip.NewReader(br)
    124  - if err != nil {
    125  - return nil, err
    126  - }
    127  - br = bufio.NewReader(zr)
    128  - }
    129  - m := &AsnMap{
    130  - asName: map[int]string{},
    131  - asCountry: map[int]string{},
    132  - asDesc: map[string]int{},
    133  - }
    134  - for {
    135  - line, err := br.ReadSlice('\n')
    136  - if err == io.EOF {
    137  - return m, nil
    138  - }
    139  - if err != nil {
    140  - return nil, err
    141  - }
    142  - var startIPB, endIPB, asnB, country, desc []byte
    143  - if err := parseTSV(line, &startIPB, &endIPB, &asnB, &country, &desc); err != nil {
    144  - return nil, err
    145  - }
    146  - if string(desc) == "Not routed" {
    147  - continue
    148  - }
    149  - as64, err := mem.ParseInt(mem.B(asnB), 10, 64)
    150  - if err != nil {
    151  - return nil, fmt.Errorf("bogus ASN %q for line %q", asnB, line)
    152  - }
    153  - as := int(as64)
    154  - if _, ok := m.asName[as]; !ok {
    155  - m.asName[as] = string(desc)
    156  - m.asCountry[as] = string(country)
    157  - m.asDesc[string(desc)] = as
    158  - }
     117 + br := bufio.NewReader(r)
     118 + magic, err := br.Peek(2)
     119 + if err != nil {
     120 + return nil, err
     121 + }
     122 + if string(magic) == "\x1f\x8b" {
     123 + zr, err := gzip.NewReader(br)
     124 + if err != nil {
     125 + return nil, err
     126 + }
     127 + br = bufio.NewReader(zr)
     128 + }
     129 + m := &AsnMap{
     130 + asName: map[int]string{},
     131 + asCountry: map[int]string{},
     132 + asDesc: map[string]int{},
     133 + }
     134 + for {
     135 + line, err := br.ReadSlice('\n')
     136 + if err == io.EOF {
     137 + return m, nil
     138 + }
     139 + if err != nil {
     140 + return nil, err
     141 + }
     142 + var startIPB, endIPB, asnB, country, desc []byte
     143 + if err := parseTSV(line, &startIPB, &endIPB, &asnB, &country, &desc); err != nil {
     144 + return nil, err
     145 + }
     146 + if string(desc) == "Not routed" {
     147 + continue
     148 + }
     149 + as64, err := mem.ParseInt(mem.B(asnB), 10, 64)
     150 + if err != nil {
     151 + return nil, fmt.Errorf("bogus ASN %q for line %q", asnB, line)
     152 + }
     153 + as := int(as64)
     154 + if _, ok := m.asName[as]; !ok {
     155 + m.asName[as] = string(desc)
     156 + m.asCountry[as] = string(country)
     157 + m.asDesc[string(desc)] = as
     158 + }
    159 159   
    160  - startIP, err := netaddr.ParseIP(string(startIPB)) // TODO: add ParseIPBytes
    161  - if err != nil {
    162  - return nil, fmt.Errorf("bogus IP %q for line %q", startIPB, line)
    163  - }
    164  - endIP, err := netaddr.ParseIP(string(endIPB)) // TODO: add ParseIPBytes
    165  - if err != nil {
    166  - return nil, fmt.Errorf("bogus IP %q for line %q", endIPB, line)
    167  - }
    168  - m.recs = append(m.recs, rec{startIP, endIP, as})
    169  - }
     160 + startIP, err := netaddr.ParseIP(string(startIPB)) // TODO: add ParseIPBytes
     161 + if err != nil {
     162 + return nil, fmt.Errorf("bogus IP %q for line %q", startIPB, line)
     163 + }
     164 + endIP, err := netaddr.ParseIP(string(endIPB)) // TODO: add ParseIPBytes
     165 + if err != nil {
     166 + return nil, fmt.Errorf("bogus IP %q for line %q", endIPB, line)
     167 + }
     168 + m.recs = append(m.recs, rec{startIP, endIP, as})
     169 + }
    170 170  }
    171 171   
    172 172  func parseTSV(line []byte, dsts ...*[]byte) error {
    173  - if len(line) > 0 && line[len(line)-1] == '\n' {
    174  - line = line[:len(line)-1]
    175  - }
    176  - for i, dst := range dsts {
    177  - last := i == len(dsts)-1
    178  - tab := bytes.IndexByte(line, '\t')
    179  - if tab == -1 && !last {
    180  - return fmt.Errorf("short line: %q", line)
    181  - }
    182  - if tab != -1 {
    183  - *dst, line = line[:tab], line[tab+1:]
    184  - } else {
    185  - *dst = line
    186  - }
    187  - }
    188  - return nil
     173 + if len(line) > 0 && line[len(line)-1] == '\n' {
     174 + line = line[:len(line)-1]
     175 + }
     176 + for i, dst := range dsts {
     177 + last := i == len(dsts)-1
     178 + tab := bytes.IndexByte(line, '\t')
     179 + if tab == -1 && !last {
     180 + return fmt.Errorf("short line: %q", line)
     181 + }
     182 + if tab != -1 {
     183 + *dst, line = line[:tab], line[tab+1:]
     184 + } else {
     185 + *dst = line
     186 + }
     187 + }
     188 + return nil
    189 189  }
    190 190   
    191 191  // Range2CIDR turns an IP range into a CIDR.
    192 192  func Range2CIDR(first, last net.IP) *net.IPNet {
    193  - startip, m := ipToInt(first)
    194  - endip, _ := ipToInt(last)
    195  - newip := big.NewInt(1)
    196  - mask := big.NewInt(1)
    197  - one := big.NewInt(1)
     193 + startip, m := ipToInt(first)
     194 + endip, _ := ipToInt(last)
     195 + newip := big.NewInt(1)
     196 + mask := big.NewInt(1)
     197 + one := big.NewInt(1)
    198 198   
    199  - if startip.Cmp(endip) == 1 {
    200  - return nil
    201  - }
     199 + if startip.Cmp(endip) == 1 {
     200 + return nil
     201 + }
    202 202   
    203  - max := uint(m)
    204  - var bits uint = 1
    205  - newip.Set(startip)
    206  - tmp := new(big.Int)
    207  - for bits < max {
    208  - tmp.Rsh(startip, bits)
    209  - tmp.Lsh(tmp, bits)
     203 + max := uint(m)
     204 + var bits uint = 1
     205 + newip.Set(startip)
     206 + tmp := new(big.Int)
     207 + for bits < max {
     208 + tmp.Rsh(startip, bits)
     209 + tmp.Lsh(tmp, bits)
    210 210   
    211  - newip.Or(startip, mask)
    212  - if newip.Cmp(endip) == 1 || tmp.Cmp(startip) != 0 {
    213  - bits--
    214  - mask.Rsh(mask, 1)
    215  - break
    216  - }
     211 + newip.Or(startip, mask)
     212 + if newip.Cmp(endip) == 1 || tmp.Cmp(startip) != 0 {
     213 + bits--
     214 + mask.Rsh(mask, 1)
     215 + break
     216 + }
    217 217   
    218  - bits++
    219  - tmp.Lsh(mask, 1)
    220  - mask.Add(tmp, one)
    221  - }
     218 + bits++
     219 + tmp.Lsh(mask, 1)
     220 + mask.Add(tmp, one)
     221 + }
    222 222   
    223  - cidrstr := first.String() + "/" + strconv.Itoa(int(max-bits))
    224  - _, ipnet, _ := net.ParseCIDR(cidrstr)
     223 + cidrstr := first.String() + "/" + strconv.Itoa(int(max-bits))
     224 + _, ipnet, _ := net.ParseCIDR(cidrstr)
    225 225   
    226  - return ipnet
     226 + return ipnet
    227 227  }
    228 228   
    229 229  func ipToInt(ip net.IP) (*big.Int, int) {
    230  - val := big.NewInt(1)
     230 + val := big.NewInt(1)
    231 231   
    232  - val.SetBytes([]byte(ip))
    233  - if IsIPv4(ip) {
    234  - return val, 32
    235  - } else if IsIPv6(ip) {
    236  - return val, 128
    237  - }
     232 + val.SetBytes([]byte(ip))
     233 + if IsIPv4(ip) {
     234 + return val, 32
     235 + } else if IsIPv6(ip) {
     236 + return val, 128
     237 + }
    238 238   
    239  - return val, 0
     239 + return val, 0
    240 240  }
    241 241   
    242 242  // IsIPv4 returns true when the provided net.IP address is an IPv4 address.
    243 243  func IsIPv4(ip net.IP) bool {
    244  - return strings.Count(ip.String(), ":") < 2
     244 + return strings.Count(ip.String(), ":") < 2
    245 245  }
    246 246   
    247 247  // IsIPv6 returns true when the provided net.IP address is an IPv6 address.
    248 248  func IsIPv6(ip net.IP) bool {
    249  - return strings.Count(ip.String(), ":") >= 2
     249 + return strings.Count(ip.String(), ":") >= 2
    250 250  }
    251 251   
  • ■ ■ ■ ■ ■ ■
    modules/asn_test.go
    1 1  package modules
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "github.com/davecgh/go-spew/spew"
    6  - "inet.af/netaddr"
    7  - "testing"
     4 + "fmt"
     5 + "github.com/davecgh/go-spew/spew"
     6 + "inet.af/netaddr"
     7 + "testing"
    8 8  )
    9 9   
    10 10  func TestGetLocalAsn(t *testing.T) {
    11  - asnAsnMap, err := GetAsnMap()
    12  - var asns []ASInfo
     11 + asnAsnMap, err := GetAsnMap()
     12 + var asns []ASInfo
    13 13   
    14  - ip, err := netaddr.ParseIP("8.8.8.8")
    15  - if err != nil {
    16  - return
    17  - }
     14 + ip, err := netaddr.ParseIP("8.8.8.8")
     15 + if err != nil {
     16 + return
     17 + }
    18 18   
    19  - if asn := asnAsnMap.ASofIP(ip); asn.AS != 0 {
    20  - asnNum := asn.AS
    21  - asInfo := asnAsnMap.ASInfo(asnNum)
    22  - spew.Dump(asInfo)
    23  - }
     19 + if asn := asnAsnMap.ASofIP(ip); asn.AS != 0 {
     20 + asnNum := asn.AS
     21 + asInfo := asnAsnMap.ASInfo(asnNum)
     22 + spew.Dump(asInfo)
     23 + }
    24 24   
    25  - asnN := asnAsnMap.ASInfo(18144)
    26  - spew.Dump(asnN)
     25 + asnN := asnAsnMap.ASInfo(18144)
     26 + spew.Dump(asnN)
    27 27   
    28  - asnd := asnAsnMap.ASDesc("Google")
    29  - spew.Dump(asnd)
     28 + asnd := asnAsnMap.ASDesc("Google")
     29 + spew.Dump(asnd)
    30 30   
    31  - fmt.Println("------------")
    32  - spew.Dump(asns)
     31 + fmt.Println("------------")
     32 + spew.Dump(asns)
    33 33   
    34 34  }
    35 35   
  • ■ ■ ■ ■ ■ ■
    modules/cert.go
    1 1  package modules
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "github.com/PuerkitoBio/goquery"
    6  - "github.com/j3ssie/metabigor/core"
    7  - jsoniter "github.com/json-iterator/go"
    8  - "github.com/thoas/go-funk"
    9  - "net/url"
    10  - "strings"
     4 + "fmt"
     5 + "github.com/PuerkitoBio/goquery"
     6 + "github.com/j3ssie/metabigor/core"
     7 + jsoniter "github.com/json-iterator/go"
     8 + "github.com/thoas/go-funk"
     9 + "net/url"
     10 + "strings"
    11 11  )
    12 12   
    13 13  // CrtSHOrg get IPInfo from https://crt.sh
    14 14  func CrtSHOrg(org string, options core.Options) []string {
    15  - crtURL := fmt.Sprintf(`https://crt.sh/?O=%v`, url.QueryEscape(org))
    16  - var result []string
    17  - core.InforF("Get data from: %v", crtURL)
    18  - content := core.BigResponseReq(crtURL, options)
    19  - if content == "" {
    20  - core.ErrorF("Error sending request to: %v", crtURL)
    21  - return result
    22  - }
     15 + crtURL := fmt.Sprintf(`https://crt.sh/?O=%v`, url.QueryEscape(org))
     16 + var result []string
     17 + core.InforF("Get data from: %v", crtURL)
     18 + content, err := core.GetResponse(crtURL, options)
     19 + // simple retry if something went wrong
     20 + if err != nil {
     21 + content, err = core.GetResponse(crtURL, options)
     22 + }
     23 + if content == "" {
     24 + core.ErrorF("Error sending request to: %v", crtURL)
     25 + return result
     26 + }
     27 + 
     28 + infos := ParseCertSH(content, options)
     29 + for _, info := range infos {
     30 + var data string
     31 + if options.JsonOutput {
     32 + if options.JsonOutput {
     33 + if data, err := jsoniter.MarshalToString(info); err == nil {
     34 + result = append(result, data)
     35 + 
     36 + if !options.Quiet {
     37 + fmt.Println(data)
     38 + }
     39 + 
     40 + }
     41 + continue
     42 + }
     43 + }
    23 44   
    24  - infos := ParseCertSH(content, options)
    25  - for _, info := range infos {
    26  - var data string
    27  - if options.JsonOutput {
    28  - if options.JsonOutput {
    29  - if data, err := jsoniter.MarshalToString(info); err == nil {
    30  - result = append(result, data)
    31  - fmt.Println(data)
    32  - }
    33  - continue
    34  - }
    35  - }
     45 + if options.Verbose {
     46 + data = fmt.Sprintf("%s ;; %s ;; %s", info.Domain, info.Org, info.CertInfo)
     47 + } else {
     48 + data = info.Domain
     49 + }
     50 + result = append(result, data)
     51 + }
     52 + result = funk.UniqString(result)
    36 53   
    37  - if options.Verbose {
    38  - data = fmt.Sprintf("%s ;; %s ;; %s", info.Domain, info.Org, info.CertInfo)
    39  - } else {
    40  - data = info.Domain
    41  - }
    42  - result = append(result, data)
    43  - }
    44  - result = funk.UniqString(result)
    45  - fmt.Println(strings.Join(result, "\n"))
    46  - return result
     54 + if !options.Quiet {
     55 + fmt.Println(strings.Join(result, "\n"))
     56 + }
     57 + return result
    47 58  }
    48 59   
    49 60  type CertData struct {
    50  - Domain string
    51  - CertInfo string
    52  - Org string
     61 + Domain string
     62 + CertInfo string
     63 + Org string
     64 + WildCard bool
    53 65  }
    54 66   
    55 67  func ParseCertSH(content string, options core.Options) []CertData {
    56  - var results []CertData
    57  - doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
    58  - if err != nil {
    59  - core.ErrorF("Error parsing body: %v", err)
     68 + var results []CertData
     69 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
     70 + if err != nil {
     71 + core.ErrorF("Error parsing body: %v", err)
     72 + return results
     73 + }
    60 74   
    61  - return results
    62  - }
    63  - 
    64  - doc.Find("tr").Each(func(i int, s *goquery.Selection) {
    65  - var certInfo CertData
    66  - s.Find("td").Each(func(j int, td *goquery.Selection) {
    67  - if j == 4 {
    68  - certInfo.Domain = strings.TrimSpace(td.Text())
    69  - }
    70  - if j == 5 {
    71  - certInfo.Org = strings.TrimSpace(td.Text())
    72  - }
    73  - if j == 6 {
    74  - certInfo.CertInfo = strings.TrimSpace(td.Text())
    75  - }
    76  - })
    77  - // remove some noise
    78  - if strings.Contains(certInfo.Domain, ".") && !strings.Contains(certInfo.Domain, " ") {
    79  - if options.Cert.Clean {
    80  - certInfo.Domain = strings.ReplaceAll(certInfo.Domain, "*.", "")
    81  - results = append(results, certInfo)
    82  - } else if options.Cert.OnlyWildCard {
    83  - if strings.Contains(certInfo.Domain, "*") {
    84  - results = append(results, certInfo)
    85  - }
    86  - } else {
    87  - results = append(results, certInfo)
    88  - }
    89  - }
     75 + doc.Find("tr").Each(func(i int, s *goquery.Selection) {
     76 + var certInfo CertData
     77 + s.Find("td").Each(func(j int, td *goquery.Selection) {
     78 + if j == 4 {
     79 + certInfo.Domain = strings.TrimSpace(td.Text())
     80 + }
     81 + if j == 5 {
     82 + certInfo.Org = strings.TrimSpace(td.Text())
     83 + }
     84 + if j == 6 {
     85 + certInfo.CertInfo = strings.TrimSpace(td.Text())
     86 + }
     87 + })
     88 + // remove some noise
     89 + if strings.Contains(certInfo.Domain, ".") && !strings.Contains(certInfo.Domain, " ") {
     90 + if options.Cert.Clean {
     91 + certInfo.Domain = strings.ReplaceAll(certInfo.Domain, "*.", "")
     92 + results = append(results, certInfo)
     93 + } else if options.Cert.OnlyWildCard {
     94 + if strings.Contains(certInfo.Domain, "*") {
     95 + certInfo.WildCard = true
     96 + results = append(results, certInfo)
     97 + }
     98 + } else {
     99 + results = append(results, certInfo)
     100 + }
     101 + }
    90 102   
    91  - })
     103 + })
    92 104   
    93  - return results
     105 + return results
    94 106  }
    95 107   
  • ■ ■ ■ ■ ■ ■
    modules/cert_test.go
    1 1  package modules
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "github.com/j3ssie/metabigor/core"
    6  - "testing"
     4 + "fmt"
     5 + "github.com/j3ssie/metabigor/core"
     6 + "testing"
    7 7  )
    8 8   
    9 9  func TestParseCertSH(t *testing.T) {
    10  - var options core.Options
    11  - raw := core.GetFileContent("/tmp/tll")
    12  - result := ParseCertSH(raw, options)
    13  - fmt.Println(result)
    14  - if len(result) == 0 {
    15  - t.Errorf("Error TestParseCertSH")
    16  - }
     10 + var options core.Options
     11 + raw := core.GetFileContent("/tmp/tll")
     12 + result := ParseCertSH(raw, options)
     13 + fmt.Println(result)
     14 + if len(result) == 0 {
     15 + t.Errorf("Error TestParseCertSH")
     16 + }
    17 17  }
    18 18   
  • ■ ■ ■ ■ ■ ■
    modules/cve.go
    1  -package modules
    2  - 
    3  -import (
    4  - "github.com/j3ssie/metabigor/core"
    5  - "strings"
    6  -)
    7  - 
    8  -/*
    9  -@TODO: more source to add
    10  -https://snyk.io/vuln/
    11  -https://www.tenable.com/plugins/nessus/
    12  -https://github.com/advisories
    13  -https://packetstormsecurity.com/files/tags/exploit/
    14  -*/
    15  - 
    16  -type CVEData struct {
    17  - CVE string
    18  - Title string
    19  - Desc string
    20  - Raw string
    21  - RawQuery string
    22  -}
    23  - 
    24  -// Vulners get Org CIDR from asnlookup
    25  -func Vulners(options core.Options) []string {
    26  - var result []string
    27  - 
    28  - ///// @NOTE: Disable for lack of usage
    29  - 
    30  - //
    31  - //query := options.Search.Query
    32  - //// parsing input
    33  - //software, version := PrepareQuery(query)
    34  - //body := fmt.Sprintf(`{"apiKey":"","software":"%s","type":"software","version":"%s"}`, software, version)
    35  - //
    36  - //url := fmt.Sprintf(`https://vulners.com/api/v3/burp/software/`)
    37  - //core.InforF("Get data from: %v", url)
    38  - //headers := map[string]string{
    39  - // "UserAgent": "vulners-burpscanner-v-1.2",
    40  - // "Content-type": "application/json",
    41  - //}
    42  - //resp, _ := core.JustSend(options, "POST", url, headers, body)
    43  - //if resp.StatusCode != 200 {
    44  - // return result
    45  - //}
    46  - //jsonParsed, err := gabs.ParseJSON([]byte(resp.Body))
    47  - //if err != nil {
    48  - // core.ErrorF("Error parse JSON Data")
    49  - // return result
    50  - //}
    51  - //
    52  - //content := jsonParsed.S("data").S("search")
    53  - ////contents, _ := content.ChildrenMap()
    54  - //for _, item := range content.ChildrenMap() {
    55  - // var cveData CVEData
    56  - // cveData.RawQuery = query
    57  - // for k, v := range item.S("_source").ChildrenMap() {
    58  - // if k == "description" {
    59  - // cveData.Desc = v.Data().(string)
    60  - // }
    61  - // if k == "title" {
    62  - // cveData.Title = v.Data().(string)
    63  - // }
    64  - // if k == "id" {
    65  - // cveData.CVE = v.Data().(string)
    66  - // }
    67  - // }
    68  - //
    69  - // if options.JsonOutput {
    70  - // if data, err := jsoniter.MarshalToString(cveData); err == nil {
    71  - // result = append(result, data)
    72  - // }
    73  - // continue
    74  - // }
    75  - // info := fmt.Sprintf("%s ;; %s ;; %s", cveData.RawQuery, cveData.CVE, cveData.Desc)
    76  - // result = append(result, info)
    77  - //}
    78  - 
    79  - return result
    80  -}
    81  - 
    82  -func PrepareQuery(raw string) (string, string) {
    83  - raw = strings.ToLower(strings.TrimSpace(raw))
    84  - if !strings.Contains(raw, "|") {
    85  - return raw, "0"
    86  - }
    87  - 
    88  - // apache|1.0
    89  - data := strings.Split(raw, "|")
    90  - software := strings.TrimSpace(data[0])
    91  - version := strings.TrimSpace(data[1])
    92  - return software, version
    93  -}
    94  - 
  • ■ ■ ■ ■ ■ ■
    modules/ga.go
     1 +package modules
     2 + 
     3 +import (
     4 + "fmt"
     5 + "regexp"
     6 + "strings"
     7 +)
     8 + 
     9 +func ExtractUAID(content string) (results []string) {
     10 + regex := regexp.MustCompile(`UA-[0-9]+-[0-9]+`)
     11 + ua := regex.FindAllStringSubmatch(content, -1)
     12 + for _, id := range ua {
     13 + results = append(results, id[0])
     14 + }
     15 + 
     16 + return results
     17 +}
     18 + 
     19 +func ExtractGoogleTagManger(content string) (results []string) {
     20 + // regex 1
     21 + regex := regexp.MustCompile(`www\.googletagmanager\.com/ns\.html\?id=[A-Z0-9\-]+`)
     22 + data := regex.FindStringSubmatch(content)
     23 + fmt.Println(data)
     24 + 
     25 + if len(data) > 0 {
     26 + gtm := strings.Split(data[0], "id=")[1]
     27 + results = append(results, fmt.Sprintf("https://www.googletagmanager.com/gtm.js?id=%s", gtm))
     28 + return results
     29 + }
     30 + 
     31 + // regex 2
     32 + regex = regexp.MustCompile("GTM-[A-Z0-9]+")
     33 + data = regex.FindStringSubmatch(content)
     34 + if len(data) > 0 {
     35 + results = append(results, fmt.Sprintf("https://www.googletagmanager.com/gtm.js?id=%s", data[0]))
     36 + return results
     37 + }
     38 + 
     39 + // regex 3
     40 + //regex = regexp.MustCompile(`UA-\d+-\d+`)
     41 + //ua := regex.FindAllStringSubmatch(content, -1)
     42 + //for _, id := range ua {
     43 + // results = append(results, id[0])
     44 + //}
     45 + 
     46 + fmt.Println("ExtractGoogleTagManger: ", results)
     47 + return results
     48 +}
     49 + 
  • ■ ■ ■ ■ ■
    modules/ip.go
    1 1  package modules
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "github.com/PuerkitoBio/goquery"
    6  - "github.com/genkiroid/cert"
    7  - "github.com/j3ssie/metabigor/core"
    8  - "strings"
     4 + "crypto/tls"
     5 + "fmt"
     6 + "github.com/j3ssie/metabigor/core"
     7 + "io/ioutil"
     8 + "net/http"
     9 + "os"
    9 10  )
    10 11   
    11  -// Onyphe get IPInfo from https://www.onyphe.io
    12  -func Onyphe(query string, options core.Options) []string {
    13  - url := fmt.Sprintf(`https://www.onyphe.io/search/?query=%v`, query)
    14  - var result []string
    15  - core.InforF("Get data from: %v", url)
    16  - content := core.SendGET(url, options)
    17  - if content == "" {
    18  - return result
    19  - }
    20  - info := ParseOnyphe(content)
    21  - if !options.Verbose {
    22  - result = append(result, fmt.Sprintf("[onyphe] %v ports|%v", query, info["ports"]))
    23  - return result
    24  - }
    25  - for key, value := range info {
    26  - if key != "port" {
    27  - result = append(result, fmt.Sprintf("[onyphe] %v %v|%v", query, key, value))
    28  - }
    29  - }
    30  - cert := CertsInfo(query, info["ports"])
    31  - if cert != "" {
    32  - result = append(result, cert)
    33  - }
    34  - return result
    35  -}
    36  - 
    37  -// Shodan get IPInfo from https://www.shodan.io
    38  -func Shodan(query string, options core.Options) []string {
    39  - url := fmt.Sprintf(`https://www.shodan.io/host/%v`, query)
    40  - var result []string
    41  - core.InforF("Get data from: %v", url)
    42  - content := core.SendGET(url, options)
    43  - if content == "" {
    44  - core.DebugF("Error in sending to Shodan")
    45  - return result
    46  - }
    47  - info := ParseShodan(content)
    48  - if !options.Verbose {
    49  - result = append(result, fmt.Sprintf("[shodan] %v ports|%v", query, info["ports"]))
    50  - return result
    51  - }
    52  - for key, value := range info {
    53  - if key != "port" {
    54  - result = append(result, fmt.Sprintf("[shodan] %v %v|%v", query, key, value))
    55  - }
    56  - }
    57  - cert := CertsInfo(query, info["ports"])
    58  - if cert != "" {
    59  - result = append(result, cert)
    60  - }
    61  - return result
     12 +var tr = &http.Transport{
     13 + TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    62 14  }
    63  - 
    64  -// ParseOnyphe parsing data from Onyphe
    65  -func ParseOnyphe(content string) map[string]string {
    66  - info := make(map[string]string)
    67  - 
    68  - doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
    69  - if err != nil {
    70  - core.DebugF("Error parsing HTML")
    71  - return info
    72  - }
    73  - 
    74  - // searching for data
    75  - doc.Find(".features-list").Each(func(i int, s *goquery.Selection) {
    76  - text := s.Text()
    77  - // basic info part
    78  - if strings.Contains(text, "geoloc") {
    79  - s.Find("tr").Each(func(i int, tr *goquery.Selection) {
    80  - text := tr.Text()
    81  - if strings.Contains(text, "organization") {
    82  - organization := strings.Replace(text, "organization", "", -1)
    83  - info["organization"] = organization
    84  - }
    85  - 
    86  - if strings.Contains(text, "asn") {
    87  - asn := strings.Replace(text, "asn", "", -1)
    88  - info["asn"] = asn
    89  - }
    90  - 
    91  - if strings.Contains(text, "subnet") {
    92  - subnet := strings.Replace(text, "subnet", "", -1)
    93  - info["subnet"] = subnet
    94  - }
    95  - 
    96  - if strings.Contains(text, "city") {
    97  - city := strings.Replace(text, "city", "", -1)
    98  - info["city"] = city
    99  - }
    100  - 
    101  - if strings.Contains(text, "country") {
    102  - country := strings.Replace(text, "country", "", -1)
    103  - info["country"] = country
    104  - }
    105  - })
    106  - }
     15 +var client = &http.Client{Transport: tr}
    107 16   
    108  - // open port
    109  - if strings.Contains(text, "synscan") {
    110  - var ports []string
    111  - s.Find("a").Each(func(i int, tag *goquery.Selection) {
    112  - href, _ := tag.Attr("href")
    113  - if strings.Contains(href, "port") {
    114  - port := tag.Text()
    115  - ports = append(ports, port)
    116  - }
    117  - })
    118  - info["ports"] = strings.Join(ports, ",")
    119  - }
    120  - })
    121  - return info
    122  -}
    123  - 
    124  -// ParseShodan parsing data from Onyphe
    125  -func ParseShodan(content string) map[string]string {
    126  - info := make(map[string]string)
    127  - doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
    128  - if err != nil {
    129  - core.DebugF("Error parsing HTML")
    130  - return info
    131  - }
    132  - 
    133  - // searching for data
    134  - doc.Find(".table").Each(func(i int, s *goquery.Selection) {
    135  - text := s.Text()
    136  - // basic info part
    137  - if strings.Contains(text, "Country") {
    138  - s.Find("tr").Each(func(i int, tr *goquery.Selection) {
    139  - text := tr.Text()
    140  - if strings.Contains(text, "Organization") {
    141  - organization := strings.Replace(text, "Organization", "", -1)
    142  - info["organization"] = strings.TrimSpace(organization)
    143  - }
    144  - 
    145  - if strings.Contains(text, "ASN") {
    146  - asn := strings.Replace(text, "ASN", "", -1)
    147  - info["asn"] = strings.TrimSpace(asn)
    148  - }
    149  - 
    150  - if strings.Contains(text, "ISP") {
    151  - ISP := strings.Replace(text, "ISP", "", -1)
    152  - info["isp"] = strings.TrimSpace(ISP)
    153  - }
    154  - 
    155  - if strings.Contains(text, "Hostnames") {
    156  - hostnames := strings.Replace(text, "Hostnames", "", -1)
    157  - info["hostnames"] = strings.TrimSpace(hostnames)
    158  - }
    159  - 
    160  - if strings.Contains(text, "Country") {
    161  - country := strings.Replace(text, "Country", "", -1)
    162  - info["country"] = strings.TrimSpace(country)
    163  - }
    164  - })
    165  - }
    166  - })
    167  - 
    168  - // ports part
    169  - var ports []string
    170  - doc.Find(".services .service-long").Each(func(i int, s *goquery.Selection) {
    171  - port := strings.Replace(strings.TrimSpace(s.Find(".service-details").Text()), "\n", "/", -1)
    172  - port = strings.Replace(port, "///", "", -1)
    173  - if port != "" {
    174  - ports = append(ports, port)
    175  - }
    176  - })
    177  - //fmt.Println(ports)
    178  - info["ports"] = strings.Join(ports, ",")
    179  - return info
    180  -}
    181  - 
    182  -// SecurityTrails get IPInfo from https://securitytrails.com/list/ip/196.3.50.77
    183  -func SecurityTrails(query string, options core.Options) []string {
    184  - url := fmt.Sprintf(`https://securitytrails.com/list/ip/%v`, query)
    185  - var result []string
    186  - core.InforF("Get data from: %v", url)
    187  - content := core.RequestWithChrome(url, "root", options.Timeout)
    188  - if content == "" {
    189  - core.DebugF("Error in sending to SecurityTrails")
    190  - return result
    191  - }
    192  - datas := ParseSecurityTrails(content)
    193  - for key, value := range datas {
    194  - result = append(result, fmt.Sprintf("[securitytrails] %v %v|%v", query, key, value))
    195  - }
    196  - return result
    197  -}
    198  - 
    199  -// ParseSecurityTrails parsing data from Onyphe
    200  -func ParseSecurityTrails(content string) []map[string]string {
    201  - var result []map[string]string
    202  - doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
    203  - if err != nil {
    204  - core.DebugF("Error parsing HTML")
    205  - return result
    206  - }
    207  - 
    208  - // searching for data
    209  - doc.Find("table").Each(func(i int, s *goquery.Selection) {
    210  - info := make(map[string]string)
    211  - //text := s.Text()
    212  - // basic info part
    213  - s.Find("tr").Each(func(i int, tr *goquery.Selection) {
    214  - text := tr.Text()
    215  - if len(text) > 2 && !strings.Contains(text, "www") && !strings.Contains(text, "apex_domain") {
    216  - info["data"] = text[1:]
    217  - return
    218  - }
    219  - 
    220  - })
    221  - result = append(result, info)
    222  - })
    223  - 
    224  - return result
    225  -}
    226  - 
    227  -// CertsInfo get cert info
    228  -func CertsInfo(query string, rports string) string {
    229  - var certs cert.Certs
    230  - var err error
    231  - var domains []string
    232  - cert.SkipVerify = true
    233  - ports := strings.Split(rports, ",")
    234  - 
    235  - for _, port := range ports {
    236  - if strings.Contains(port, "/") {
    237  - port = strings.Split(port, "/")[0]
    238  - }
    239  - raw := fmt.Sprintf("%v:%v", query, port)
    240  - core.DebugF("SSL Info: %v", raw)
    241  - certs, err = cert.NewCerts([]string{raw})
    242  - if err != nil {
    243  - continue
    244  - }
    245  - for _, certItem := range certs {
    246  - for _, domain := range certItem.SANs {
    247  - domains = append(domains, domain)
    248  - }
    249  - }
    250  - }
    251  - if len(domains) == 0 {
    252  - return ""
    253  - }
    254  - return fmt.Sprintf("[Cert] %v %v", query, strings.Join(domains, ","))
     17 +func InternetDB(IP string) string {
     18 + ipURL := fmt.Sprintf("https://internetdb.shodan.io/%s", IP)
     19 + core.DebugF("Getting information from: %s", ipURL)
     20 + resp, err := client.Get(ipURL)
     21 + if err != nil {
     22 + fmt.Fprintf(os.Stderr, "%v", err)
     23 + return ""
     24 + }
     25 + defer resp.Body.Close()
     26 + body, err := ioutil.ReadAll(resp.Body)
     27 + if err != nil {
     28 + fmt.Fprintf(os.Stderr, "%v", err)
     29 + return ""
     30 + }
     31 + return string(body)
    255 32  }
    256 33   
  • ■ ■ ■ ■ ■ ■
    modules/ip_test.go
    1 1  package modules
    2 2   
    3 3  import (
    4  - "fmt"
    5  - "github.com/j3ssie/metabigor/core"
    6  - "testing"
     4 + "fmt"
     5 + "github.com/j3ssie/metabigor/core"
     6 + "testing"
    7 7  )
    8 8   
    9 9  func TestParseOnyphe(t *testing.T) {
    10  - var options core.Options
    11  - options.Verbose = true
    12  - raw := core.GetFileContent("/tmp/testttt/ony.html")
    13  - result := ParseOnyphe(raw)
    14  - fmt.Println(result)
    15  - if len(result) == 0 {
    16  - t.Errorf("Error parseOnyphe")
    17  - }
     10 + var options core.Options
     11 + options.Verbose = true
     12 + raw := core.GetFileContent("/tmp/testttt/ony.html")
     13 + result := ParseOnyphe(raw)
     14 + fmt.Println(result)
     15 + if len(result) == 0 {
     16 + t.Errorf("Error parseOnyphe")
     17 + }
    18 18  }
    19 19   
    20 20  func TestParseShodan(t *testing.T) {
    21  - var options core.Options
    22  - options.Verbose = true
    23  - raw := core.GetFileContent("/tmp/testttt/shodan.html")
    24  - result := ParseShodan(raw)
    25  - fmt.Println(result)
    26  - if len(result) == 0 {
    27  - t.Errorf("Error parseOnyphe")
    28  - }
     21 + var options core.Options
     22 + options.Verbose = true
     23 + raw := core.GetFileContent("/tmp/testttt/shodan.html")
     24 + result := ParseShodan(raw)
     25 + fmt.Println(result)
     26 + if len(result) == 0 {
     27 + t.Errorf("Error parseOnyphe")
     28 + }
    29 29  }
    30 30   
Please wait...
Page is in error, reload to recover