Projects STRLCPY metabigor Commits 30c092f2
🤬
  • Rewrite the tool in Go

  • Loading...
  • j3ssie committed 4 years ago
    30c092f2
  • ■ ■ ■ ■ ■ ■
    .gitignore
     1 +.DS_STORE
     2 +.goreleaser.yml
     3 +dist
     4 +out*
  • ■ ■ ■ ■ ■ ■
    LICENSE
     1 +MIT License
     2 + 
     3 +Copyright (c) 2019 j3ssie
     4 + 
     5 +Permission is hereby granted, free of charge, to any person obtaining a copy
     6 +of this software and associated documentation files (the "Software"), to deal
     7 +in the Software without restriction, including without limitation the rights
     8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     9 +copies of the Software, and to permit persons to whom the Software is
     10 +furnished to do so, subject to the following conditions:
     11 + 
     12 +The above copyright notice and this permission notice shall be included in all
     13 +copies or substantial portions of the Software.
     14 + 
     15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21 +SOFTWARE.
     22 + 
     23 + 
  • ■ ■ ■ ■ ■ ■
    README.md
     1 +<p align="center">
     2 + <img alt="Metabigor" src="https://image.flaticon.com/icons/svg/2303/2303030.svg" height="140" />
     3 + <p align="center">Intelligence Framework but without API key</p>
     4 + <p align="center">
     5 + <a href="https://github.com/j3ssie/metabigor"><img alt="Release" src="https://img.shields.io/badge/version-1.0-red.svg"></a>
     6 + <a href=""><img alt="Software License" src="https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square"></a>
     7 + </p>
     8 +</p>
     9 + 
     10 +## What is Metabigor?
     11 +Metabigor is Intelligence Framework, its goal is to do OSINT tasks and more but without any API key.
     12 + 
     13 + 
     14 +## Installation
     15 + 
     16 +```
     17 +go get -u https://github.com/j3ssie/metabigor
     18 +```
     19 + 
     20 + 
     21 +### Example Commands
     22 + 
     23 +```
     24 +# discovery IP of ASN
     25 +echo "company" | metabigor net --org -o /tmp/result.txt
     26 + 
     27 +# discovery IP of ASN
     28 +echo "ASN1111" | metabigor net --asn -o /tmp/result.txt
     29 +cat list_of_ASNs | metabigor net --asn -o /tmp/result.txt
     30 + 
     31 +# running masscan on port 443
     32 +echo "1.2.3.4/24" | metabigor scan -p 443 -o /tmp/result.txt
     33 + 
     34 +# running masscan on port all port and nmap on open port
     35 +cat list_of_IPs | metabigor scan --detail -o /tmp/result.txt
     36 +```
     37 + 
     38 +## Credits
     39 + 
     40 +Logo from [flaticon](https://www.flaticon.com/free-icon/metabolism_1774457) by [freepik
     41 +](https://www.flaticon.com/authors/freepik)
     42 + 
     43 +## Disclaimer
     44 + 
     45 +This tool is for educational purposes only. You are responsible for your own actions. If you mess something up or break any laws while using this software, it's your fault, and your fault only.
     46 + 
     47 +## License
     48 + 
     49 +`Metabigor` is made with ♥ by [@j3ssiejjj](https://twitter.com/j3ssiejjj) and it is released under the MIT license.
     50 + 
  • ■ ■ ■ ■ ■ ■
    cmd/net.go
     1 +package cmd
     2 + 
     3 +import (
     4 + "fmt"
     5 + "strings"
     6 + "sync"
     7 + 
     8 + "github.com/j3ssie/metabigor/core"
     9 + "github.com/j3ssie/metabigor/modules"
     10 + "github.com/spf13/cobra"
     11 + "github.com/thoas/go-funk"
     12 +)
     13 + 
     14 +var netCmd *cobra.Command
     15 + 
     16 +func init() {
     17 + // byeCmd represents the bye command
     18 + var netCmd = &cobra.Command{
     19 + Use: "net",
     20 + Short: "Discover Network Inforamtion about targets",
     21 + Long: fmt.Sprintf(`Metabigor - Intelligence Framework but without API key - %v by %v`, core.VERSION, core.AUTHOR),
     22 + RunE: runNet,
     23 + }
     24 + 
     25 + netCmd.Flags().Bool("asn", false, "Take input as ASN")
     26 + netCmd.Flags().Bool("org", false, "Take input as Organization")
     27 + RootCmd.AddCommand(netCmd)
     28 +}
     29 + 
     30 +func runNet(cmd *cobra.Command, args []string) error {
     31 + asn, _ := cmd.Flags().GetBool("asn")
     32 + org, _ := cmd.Flags().GetBool("org")
     33 + var inputs []string
     34 + 
     35 + if strings.Contains(options.Input, "\n") {
     36 + inputs = strings.Split(options.Input, "\n")
     37 + } else {
     38 + inputs = append(inputs, options.Input)
     39 + }
     40 + 
     41 + var wg sync.WaitGroup
     42 + jobs := make(chan string)
     43 + 
     44 + for i := 0; i < options.Concurrency; i++ {
     45 + wg.Add(1)
     46 + go func() {
     47 + defer wg.Done()
     48 + // do real stuff here
     49 + for job := range jobs {
     50 + var osintResult []string
     51 + if asn {
     52 + osintResult = runASN(job, options)
     53 + } else if org {
     54 + osintResult = runOrg(job, options)
     55 + }
     56 + StoreData(osintResult, options)
     57 + }
     58 + }()
     59 + }
     60 + 
     61 + for _, input := range inputs {
     62 + jobs <- input
     63 + }
     64 + 
     65 + close(jobs)
     66 + wg.Wait()
     67 + 
     68 + if !core.FileExists(options.Output) {
     69 + core.ErrorF("No data found")
     70 + }
     71 + return nil
     72 +}
     73 + 
     74 +func runASN(input string, options core.Options) []string {
     75 + core.BannerF("Starting get IP Info from ASN: ", input)
     76 + options.Net.Asn = input
     77 + var data []string
     78 + var wg sync.WaitGroup
     79 + wg.Add(1)
     80 + go func() {
     81 + data = append(data, modules.ASNBgpDotNet(options)...)
     82 + wg.Done()
     83 + }()
     84 + 
     85 + wg.Add(1)
     86 + go func() {
     87 + data = append(data, modules.IPInfo(options)...)
     88 + wg.Done()
     89 + }()
     90 + 
     91 + // wg.Add(1)
     92 + // go func() {
     93 + // data = append(data, modules.ASNSpyse(options)...)
     94 + // wg.Done()
     95 + // }()
     96 + 
     97 + wg.Wait()
     98 + return data
     99 +}
     100 + 
     101 +func runOrg(input string, options core.Options) []string {
     102 + core.BannerF("Starting get IP Info for Organization: ", input)
     103 + options.Net.Org = input
     104 + var data []string
     105 + var wg sync.WaitGroup
     106 + wg.Add(1)
     107 + go func() {
     108 + data = append(data, modules.OrgBgpDotNet(options)...)
     109 + wg.Done()
     110 + }()
     111 + wg.Add(1)
     112 + go func() {
     113 + data = append(data, modules.ASNLookup(options)...)
     114 + wg.Done()
     115 + }()
     116 + wg.Wait()
     117 + 
     118 + var cidrs []string
     119 + // get more IP by result ASN
     120 + for _, item := range data {
     121 + // get more range from ASN
     122 + if strings.HasPrefix(strings.ToLower(item), "as") {
     123 + wg.Add(1)
     124 + go func(item string) {
     125 + cidrs = append(cidrs, runASN(item, options)...)
     126 + wg.Done()
     127 + }(item)
     128 + continue
     129 + } else if core.StartWithNum(item) {
     130 + cidrs = append(cidrs, item)
     131 + }
     132 + }
     133 + wg.Wait()
     134 + return funk.Uniq(cidrs).([]string)
     135 +}
     136 + 
     137 +// StoreData store data to output
     138 +func StoreData(data []string, options core.Options) {
     139 + if len(data) > 0 {
     140 + fmt.Println(strings.Join(data, "\n"))
     141 + _, err := core.AppendToContent(options.Output, strings.Join(data, "\n"))
     142 + if err == nil {
     143 + core.InforF("Write output to: %v", options.Output)
     144 + }
     145 + }
     146 +}
     147 + 
  • ■ ■ ■ ■ ■ ■
    cmd/root.go
     1 +package cmd
     2 + 
     3 +import (
     4 + "bufio"
     5 + "fmt"
     6 + "os"
     7 + "strings"
     8 + 
     9 + "github.com/j3ssie/metabigor/core"
     10 + "github.com/spf13/cobra"
     11 +)
     12 + 
     13 +var options = core.Options{}
     14 +var config struct {
     15 + defaultSign string
     16 + secretCollab string
     17 + port string
     18 +}
     19 + 
     20 +// RootCmd represents the base command when called without any subcommands
     21 +var RootCmd = &cobra.Command{
     22 + Use: "metabigor",
     23 + Short: "Metabigor",
     24 + Long: fmt.Sprintf(`Metabigor - Intelligence Framework but without API key - %v by %v`, core.VERSION, core.AUTHOR),
     25 +}
     26 + 
     27 +// Execute main function
     28 +func Execute() {
     29 + if err := RootCmd.Execute(); err != nil {
     30 + fmt.Println(err)
     31 + os.Exit(1)
     32 + }
     33 +}
     34 + 
     35 +func init() {
     36 + cobra.OnInitialize(initConfig)
     37 + RootCmd.PersistentFlags().StringVar(&options.ConfigFile, "configFile", "~/.metabigor/config.yaml", "root Project")
     38 + RootCmd.PersistentFlags().StringVar(&options.Scan.TmpOutput, "tmp", "", "Temp Output folder")
     39 + RootCmd.PersistentFlags().StringVar(&options.Proxy, "proxy", "", "Proxy for doing request")
     40 + RootCmd.PersistentFlags().IntVarP(&options.Concurrency, "concurrency", "c", 3, "concurrency")
     41 + RootCmd.PersistentFlags().IntVar(&options.Timeout, "timeout", 10, "timeout")
     42 + RootCmd.PersistentFlags().StringVarP(&options.Input, "input", "i", "-", "input as a string, file or from stdin")
     43 + RootCmd.PersistentFlags().StringVarP(&options.Output, "output", "o", "out.txt", "output name")
     44 + RootCmd.PersistentFlags().BoolVar(&options.Debug, "debug", false, "Debug")
     45 + RootCmd.PersistentFlags().BoolVarP(&options.Verbose, "verbose", "v", false, "Verbose")
     46 +}
     47 + 
     48 +// initConfig reads in config file and ENV variables if set.
     49 +func initConfig() {
     50 + if options.Debug {
     51 + options.Verbose = true
     52 + }
     53 + if options.Verbose {
     54 + core.InforF("Metabigor %v by %v\n", core.VERSION, core.AUTHOR)
     55 + }
     56 + core.InitLog(options)
     57 + // planned feature
     58 + // if !core.FileExists(options.ConfigFile) {
     59 + // core.InitConfig(options)
     60 + // }
     61 + if options.Scan.TmpOutput != "" && !core.FolderExists(options.Scan.TmpOutput) {
     62 + core.InforF("Create new temp folder: %v", options.Scan.TmpOutput)
     63 + os.MkdirAll(options.Scan.TmpOutput, 0750)
     64 + }
     65 + 
     66 + // got input from stdin
     67 + if options.Input == "-" {
     68 + stat, _ := os.Stdin.Stat()
     69 + if (stat.Mode() & os.ModeCharDevice) == 0 {
     70 + var data []string
     71 + sc := bufio.NewScanner(os.Stdin)
     72 + for sc.Scan() {
     73 + data = append(data, sc.Text())
     74 + }
     75 + options.Input = strings.Join(data, "\n")
     76 + }
     77 + } else {
     78 + // get input from a file or just a string
     79 + if core.FileExists(options.Input) {
     80 + options.Input = core.GetFileContent(options.Input)
     81 + }
     82 + }
     83 + 
     84 + if options.Input == "-" || options.Input == "" {
     85 + core.ErrorF("No input found")
     86 + os.Exit(1)
     87 + }
     88 + 
     89 +}
     90 + 
  • ■ ■ ■ ■ ■ ■
    cmd/scan.go
     1 +package cmd
     2 + 
     3 +import (
     4 + "fmt"
     5 + "strings"
     6 + "sync"
     7 + 
     8 + "github.com/j3ssie/metabigor/core"
     9 + "github.com/j3ssie/metabigor/modules"
     10 + "github.com/spf13/cobra"
     11 +)
     12 + 
     13 +var scanCmd *cobra.Command
     14 + 
     15 +func init() {
     16 + // byeCmd represents the bye command
     17 + var scanCmd = &cobra.Command{
     18 + Use: "scan",
     19 + Short: "Wrapper to run scan from input",
     20 + Long: fmt.Sprintf(`Metabigor - Intelligence Framework but without API key - %v by %v`, core.VERSION, core.AUTHOR),
     21 + RunE: runScan,
     22 + }
     23 + 
     24 + scanCmd.Flags().StringP("ports", "p", "0-65535", "Port range for previous command")
     25 + scanCmd.Flags().StringP("rate", "r", "5000", "Port range for previous command")
     26 + scanCmd.Flags().Bool("detail", false, "Do Nmap scan based on previous output")
     27 + scanCmd.Flags().BoolP("flat", "f", false, "format output like this: 1.2.3.4:443")
     28 + scanCmd.Flags().BoolP("skip-masscan", "s", false, "run nmap from input format like this: 1.2.3.4:443")
     29 + scanCmd.Flags().String("nmap-script", "", "nmap scripts")
     30 + RootCmd.AddCommand(scanCmd)
     31 + 
     32 +}
     33 + 
     34 +func runScan(cmd *cobra.Command, args []string) error {
     35 + options.Scan.NmapScripts, _ = cmd.Flags().GetString("nmap-script")
     36 + options.Scan.Ports, _ = cmd.Flags().GetString("ports")
     37 + options.Scan.Rate, _ = cmd.Flags().GetString("rate")
     38 + options.Scan.Detail, _ = cmd.Flags().GetBool("detail")
     39 + options.Scan.Flat, _ = cmd.Flags().GetBool("flat")
     40 + options.Scan.SkipOverview, _ = cmd.Flags().GetBool("skip-masscan")
     41 + 
     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 + }
     48 + 
     49 + var result []string
     50 + // var detailResult []string
     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 + if options.Scan.SkipOverview {
     61 + result = directDetail(job, options)
     62 + } else {
     63 + result = runRoutine(job, options)
     64 + }
     65 + StoreData(result, options)
     66 + }
     67 + }()
     68 + }
     69 + 
     70 + for _, input := range inputs {
     71 + jobs <- input
     72 + }
     73 + 
     74 + close(jobs)
     75 + wg.Wait()
     76 + 
     77 + return nil
     78 +}
     79 + 
     80 +func runRoutine(input string, options core.Options) []string {
     81 + core.BannerF("Run quick scan on: ", input)
     82 + var data []string
     83 + data = append(data, modules.RunMasscan(input, options)...)
     84 + if !options.Scan.Detail {
     85 + return data
     86 + }
     87 + 
     88 + var wg sync.WaitGroup
     89 + var realData []string
     90 + for _, item := range data {
     91 + wg.Add(1)
     92 + go func(item string) {
     93 + realData = append(realData, runDetail(item, options)...)
     94 + wg.Done()
     95 + }(item)
     96 + }
     97 + wg.Wait()
     98 + return realData
     99 +}
     100 + 
     101 +func runDetail(input string, options core.Options) []string {
     102 + host := strings.Split(input, " - ")[0]
     103 + ports := strings.Split(input, " - ")[1]
     104 + core.BannerF("Run detail scan on: ", fmt.Sprintf("%v %v", host, ports))
     105 + return modules.RunNmap(host, ports, options)
     106 +}
     107 + 
     108 +func directDetail(input string, options core.Options) []string {
     109 + host := strings.Split(input, ":")[0]
     110 + ports := strings.Split(input, ":")[1]
     111 + core.BannerF("Run detail scan on: ", fmt.Sprintf("%v %v", host, ports))
     112 + return modules.RunNmap(host, ports, options)
     113 +}
     114 + 
  • ■ ■ ■ ■ ■ ■
    core/common.go
     1 +package core
     2 + 
     3 +import (
     4 + "fmt"
     5 + "io/ioutil"
     6 + "os"
     7 + 
     8 + // "github.com/Sirupsen/logrus"
     9 + "github.com/fatih/color"
     10 + "github.com/sirupsen/logrus"
     11 +)
     12 + 
     13 +var log = logrus.New()
     14 + 
     15 +// InitLog init log
     16 +func InitLog(options Options) {
     17 + log.SetOutput(os.Stderr)
     18 + if options.Debug == true {
     19 + log.SetLevel(logrus.DebugLevel)
     20 + } else if options.Verbose == true {
     21 + log.SetLevel(logrus.InfoLevel)
     22 + } else {
     23 + log.SetOutput(ioutil.Discard)
     24 + }
     25 +}
     26 + 
     27 +// GoodF print good message
     28 +func GoodF(format string, args ...interface{}) {
     29 + good := color.HiGreenString("[+]")
     30 + fmt.Printf("%s %s\n", good, fmt.Sprintf(format, args...))
     31 +}
     32 + 
     33 +// BannerF print info message
     34 +func BannerF(format string, data string) {
     35 + banner := color.BlueString("[*] %v", format)
     36 + log.Info(fmt.Sprintf("%v%v", banner, color.HiGreenString(data)))
     37 +}
     38 + 
     39 +// InforF print info message
     40 +func InforF(format string, args ...interface{}) {
     41 + log.Info(fmt.Sprintf(format, args...))
     42 +}
     43 + 
     44 +// WarningF print good message
     45 +func WarningF(format string, args ...interface{}) {
     46 + good := color.YellowString("[!]")
     47 + fmt.Printf("%s %s\n", good, fmt.Sprintf(format, args...))
     48 +}
     49 + 
     50 +// DebugF print debug message
     51 +func DebugF(format string, args ...interface{}) {
     52 + log.Debug(fmt.Sprintf(format, args...))
     53 +}
     54 + 
     55 +// ErrorF print good message
     56 +func ErrorF(format string, args ...interface{}) {
     57 + good := color.RedString("[-]")
     58 + fmt.Printf("%s %s\n", good, fmt.Sprintf(format, args...))
     59 +}
     60 + 
  • ■ ■ ■ ■ ■ ■
    core/config.go
     1 +package core
     2 + 
     3 +import (
     4 + "bytes"
     5 + "fmt"
     6 + "io/ioutil"
     7 + "os"
     8 + "path/filepath"
     9 + "strings"
     10 + 
     11 + "github.com/mitchellh/go-homedir"
     12 + "github.com/spf13/viper"
     13 +)
     14 + 
     15 +// InitConfig Init the config
     16 +func InitConfig(options Options) {
     17 + options.ConfigFile, _ = homedir.Expand(options.ConfigFile)
     18 + RootFolder := filepath.Dir(options.ConfigFile)
     19 + if !FolderExists(RootFolder) {
     20 + InforF("Init new config at %v", RootFolder)
     21 + os.MkdirAll(RootFolder, 0750)
     22 + }
     23 + 
     24 + // init config
     25 + v := viper.New()
     26 + v.AddConfigPath(RootFolder)
     27 + v.SetConfigName("config")
     28 + v.SetConfigType("yaml")
     29 + if !FileExists(options.ConfigFile) {
     30 + InforF("Write new config to: %v", options.ConfigFile)
     31 + v.SetDefault("Sessions", map[string]string{
     32 + "fofa": "xxx",
     33 + "censys": "xxx",
     34 + "zoomeye": "xxx",
     35 + "github": "xxx",
     36 + })
     37 + v.SetDefault("Credentials", map[string]string{
     38 + "fofa": "username:password",
     39 + "censys": "username:password",
     40 + "zoomeye": "username:password",
     41 + "github": "username:password",
     42 + })
     43 + v.WriteConfigAs(options.ConfigFile)
     44 + } else {
     45 + if options.Debug {
     46 + InforF("Load config from: %v", options.ConfigFile)
     47 + }
     48 + b, _ := ioutil.ReadFile(options.ConfigFile)
     49 + v.ReadConfig(bytes.NewBuffer(b))
     50 + }
     51 +}
     52 + 
     53 +// GetCred get credentials
     54 +func GetCred(source string, options Options) string {
     55 + options.ConfigFile, _ = homedir.Expand(options.ConfigFile)
     56 + RootFolder := filepath.Dir(options.ConfigFile)
     57 + v := viper.New()
     58 + v.SetConfigName("config")
     59 + v.SetConfigType("yaml")
     60 + v.AddConfigPath(RootFolder)
     61 + if err := v.ReadInConfig(); err != nil {
     62 + fmt.Printf("Failed to read the configuration file: %s\n", err)
     63 + InitConfig(options)
     64 + return ""
     65 + }
     66 + 
     67 + Creds := v.GetStringMapString("Credentials")
     68 + if Creds == nil {
     69 + return ""
     70 + }
     71 + for k, v := range Creds {
     72 + if strings.ToLower(k) == strings.ToLower(source) {
     73 + return fmt.Sprintf("%v", v)
     74 + }
     75 + }
     76 + return ""
     77 +}
     78 + 
     79 +// GetSess get credentials
     80 +func GetSess(source string, options Options) string {
     81 + options.ConfigFile, _ = homedir.Expand(options.ConfigFile)
     82 + RootFolder := filepath.Dir(options.ConfigFile)
     83 + v := viper.New()
     84 + v.SetConfigName("config")
     85 + v.SetConfigType("yaml")
     86 + v.AddConfigPath(RootFolder)
     87 + if err := v.ReadInConfig(); err != nil {
     88 + fmt.Printf("Failed to read the configuration file: %s\n", err)
     89 + InitConfig(options)
     90 + return ""
     91 + }
     92 + Creds := v.GetStringMapString("Sessions")
     93 + if Creds == nil {
     94 + return ""
     95 + }
     96 + for k, v := range Creds {
     97 + if strings.ToLower(k) == strings.ToLower(source) {
     98 + return fmt.Sprintf("%v", v)
     99 + }
     100 + }
     101 + return ""
     102 +}
     103 + 
     104 +// SaveSess get credentials
     105 +func SaveSess(source string, sess string, options Options) string {
     106 + options.ConfigFile, _ = homedir.Expand(options.ConfigFile)
     107 + RootFolder := filepath.Dir(options.ConfigFile)
     108 + v := viper.New()
     109 + v.SetConfigName("config")
     110 + v.SetConfigType("yaml")
     111 + v.AddConfigPath(RootFolder)
     112 + if err := v.ReadInConfig(); err != nil {
     113 + fmt.Printf("Failed to read the configuration file: %s\n", err)
     114 + InitConfig(options)
     115 + return ""
     116 + }
     117 + 
     118 + Sessions := v.GetStringMapString("Sessions")
     119 + Sessions[source] = sess
     120 + v.Set("Sessions", Sessions)
     121 + v.WriteConfig()
     122 + return sess
     123 +}
     124 + 
  • ■ ■ ■ ■ ■ ■
    core/config_test.go
     1 +package core
     2 + 
     3 +import (
     4 + "fmt"
     5 + "testing"
     6 +)
     7 + 
     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 + }
     17 +}
     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 + }
     27 +}
     28 + 
  • ■ ■ ■ ■ ■ ■
    core/helper.go
     1 +package core
     2 + 
     3 +import (
     4 + "archive/zip"
     5 + "bufio"
     6 + "crypto/sha1"
     7 + "encoding/json"
     8 + "fmt"
     9 + "io"
     10 + "io/ioutil"
     11 + "os"
     12 + "path/filepath"
     13 + "regexp"
     14 + "strconv"
     15 + "strings"
     16 + "time"
     17 + 
     18 + "github.com/mitchellh/go-homedir"
     19 +)
     20 + 
     21 +// GetFileContent Reading file and return content of it
     22 +func GetFileContent(filename string) string {
     23 + var result string
     24 + if strings.Contains(filename, "~") {
     25 + filename, _ = homedir.Expand(filename)
     26 + }
     27 + file, err := os.Open(filename)
     28 + if err != nil {
     29 + return result
     30 + }
     31 + defer file.Close()
     32 + b, err := ioutil.ReadAll(file)
     33 + if err != nil {
     34 + return result
     35 + }
     36 + return string(b)
     37 +}
     38 + 
     39 +// ReadingFile Reading file and return content as []string
     40 +func ReadingFile(filename string) []string {
     41 + var result []string
     42 + if strings.HasPrefix(filename, "~") {
     43 + filename, _ = homedir.Expand(filename)
     44 + }
     45 + file, err := os.Open(filename)
     46 + defer file.Close()
     47 + if err != nil {
     48 + return result
     49 + }
     50 + 
     51 + scanner := bufio.NewScanner(file)
     52 + for scanner.Scan() {
     53 + val := scanner.Text()
     54 + result = append(result, val)
     55 + }
     56 + 
     57 + if err := scanner.Err(); err != nil {
     58 + return result
     59 + }
     60 + return result
     61 +}
     62 + 
     63 +// ReadingFileUnique Reading file and return content as []string
     64 +func ReadingFileUnique(filename string) []string {
     65 + var result []string
     66 + if strings.Contains(filename, "~") {
     67 + filename, _ = homedir.Expand(filename)
     68 + }
     69 + file, err := os.Open(filename)
     70 + defer file.Close()
     71 + if err != nil {
     72 + return result
     73 + }
     74 + 
     75 + unique := true
     76 + seen := make(map[string]bool)
     77 + 
     78 + scanner := bufio.NewScanner(file)
     79 + for scanner.Scan() {
     80 + val := scanner.Text()
     81 + // unique stuff
     82 + if val == "" {
     83 + continue
     84 + }
     85 + if seen[val] && unique {
     86 + continue
     87 + }
     88 + 
     89 + if unique {
     90 + seen[val] = true
     91 + result = append(result, val)
     92 + }
     93 + }
     94 + 
     95 + if err := scanner.Err(); err != nil {
     96 + return result
     97 + }
     98 + return result
     99 +}
     100 + 
     101 +// WriteToFile write string to a file
     102 +func WriteToFile(filename string, data string) (string, error) {
     103 + file, err := os.Create(filename)
     104 + if err != nil {
     105 + return "", err
     106 + }
     107 + defer file.Close()
     108 + 
     109 + _, err = io.WriteString(file, data+"\n")
     110 + if err != nil {
     111 + return "", err
     112 + }
     113 + return filename, file.Sync()
     114 +}
     115 + 
     116 +// AppendToContent append string to a file
     117 +func AppendToContent(filename string, data string) (string, error) {
     118 + // If the file doesn't exist, create it, or append to the file
     119 + f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
     120 + if err != nil {
     121 + return "", err
     122 + }
     123 + if _, err := f.Write([]byte(data + "\n")); err != nil {
     124 + return "", err
     125 + }
     126 + if err := f.Close(); err != nil {
     127 + return "", err
     128 + }
     129 + return filename, nil
     130 +}
     131 + 
     132 +// FileExists check if file is exist or not
     133 +func FileExists(filename string) bool {
     134 + info, err := os.Stat(filename)
     135 + if os.IsNotExist(err) {
     136 + return false
     137 + }
     138 + return !info.IsDir()
     139 +}
     140 + 
     141 +// FolderExists check if file is exist or not
     142 +func FolderExists(foldername string) bool {
     143 + if _, err := os.Stat(foldername); os.IsNotExist(err) {
     144 + return false
     145 + }
     146 + return true
     147 +}
     148 + 
     149 +// GetFileNames get all file name with extension
     150 +func GetFileNames(dir string, ext string) []string {
     151 + if _, err := os.Stat(dir); os.IsNotExist(err) {
     152 + return nil
     153 + }
     154 + 
     155 + var files []string
     156 + filepath.Walk(dir, func(path string, f os.FileInfo, _ error) error {
     157 + if !f.IsDir() {
     158 + if strings.HasSuffix(f.Name(), ext) {
     159 + filename, _ := filepath.Abs(path)
     160 + files = append(files, filename)
     161 + }
     162 + }
     163 + return nil
     164 + })
     165 + return files
     166 +}
     167 + 
     168 +// IsJSON check if string is JSON or not
     169 +func IsJSON(str string) bool {
     170 + var js json.RawMessage
     171 + return json.Unmarshal([]byte(str), &js) == nil
     172 +}
     173 + 
     174 +// GetTS get current timestamp and return a string
     175 +func GetTS() string {
     176 + return strconv.FormatInt(time.Now().Unix(), 10)
     177 +}
     178 + 
     179 +// GenHash gen SHA1 hash from string
     180 +func GenHash(text string) string {
     181 + h := sha1.New()
     182 + h.Write([]byte(text))
     183 + hashed := h.Sum(nil)
     184 + return fmt.Sprintf("%x", hashed)
     185 +}
     186 + 
     187 +// Unzip will decompress a zip archive, moving all files and folders
     188 +// within the zip file (parameter 1) to an output directory (parameter 2).
     189 +func Unzip(src string, dest string) ([]string, error) {
     190 + 
     191 + var filenames []string
     192 + 
     193 + r, err := zip.OpenReader(src)
     194 + if err != nil {
     195 + return filenames, err
     196 + }
     197 + defer r.Close()
     198 + 
     199 + for _, f := range r.File {
     200 + 
     201 + // Store filename/path for returning and using later on
     202 + fpath := filepath.Join(dest, f.Name)
     203 + 
     204 + if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
     205 + return filenames, fmt.Errorf("%s: illegal file path", fpath)
     206 + }
     207 + 
     208 + filenames = append(filenames, fpath)
     209 + 
     210 + if f.FileInfo().IsDir() {
     211 + // Make Folder
     212 + os.MkdirAll(fpath, os.ModePerm)
     213 + continue
     214 + }
     215 + 
     216 + // Make File
     217 + if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
     218 + return filenames, err
     219 + }
     220 + 
     221 + outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
     222 + if err != nil {
     223 + return filenames, err
     224 + }
     225 + 
     226 + rc, err := f.Open()
     227 + if err != nil {
     228 + return filenames, err
     229 + }
     230 + 
     231 + _, err = io.Copy(outFile, rc)
     232 + 
     233 + // Close the file without defer to close before next iteration of loop
     234 + outFile.Close()
     235 + rc.Close()
     236 + 
     237 + if err != nil {
     238 + return filenames, err
     239 + }
     240 + }
     241 + return filenames, nil
     242 +}
     243 + 
     244 +// ExpandLength make slice to length
     245 +func ExpandLength(list []string, length int) []string {
     246 + c := []string{}
     247 + for i := 1; i <= length; i++ {
     248 + c = append(c, list[i%len(list)])
     249 + }
     250 + return c
     251 +}
     252 + 
     253 +// StartWithNum check if string start with number
     254 +func StartWithNum(raw string) bool {
     255 + r, err := regexp.Compile("^[0-9].*")
     256 + if err != nil {
     257 + return false
     258 + }
     259 + return r.MatchString(raw)
     260 +}
     261 + 
  • ■ ■ ■ ■ ■ ■
    core/options.go
     1 +package core
     2 + 
     3 +// Options global options
     4 +type Options struct {
     5 + Input string
     6 + Output string
     7 + TmpOutput string
     8 + ConfigFile string
     9 + Proxy string
     10 + 
     11 + Concurrency int
     12 + Delay int
     13 + SaveRaw bool
     14 + Timeout int
     15 + Verbose bool
     16 + Debug bool
     17 + // Ports string
     18 + // Rate string
     19 + Scan ScanOptions
     20 + Net NetOptions
     21 +}
     22 + 
     23 +// ScanOptions options for net command
     24 +type ScanOptions struct {
     25 + Ports string
     26 + Rate string
     27 + Detail bool
     28 + Flat bool
     29 + SkipOverview bool
     30 + TmpOutput string
     31 + NmapScripts string
     32 +}
     33 + 
     34 +// NetOptions options for net command
     35 +type NetOptions struct {
     36 + Asn string
     37 + Org string
     38 +}
     39 + 
     40 +// HTTPRequest all information about response
     41 +type HTTPRequest struct {
     42 + Method string
     43 + URL string
     44 + Headers map[string]string
     45 + Body string
     46 +}
     47 + 
     48 +// HTTPResponse all information about response
     49 +type HTTPResponse struct {
     50 + StatusCode int
     51 + Status string
     52 + Headers map[string][]string
     53 + Body string
     54 + ResponseTime float64
     55 + Length int
     56 + Beautify string
     57 +}
     58 + 
  • ■ ■ ■ ■ ■ ■
    core/request.go
     1 +package core
     2 + 
     3 +import (
     4 + "context"
     5 + "crypto/tls"
     6 + "fmt"
     7 + "strconv"
     8 + "strings"
     9 + "time"
     10 + 
     11 + "github.com/chromedp/chromedp"
     12 + "github.com/jaeles-project/jaeles/libs"
     13 + "github.com/parnurzeal/gorequest"
     14 +)
     15 + 
     16 +// RequestWithChrome Do request with real browser
     17 +func RequestWithChrome(url string, contentID string) string {
     18 + // opts := append(chromedp.DefaultExecAllocatorOptions[:],
     19 + // chromedp.Flag("headless", false),
     20 + // chromedp.Flag("disable-gpu", true),
     21 + // chromedp.Flag("enable-automation", true),
     22 + // chromedp.Flag("disable-extensions", false),
     23 + // )
     24 + ctx, cancel := chromedp.NewContext(context.Background())
     25 + ctx, cancel = context.WithTimeout(ctx, 10*time.Second)
     26 + defer cancel()
     27 + 
     28 + // run task list
     29 + var data string
     30 + err := chromedp.Run(ctx,
     31 + chromedp.Navigate(url),
     32 + // chromedp.WaitVisible(contentID),
     33 + chromedp.OuterHTML(contentID, &data, chromedp.NodeVisible, chromedp.ByID),
     34 + )
     35 + if err != nil {
     36 + return ""
     37 + }
     38 + 
     39 + return data
     40 +}
     41 + 
     42 +// SendGET just send GET request
     43 +func SendGET(url string, options Options) string {
     44 + req := HTTPRequest{
     45 + Method: "GET",
     46 + URL: url,
     47 + }
     48 + resp := SendRequest(req, options)
     49 + return resp.Body
     50 +}
     51 + 
     52 +// SendPOST just send POST request
     53 +func SendPOST(url string, options Options) string {
     54 + req := HTTPRequest{
     55 + Method: "POST",
     56 + URL: url,
     57 + }
     58 + resp := SendRequest(req, options)
     59 + return resp.Body
     60 +}
     61 + 
     62 +// SendRequest just send GET request
     63 +func SendRequest(req HTTPRequest, options Options) HTTPResponse {
     64 + method := req.Method
     65 + url := req.URL
     66 + headers := req.Headers
     67 + body := req.Body
     68 + 
     69 + // new client
     70 + client := gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true})
     71 + client.Timeout(time.Duration(options.Timeout) * time.Second)
     72 + if options.Proxy != "" {
     73 + client.Proxy(options.Proxy)
     74 + }
     75 + var res HTTPResponse
     76 + // choose method
     77 + switch method {
     78 + case "GET":
     79 + client.Get(url)
     80 + break
     81 + case "POST":
     82 + client.Post(url)
     83 + break
     84 + case "PUT":
     85 + client.Put(url)
     86 + break
     87 + case "HEAD":
     88 + client.Head(url)
     89 + break
     90 + case "PATCH":
     91 + client.Patch(url)
     92 + break
     93 + case "DELETE":
     94 + client.Delete(url)
     95 + break
     96 + }
     97 + 
     98 + timeStart := time.Now()
     99 + for k, v := range headers {
     100 + client.AppendHeader(k, v)
     101 + }
     102 + if body != "" {
     103 + client.Send(body)
     104 + }
     105 + 
     106 + // really sending stuff
     107 + resp, resBody, errs := client.End()
     108 + resTime := time.Since(timeStart).Seconds()
     109 + 
     110 + if len(errs) > 0 && res.StatusCode != 0 {
     111 + return res
     112 + } else if len(errs) > 0 {
     113 + libs.ErrorF("Error sending %v", errs)
     114 + return HTTPResponse{}
     115 + }
     116 + 
     117 + resp.Body.Close()
     118 + // return ParseResponse(resp, resBody, resTime), nil
     119 + 
     120 + return ParseResponse(resp, resBody, resTime)
     121 + 
     122 +}
     123 + 
     124 +// ParseResponse field to Response
     125 +func ParseResponse(resp gorequest.Response, resBody string, resTime float64) (res HTTPResponse) {
     126 + // var res libs.Response
     127 + resLength := len(string(resBody))
     128 + 
     129 + // format the headers
     130 + var resHeaders []map[string]string
     131 + for k, v := range resp.Header {
     132 + element := make(map[string]string)
     133 + element[k] = strings.Join(v[:], "")
     134 + resLength += len(fmt.Sprintf("%s: %s\n", k, strings.Join(v[:], "")))
     135 + resHeaders = append(resHeaders, element)
     136 + }
     137 + // respones time in second
     138 + resHeaders = append(resHeaders,
     139 + map[string]string{"Total Length": strconv.Itoa(resLength)},
     140 + map[string]string{"Response Time": fmt.Sprintf("%f", resTime)},
     141 + )
     142 + 
     143 + // set some variable
     144 + res.Headers = resp.Header
     145 + res.StatusCode = resp.StatusCode
     146 + res.Status = resp.Status
     147 + res.Body = resBody
     148 + res.ResponseTime = resTime
     149 + res.Length = resLength
     150 + return res
     151 +}
     152 + 
  • ■ ■ ■ ■ ■ ■
    core/version.go
     1 +package core
     2 + 
     3 +const (
     4 + // VERSION current Jaeles version
     5 + VERSION = "beta v0.1"
     6 + // AUTHOR author of this
     7 + AUTHOR = "@j3ssiejjj"
     8 +)
     9 + 
  • ■ ■ ■ ■ ■ ■
    main.go
     1 +package main
     2 + 
     3 +import "github.com/j3ssie/metabigor/cmd"
     4 + 
     5 +func main() {
     6 + cmd.Execute()
     7 +}
     8 + 
  • ■ ■ ■ ■ ■ ■
    modules/netblock.go
     1 +package modules
     2 + 
     3 +import (
     4 + "encoding/json"
     5 + "fmt"
     6 + "strings"
     7 + 
     8 + "github.com/PuerkitoBio/goquery"
     9 + "github.com/j3ssie/metabigor/core"
     10 + "github.com/thoas/go-funk"
     11 +)
     12 + 
     13 +func getAsnNum(raw string) string {
     14 + if strings.HasPrefix(strings.ToLower(raw), "as") {
     15 + return raw[2:]
     16 + }
     17 + return raw
     18 +}
     19 + 
     20 +// IPInfo get CIDR from ASN
     21 +func IPInfo(options core.Options) []string {
     22 + asn := getAsnNum(options.Net.Asn)
     23 + url := fmt.Sprintf(`https://ipinfo.io/AS%v`, asn)
     24 + var result []string
     25 + core.InforF("Get data from: %v", url)
     26 + content := core.RequestWithChrome(url, "ipTabContent")
     27 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
     28 + if err != nil {
     29 + return result
     30 + }
     31 + // searching for data
     32 + doc.Find("tr").Each(func(i int, s *goquery.Selection) {
     33 + s.Find("address").First()
     34 + if !strings.Contains(s.Text(), "Netblock") {
     35 + data := strings.Split(strings.TrimSpace(s.Text()), " ")
     36 + cidr := strings.TrimSpace(data[0])
     37 + desc := strings.TrimSpace(data[len(data)-1])
     38 + 
     39 + core.InforF(fmt.Sprintf("%s - %s", cidr, desc))
     40 + result = append(result, fmt.Sprintf("%s", cidr))
     41 + }
     42 + 
     43 + })
     44 + return result
     45 +}
     46 + 
     47 +// IPv4Info get CIDR from ASN via ipv4info.com
     48 +func IPv4Info(options core.Options) []string {
     49 + asn := getAsnNum(options.Net.Asn)
     50 + url := fmt.Sprintf(`http://ipv4info.com/?act=check&ip=AS%v`, asn)
     51 + var result []string
     52 + 
     53 + core.InforF("Get data from: %v", url)
     54 + content := core.SendGET(url, options)
     55 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
     56 + if err != nil {
     57 + return result
     58 + }
     59 + 
     60 + // finding ID of block
     61 + var ASNLink []string
     62 + doc.Find("a").Each(func(i int, s *goquery.Selection) {
     63 + href, ok := s.Attr("href")
     64 + if ok {
     65 + if strings.HasPrefix(href, "/org/") {
     66 + ASNLink = append(ASNLink, href)
     67 + }
     68 + }
     69 + })
     70 + 
     71 + // searching for data
     72 + ASNLink = funk.Uniq(ASNLink).([]string)
     73 + for _, link := range ASNLink {
     74 + core.InforF("Get data from: %v", link)
     75 + url := fmt.Sprintf(`http://ipv4info.com%v`, link)
     76 + core.InforF("Get data from: %v", url)
     77 + content := core.SendGET(url, options)
     78 + // finding ID of block
     79 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
     80 + if err != nil {
     81 + return result
     82 + }
     83 + 
     84 + doc.Find("td").Each(func(i int, s *goquery.Selection) {
     85 + style, _ := s.Attr("style")
     86 + class, _ := s.Attr("class")
     87 + if style == "padding: 0 0 0 0;" && class == "bold" {
     88 + data := s.Text()
     89 + result = append(result, data)
     90 + }
     91 + 
     92 + })
     93 + }
     94 + core.InforF("\n%v", strings.Join(result, "\n"))
     95 + return result
     96 +}
     97 + 
     98 +// ASNBgpDotNet get ASN infor from bgp.net
     99 +func ASNBgpDotNet(options core.Options) []string {
     100 + asn := getAsnNum(options.Net.Asn)
     101 + url := fmt.Sprintf(`https://bgp.he.net/AS%v#_prefixes`, asn)
     102 + core.InforF("Get data from: %v", url)
     103 + var result []string
     104 + content := core.RequestWithChrome(url, "prefixes")
     105 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
     106 + if err != nil {
     107 + return result
     108 + }
     109 + // searching for data
     110 + doc.Find("tr").Each(func(i int, s *goquery.Selection) {
     111 + data := strings.Split(strings.TrimSpace(s.Text()), " ")
     112 + cidr := strings.TrimSpace(data[0])
     113 + if !strings.Contains(cidr, "Prefix") {
     114 + desc := strings.TrimSpace(data[len(data)-1])
     115 + core.InforF(fmt.Sprintf("%s - %s", cidr, desc))
     116 + result = append(result, fmt.Sprintf("%s", cidr))
     117 + }
     118 + })
     119 + return result
     120 +}
     121 + 
     122 +// ASNSpyse get ASN infor from spyse.com
     123 +func ASNSpyse(options core.Options) []string {
     124 + asn := getAsnNum(options.Net.Asn)
     125 + url := fmt.Sprintf(`https://spyse.com/target/as/%v#c-domain__anchor--3--%v`, asn, asn)
     126 + var result []string
     127 + core.InforF("Get data from: %v", url)
     128 + content := core.RequestWithChrome(url, "asn-ipv4-ranges")
     129 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
     130 + if err != nil {
     131 + return result
     132 + }
     133 + // searching for data
     134 + doc.Find("tr").Each(func(i int, s *goquery.Selection) {
     135 + data := strings.Split(strings.TrimSpace(s.Text()), " ")
     136 + cidr := strings.TrimSpace(data[0])
     137 + if !strings.Contains(cidr, "CIDR") {
     138 + desc := strings.Split(data[len(data)-2], "\n")
     139 + realDesc := desc[len(desc)-1]
     140 + core.InforF(fmt.Sprintf("%s - %s", cidr, realDesc))
     141 + result = append(result, fmt.Sprintf("%s", cidr))
     142 + }
     143 + })
     144 + return result
     145 +}
     146 + 
     147 +/* Get IP range from Organization */
     148 + 
     149 +// OrgBgpDotNet get Org infor from bgp.net
     150 +func OrgBgpDotNet(options core.Options) []string {
     151 + org := options.Net.Org
     152 + url := fmt.Sprintf(`https://bgp.he.net/search?search%%5Bsearch%%5D=%v&commit=Search`, org)
     153 + core.InforF("Get data from: %v", url)
     154 + var result []string
     155 + content := core.RequestWithChrome(url, "search")
     156 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
     157 + if err != nil {
     158 + return result
     159 + }
     160 + 
     161 + // searching for data
     162 + doc.Find("tr").Each(func(i int, s *goquery.Selection) {
     163 + if !strings.Contains(s.Text(), "Result") && !strings.Contains(s.Text(), "Description") {
     164 + data := strings.Split(strings.TrimSpace(s.Text()), " ")[0]
     165 + realdata := strings.Split(data, "\n")
     166 + cidr := strings.TrimSpace(realdata[0])
     167 + desc := strings.TrimSpace(realdata[len(realdata)-1])
     168 + core.InforF(fmt.Sprintf("%s - %s", cidr, desc))
     169 + result = append(result, fmt.Sprintf("%s", cidr))
     170 + }
     171 + })
     172 + return result
     173 +}
     174 + 
     175 +// ASNLookup get Org CIDR from asnlookup
     176 +func ASNLookup(options core.Options) []string {
     177 + org := options.Net.Org
     178 + url := fmt.Sprintf(`http://asnlookup.com/api/lookup?org=%v`, org)
     179 + core.InforF("Get data from: %v", url)
     180 + data := core.SendGET(url, options)
     181 + var result []string
     182 + if data == "" {
     183 + return result
     184 + }
     185 + err := json.Unmarshal([]byte(data), &result)
     186 + if err != nil {
     187 + return result
     188 + }
     189 + 
     190 + for _, item := range result {
     191 + core.InforF(item)
     192 + }
     193 + return result
     194 +}
     195 + 
  • ■ ■ ■ ■ ■ ■
    modules/netblock_test.go
     1 +package modules
     2 + 
     3 +import (
     4 + "testing"
     5 + 
     6 + "github.com/j3ssie/metabigor/core"
     7 +)
     8 + 
     9 +func TestIPInfo(t *testing.T) {
     10 + var options core.Options
     11 + options.Net.Asn = "AS714"
     12 + result := IPInfo(options)
     13 + if len(result) == 0 {
     14 + t.Errorf("Error IPInfo")
     15 + }
     16 +}
     17 + 
     18 +func TestIPv4Info(t *testing.T) {
     19 + var options core.Options
     20 + options.Net.Asn = "AS6432"
     21 + result := IPv4Info(options)
     22 + if len(result) == 0 {
     23 + t.Errorf("Error IPv4Info")
     24 + }
     25 +}
     26 + 
     27 +func TestASNBgpDotNet(t *testing.T) {
     28 + var options core.Options
     29 + options.Net.Asn = "AS62830"
     30 + result := ASNBgpDotNet(options)
     31 + if len(result) == 0 {
     32 + t.Errorf("Error TestASNBgpDotNet")
     33 + }
     34 +}
     35 + 
     36 +func TestASNSpyse(t *testing.T) {
     37 + var options core.Options
     38 + options.Net.Asn = "714"
     39 + result := ASNSpyse(options)
     40 + if len(result) == 0 {
     41 + t.Errorf("Error TestASNSpyse")
     42 + }
     43 +}
     44 + 
     45 +func TestOrgBgpDotNet(t *testing.T) {
     46 + var options core.Options
     47 + options.Net.Org = "riot"
     48 + result := OrgBgpDotNet(options)
     49 + if len(result) == 0 {
     50 + t.Errorf("Error TestOrgBgpDotNet")
     51 + }
     52 +}
     53 + 
     54 +func TestASNLookup(t *testing.T) {
     55 + var options core.Options
     56 + options.Net.Org = "riot"
     57 + result := ASNLookup(options)
     58 + if len(result) == 0 {
     59 + t.Errorf("Error ASNLookup")
     60 + }
     61 +}
     62 + 
  • ■ ■ ■ ■ ■ ■
    modules/scan.go
     1 +package modules
     2 + 
     3 +import (
     4 + "fmt"
     5 + "io/ioutil"
     6 + "os"
     7 + "os/exec"
     8 + "strings"
     9 + 
     10 + "github.com/PuerkitoBio/goquery"
     11 + "github.com/j3ssie/metabigor/core"
     12 +)
     13 + 
     14 +// RunMasscan run masscan command and return list of port open
     15 +func RunMasscan(input string, options core.Options) []string {
     16 + ports := options.Scan.Ports
     17 + rate := options.Scan.Rate
     18 + if ports == "" {
     19 + ports = "443"
     20 + }
     21 + 
     22 + massOutput := options.Scan.TmpOutput
     23 + tmpFile, _ := ioutil.TempFile(os.TempDir(), "mass-*")
     24 + if massOutput != "" {
     25 + tmpFile, _ = ioutil.TempFile(massOutput, "mass-*")
     26 + }
     27 + massOutput = tmpFile.Name()
     28 + 
     29 + masscanCmd := fmt.Sprintf("sudo masscan --rate %v -p %v -oX %v %v", rate, ports, massOutput, input)
     30 + core.DebugF("Execute: %v", masscanCmd)
     31 + command := []string{
     32 + "bash",
     33 + "-c",
     34 + masscanCmd,
     35 + }
     36 + exec.Command(command[0], command[1:]...).CombinedOutput()
     37 + // parse output
     38 + var realResult []string
     39 + result := make(map[string]string)
     40 + if !core.FileExists(massOutput) {
     41 + return realResult
     42 + }
     43 + data := core.GetFileContent(massOutput)
     44 + rawResult := ParsingMasscan(data)
     45 + // get flat output for easily parse to other tools
     46 + if options.Scan.Flat {
     47 + for k, v := range rawResult {
     48 + for _, port := range v {
     49 + realResult = append(realResult, fmt.Sprintf("%v:%v", k, port))
     50 + }
     51 + }
     52 + return realResult
     53 + }
     54 + 
     55 + // group them by host
     56 + for k, v := range rawResult {
     57 + result[k] += fmt.Sprintf("%v", strings.Join(v, ","))
     58 + }
     59 + 
     60 + for k, v := range result {
     61 + realResult = append(realResult, fmt.Sprintf("%v - %v", k, v))
     62 + }
     63 + 
     64 + return realResult
     65 +}
     66 + 
     67 +// RunNmap run nmap command and return list of port open
     68 +func RunNmap(input string, ports string, options core.Options) []string {
     69 + // ports := options.Ports
     70 + if ports == "" {
     71 + ports = "443"
     72 + }
     73 + nmapOutput := options.Scan.TmpOutput
     74 + tmpFile, _ := ioutil.TempFile(os.TempDir(), "nmap-*")
     75 + if nmapOutput != "" {
     76 + tmpFile, _ = ioutil.TempFile(nmapOutput, "nmap-*")
     77 + }
     78 + nmapOutput = tmpFile.Name()
     79 + nmapCmd := fmt.Sprintf("sudo nmap -sSV -p %v %v -T4 -oA %v", ports, input, nmapOutput)
     80 + if options.Scan.NmapScripts != "" {
     81 + nmapCmd = fmt.Sprintf("sudo nmap -sSV -p %v %v -T4 --script %v -oA %v", ports, input, options.Scan.NmapScripts, nmapOutput)
     82 + }
     83 + core.DebugF("Execute: %v", nmapCmd)
     84 + command := []string{
     85 + "bash",
     86 + "-c",
     87 + nmapCmd,
     88 + }
     89 + exec.Command(command[0], command[1:]...).CombinedOutput()
     90 + var result []string
     91 + realNmapOutput := nmapOutput + ".xml"
     92 + if !core.FileExists(realNmapOutput) {
     93 + return result
     94 + }
     95 + // result := ""
     96 + data := core.GetFileContent(realNmapOutput)
     97 + rawResult := ParsingNmap(data)
     98 + for k, v := range rawResult {
     99 + result = append(result, fmt.Sprintf("%v - %v", k, strings.Join(v, ",")))
     100 + }
     101 + 
     102 + return result
     103 +}
     104 + 
     105 +// ParsingMasscan parse result from masscan XML format
     106 +func ParsingMasscan(raw string) map[string][]string {
     107 + result := make(map[string][]string)
     108 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(raw))
     109 + if err != nil {
     110 + return result
     111 + }
     112 + 
     113 + doc.Find("host").Each(func(i int, s *goquery.Selection) {
     114 + ip, _ := s.Find("address").First().Attr("addr")
     115 + port, _ := s.Find("port").First().Attr("portid")
     116 + result[ip] = append(result[ip], port)
     117 + })
     118 + 
     119 + return result
     120 +}
     121 + 
     122 +// ParsingNmap parse result from nmap XML format
     123 +func ParsingNmap(raw string) map[string][]string {
     124 + result := make(map[string][]string)
     125 + 
     126 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(raw))
     127 + if err != nil {
     128 + return result
     129 + }
     130 + doc.Find("host").Each(func(i int, h *goquery.Selection) {
     131 + ip, _ := h.Find("address").First().Attr("addr")
     132 + h.Find("port").Each(func(j int, s *goquery.Selection) {
     133 + service, _ := s.Find("service").First().Attr("name")
     134 + product, ok := s.Find("service").First().Attr("product")
     135 + if !ok {
     136 + product = ""
     137 + }
     138 + port, _ := s.Attr("portid")
     139 + info := fmt.Sprintf("%v/%v/%v", port, service, product)
     140 + // fmt.Println(ip, port, service)
     141 + result[ip] = append(result[ip], strings.TrimSpace(info))
     142 + })
     143 + })
     144 + 
     145 + return result
     146 +}
     147 + 
  • ■ ■ ■ ■ ■ ■
    modules/scan_test.go
     1 +package modules
     2 + 
     3 +import (
     4 + "fmt"
     5 + "testing"
     6 + 
     7 + "github.com/j3ssie/metabigor/core"
     8 +)
     9 + 
     10 +func TestRunMasscan(t *testing.T) {
     11 + var options core.Options
     12 + options.Input = "103.102.128.0/24"
     13 + result := RunMasscan("103.102.128.0/24", options)
     14 + if len(result) == 0 {
     15 + t.Errorf("Error RunMasscan")
     16 + }
     17 +}
     18 +func TestParsingNmap(t *testing.T) {
     19 + // var options core.Options
     20 + // options.Input = "103.102.128.0/24"
     21 + raw := core.GetFileContent("/tmp/tau/tl.xml")
     22 + result := ParsingNmap(raw)
     23 + fmt.Println(result)
     24 + if len(result) == 0 {
     25 + t.Errorf("Error RunMasscan")
     26 + }
     27 +}
     28 + 
  • ■ ■ ■ ■ ■ ■
    modules/search.go
     1 +package modules
     2 + 
     3 +import (
     4 + "fmt"
     5 + "strings"
     6 + 
     7 + "github.com/PuerkitoBio/goquery"
     8 + "github.com/j3ssie/metabigor/core"
     9 +)
     10 + 
     11 +// FoFa doing searching on FoFa
     12 +func FoFa(options core.Options) string {
     13 + asn := options.Net.Asn
     14 + url := fmt.Sprintf(`https://ipinfo.io/%v`, asn)
     15 + 
     16 + if options.Debug {
     17 + core.DebugF(url)
     18 + }
     19 + 
     20 + content := core.RequestWithChrome(url, "ipTabContent")
     21 + doc, err := goquery.NewDocumentFromReader(strings.NewReader(content))
     22 + if err != nil {
     23 + return ""
     24 + }
     25 + // searching for data
     26 + doc.Find("tr").Each(func(i int, s *goquery.Selection) {
     27 + data := strings.Split(strings.TrimSpace(s.Text()), " ")
     28 + cidr := strings.TrimSpace(data[0])
     29 + desc := strings.TrimSpace(data[len(data)-1])
     30 + fmt.Printf("Link #%d:\ntext: %s - %s\n\n", i, cidr, desc)
     31 + })
     32 + return content
     33 +}
     34 + 
     35 +// // FofaLogin do login to Fofa
     36 +// func FofaSession(options core.Options) bool {
     37 +// // check session is still valid or not
     38 +// sessURL := "https://fofa.so/user/users/info"
     39 +// headers := map[string]string{
     40 +// "Cookie": core.GetSess("fofa", options),
     41 +// }
     42 +// core.DebugF(sessURL)
     43 +// req := core.HTTPRequest{
     44 +// Method: "GET",
     45 +// URL: "https://fofa.so/user/users/info",
     46 +// Headers: headers,
     47 +// }
     48 +// resp := core.SendRequest(req, options)
     49 +// if resp.StatusCode == 200 {
     50 +// return true
     51 +// }
     52 + 
     53 +// return false
     54 +// }
     55 + 
  • ■ ■ ■ ■ ■ ■
    modules/search_test.go
     1 +package modules
     2 + 
     3 +import (
     4 + "testing"
     5 + 
     6 + "github.com/j3ssie/metabigor/core"
     7 +)
     8 + 
     9 +func TestFofa(t *testing.T) {
     10 + var options core.Options
     11 + options.Input = "103.102.128.0/24"
     12 + result := RunMasscan("103.102.128.0/24", options)
     13 + if len(result) == 0 {
     14 + t.Errorf("Error RunMasscan")
     15 + }
     16 +}
     17 + 
Please wait...
Page is in error, reload to recover