├── images ├── pegasus.png └── recent.png ├── src ├── helper │ ├── version.go │ ├── ascii.go │ └── helper.go ├── network │ ├── sniffing │ │ └── packet_sniffer.go │ ├── network_tools.go │ └── scanning │ │ └── port_scanner.go ├── cmd │ └── cmd.go ├── osint │ └── osint_tools.go └── shell.go ├── Dockerfile ├── go.mod ├── main.go ├── COPYING ├── install └── install-pcap ├── go.sum └── README.md /images/pegasus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nebrix/Pegasus/HEAD/images/pegasus.png -------------------------------------------------------------------------------- /images/recent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nebrix/Pegasus/HEAD/images/recent.png -------------------------------------------------------------------------------- /src/helper/version.go: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | func GetVersion() string { 4 | version := "4.4.2" 5 | return version 6 | } 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.21 2 | 3 | WORKDIR /app 4 | 5 | COPY . . 6 | 7 | RUN apt-get update && \ 8 | apt-get install -y libpcap-dev 9 | 10 | RUN go build -o pegasus 11 | 12 | CMD [ "./pegasus" ] -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module shell 2 | 3 | go 1.21 4 | 5 | require ( 6 | github.com/go-ping/ping v1.1.0 7 | github.com/google/gopacket v1.1.19 8 | github.com/likexian/whois v1.15.1 9 | golang.org/x/net v0.23.0 10 | ) 11 | 12 | require ( 13 | github.com/google/uuid v1.4.0 // indirect 14 | golang.org/x/sync v0.5.0 // indirect 15 | golang.org/x/sys v0.18.0 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | shell "shell/src" 7 | ) 8 | 9 | func main() { 10 | styleFlag := flag.String("style", "default", "Specify the shell style") 11 | flag.Parse() 12 | 13 | config := shell.ShellConfig{PromptStyle: *styleFlag} 14 | initializeShell, err := shell.NewShell(config) 15 | if err != nil { 16 | fmt.Printf("Error initializing shell: %v\n", err) 17 | return 18 | } 19 | 20 | initializeShell.Start() 21 | } 22 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Nebrix 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. -------------------------------------------------------------------------------- /install/install-pcap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | os_name=$(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2 | awk '{print $1}') 4 | 5 | case "$os_name" in 6 | "Arch") 7 | # Arch Linux Installer 8 | if command -v pacman &> /dev/null; then 9 | sudo pacman -S --needed --noconfirm libpcap 10 | elif command -v yay &> /dev/null; then 11 | yay -S --needed --noconfirm libpcap 12 | fi 13 | ;; 14 | "Ubuntu" | "Debian" | "LinuxMint" | "elementary" | "Pop") 15 | # Debian-based Linux Installer 16 | if command -v apt-get &> /dev/null; then 17 | sudo apt-get install -y libpcap-dev 18 | fi 19 | ;; 20 | "Fedora" | "RedHat" | "CentOS") 21 | # Redhat-based Linux Installer 22 | if command -v dnf &> /dev/null; then 23 | sudo dnf install -y libpcap-devel 24 | elif command -v yum &> /dev/null; then 25 | sudo yum install -y libpcap-devel 26 | fi 27 | ;; 28 | *) 29 | echo -e "\033[0;31m[-] Unsupported Linux distribuation. Please install libpcap manually.\033[0m" 30 | ;; 31 | esac 32 | 33 | if [ $? -eq 0 ]; then 34 | echo -e "\033[0;32m[+] Install successful!\033[0m" 35 | else 36 | echo -e "\033[0;31m[-] Install failed.\033[0m" 37 | fi -------------------------------------------------------------------------------- /src/helper/ascii.go: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "runtime" 7 | ) 8 | 9 | func getUsername() string { 10 | username := os.Getenv("USER") 11 | if username == "" { 12 | username = os.Getenv("LOGNAME") 13 | } 14 | if username == "" { 15 | username = os.Getenv("USERNAME") 16 | } 17 | if username == "" { 18 | username = "Unknown" 19 | } 20 | return username 21 | } 22 | 23 | func retrieveDistributionName() string { 24 | if runtime.GOOS == "windows" { 25 | return "Windows" 26 | } else if runtime.GOOS == "linux" { 27 | return "Linux" 28 | } else { 29 | return "MacOS" 30 | } 31 | } 32 | 33 | func Ascii() { 34 | username := getUsername() 35 | distro := retrieveDistributionName() 36 | 37 | fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⡀⠀⠀⠀⠀⠀") 38 | fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣧⠃⡃⠀⠀⠀⠀⠀") 39 | fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⢿⠇⠏⡇⠀⠀⠀⠀") 40 | fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣟⠏⡜⠰⢣⠀⠀⠀⠀") 41 | fmt.Println("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡴⠟⣡⠊⡠⢁⣎⠀⠀⠀⠀") 42 | fmt.Println("⠀⠀⢀⣶⣰⡂⠀⠀⠀⠀⣠⠖⠋⡔⠊⡠⢏⡠⢃⡜⠀⠀⠀⠀") 43 | fmt.Println("⠀⠀⡧⣩⠾⢹⣓⣤⠀⠘⣯⡀⠀⣗⣋⣤⢃⠔⢩⠆⠀⠀⠀⠀") 44 | fmt.Println("⠀⣸⣅⠁⢁⡞⠨⡍⢷⢂⡾⠁⣰⠡⠤⣊⠥⠒⠁⠀⠀⠀⠀⠀") 45 | fmt.Println("⠘⠿⠽⠞⢫⠀⠀⠀⢻⠟⣡⡾⠱⡑⠦⠥⣀⣀⣀⠀⠀⠀⠀⠀") 46 | fmt.Println("⠀⠀⠀⠀⡎⢀⠐⠀⠁⠈⠺⠷⠣⠃⠁⡀⠈⢿⡇⠨⢢⠀⠀⠀") 47 | fmt.Println("⠀⠀⠀⢀⡃⠀⠐⠀⠂⠐⠂⢀⠂⠂⠐⢀⠀⡾⢔⢄⠡⣃⠀⠀") 48 | fmt.Printf("⠀ ⢸⡏⠃⠀⠙⣞⡆⠀⠀⠀⠀⠀⠀⣵⡚⠱⣎⣇⠀⠀ username: %v\n", username) 49 | fmt.Printf(" ⠀ ⣿⣷⠄⠀⠀⢹⣽⠀⠀⠀⠀⠀⣼⣳⠃⠀⠹⣾⣤⠀ OS : %v\n", distro) 50 | fmt.Printf("⠀ ⠉⠁⠀⠀⠰⠿⠟⠀⠀⠀⠀⠘⠛⠛⠀⠀⠀⠹⠋ version : %v\n", GetVersion()) 51 | } 52 | -------------------------------------------------------------------------------- /src/network/sniffing/packet_sniffer.go: -------------------------------------------------------------------------------- 1 | package sniffing 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/google/gopacket" 8 | "github.com/google/gopacket/pcap" 9 | ) 10 | 11 | func printPacketInfo(packet gopacket.Packet) { 12 | networkLayer := packet.NetworkLayer() 13 | transportLayer := packet.TransportLayer() 14 | applicationLayer := packet.ApplicationLayer() 15 | 16 | fmt.Println("Packet Captured:") 17 | fmt.Printf(" Timestamp: %v\n", packet.Metadata().Timestamp) 18 | fmt.Printf(" Length: %v bytes\n\n", packet.Metadata().CaptureLength) 19 | 20 | if networkLayer != nil { 21 | fmt.Printf(" Network Layer: %v\n", networkLayer.LayerType()) 22 | fmt.Printf(" Source IP: %v\n", networkLayer.NetworkFlow().Src()) 23 | fmt.Printf(" Dest IP: %v\n\n", networkLayer.NetworkFlow().Dst()) 24 | } 25 | 26 | if transportLayer != nil { 27 | fmt.Printf(" Transport Layer: %v\n", transportLayer.LayerType()) 28 | fmt.Printf(" Source Port: %v\n", transportLayer.TransportFlow().Src()) 29 | fmt.Printf(" Dest Port: %v\n\n", transportLayer.TransportFlow().Dst()) 30 | } 31 | 32 | if applicationLayer != nil { 33 | fmt.Printf(" Application Layer: %v\n", applicationLayer.LayerType()) 34 | fmt.Printf(" Payload: %v\n\n", applicationLayer.Payload()) 35 | } 36 | } 37 | 38 | func PacketSniffer(networkInterface string) { 39 | handle, err := pcap.OpenLive(networkInterface, 1600, true, pcap.BlockForever) 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | defer handle.Close() 44 | 45 | packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) 46 | 47 | for packet := range packetSource.Packets() { 48 | printPacketInfo(packet) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/cmd/cmd.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "shell/src/helper" 6 | "shell/src/network" 7 | "shell/src/network/scanning" 8 | "shell/src/network/sniffing" 9 | "shell/src/osint" 10 | "strconv" 11 | "time" 12 | ) 13 | 14 | func Traceroute(arguments []string) { 15 | network.Traceroute(arguments[0]) 16 | } 17 | 18 | func Webheader(arguments []string) { 19 | osint.HeaderRetrieve(arguments[0]) 20 | } 21 | 22 | func PortScanner(arguments []string) { 23 | scanning.PortScanner(arguments[0]) 24 | } 25 | 26 | func Ping(arguments []string) { 27 | host, count := arguments[0], 0 28 | if len(arguments) > 1 { 29 | count, _ = strconv.Atoi(arguments[1]) 30 | } 31 | 32 | network.Ping(host, count, 2*time.Second) 33 | } 34 | 35 | func Whois(arguments []string) { 36 | osint.Getwhois(arguments[0]) 37 | } 38 | 39 | func Hash(arguments []string) { 40 | method, data := arguments[0], arguments[1] 41 | 42 | switch method { 43 | case "md5", "sha1", "sha256", "sha512": 44 | network.Hash(method, data) 45 | case "decode": 46 | fmt.Printf("Hash Algorithm: %s\n", network.DecodeHash(data)) 47 | default: 48 | helper.HandleWarn("Unsupported hash method", method) 49 | } 50 | } 51 | 52 | func ShowIP() { 53 | osint.ShowIP() 54 | } 55 | 56 | func ShowSubnet(arguments []string) { 57 | if cidr, err := strconv.Atoi(arguments[1]); !helper.HandleErr("Invalid CIDR", err) { 58 | network.ShowCalculation(arguments[0], cidr) 59 | } 60 | } 61 | 62 | func GetDNSRecords(arguments []string) { 63 | osint.GetDNSRecords(arguments[0]) 64 | } 65 | 66 | func GetIPInfo(arguments []string) { 67 | osint.GetIpInfo(arguments[0]) 68 | } 69 | 70 | func ShowSnifferPackets(arguments []string) { 71 | sniffing.PacketSniffer(arguments[0]) 72 | } 73 | -------------------------------------------------------------------------------- /src/helper/helper.go: -------------------------------------------------------------------------------- 1 | package helper 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | "runtime" 8 | "sort" 9 | "strings" 10 | ) 11 | 12 | var ( 13 | RESET = "\033[0m" 14 | ERROR = "\033[31m" 15 | WARNING = "\033[33m" 16 | ) 17 | 18 | func init() { 19 | if runtime.GOOS == "windows" { 20 | if os.Stdout == nil || os.Stdout == os.Stderr { 21 | RESET = "" 22 | ERROR = "" 23 | WARNING = "" 24 | } 25 | } 26 | } 27 | 28 | func ExtractUsername(p string) string { 29 | usernameParts := strings.Split(p, "\\") 30 | if len(usernameParts) > 1 { 31 | return usernameParts[1] 32 | } 33 | return p 34 | } 35 | 36 | func GetGitBranch(directory string) string { 37 | cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD") 38 | cmd.Dir = directory 39 | 40 | output, err := cmd.Output() 41 | if err != nil { 42 | return "" 43 | } 44 | 45 | return strings.TrimSpace(string(output)) 46 | } 47 | 48 | func MainHelp() { 49 | fmt.Println("Available Commands:") 50 | printCommandHelp("ping", "ICMP Ping", "Send ICMP echo requests to check the reachability of a host and measure round-trip times.") 51 | printCommandHelp("hash", "Hash", "Generate a cryptographic hash value for a given input.") 52 | printCommandHelp("subnet", "Subnet Calculator", "Calculate subnet details, including network and broadcast addresses, and IP ranges.") 53 | printCommandHelp("sniff", "Packet Sniffer", "Capture and analyze network packets on a specified interface.") 54 | printCommandHelp("traceroute", "Traceroute", "Reveal the network path and measure transit times of packets to a destination IP address.") 55 | printCommandHelp("scan", "Port Scanner", "Scan for open ports on a specified IP address or domain.") 56 | } 57 | 58 | func OsintHelp() { 59 | fmt.Println("Available Commands:") 60 | printCommandHelp("dig", "DNS Enumeration", "Perform DNS enumeration on a domain to gather information about its DNS records.") 61 | printCommandHelp("whois", "WHOIS Lookup", "Retrieve detailed registration information for a domain, including contact details.") 62 | printCommandHelp("lookup", "IP Lookup", "Retrieve basic information about an IP address, such as its geolocation and ISP.") 63 | printCommandHelp("webheader", "Website Header", "Retrieve basic header information via a HTTP web request") 64 | printCommandHelp("ip", "IP Addresses", "Display local and public IP addresses for the currently connected network.") 65 | } 66 | 67 | func printCommandHelp(command, title, description string) { 68 | fmt.Printf(" - %v (%v):\n\t%v\n", command, title, description) 69 | } 70 | 71 | func HandleErr(msg string, err error) bool { 72 | if err != nil { 73 | fmt.Printf(ERROR+"%v: %v\n"+RESET, msg, err) 74 | return true 75 | } 76 | return false 77 | } 78 | 79 | func HandleWarn(msg string, p string) bool { 80 | fmt.Printf(WARNING+"%v: %v\n"+RESET, msg, p) 81 | return true 82 | } 83 | 84 | func OSReadDir(root string) ([]string, error) { 85 | var files []string 86 | dirEntries, err := os.ReadDir(root) 87 | if HandleErr("", err) { 88 | return nil, err 89 | } 90 | 91 | for _, dirEntry := range dirEntries { 92 | if dirEntry.IsDir() { 93 | files = append(files, dirEntry.Name()+"/") 94 | } else { 95 | files = append(files, dirEntry.Name()) 96 | } 97 | } 98 | 99 | sort.Strings(files) 100 | 101 | return files, nil 102 | } 103 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw= 2 | github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= 3 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 4 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 5 | github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 6 | github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= 7 | github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 8 | github.com/likexian/gokit v0.25.13 h1:p2Uw3+6fGG53CwdU2Dz0T6bOycdb2+bAFAa3ymwWVkM= 9 | github.com/likexian/gokit v0.25.13/go.mod h1:qQhEWFBEfqLCO3/vOEo2EDKd+EycekVtUK4tex+l2H4= 10 | github.com/likexian/whois v1.15.1 h1:6vTMI8n9s1eJdmcO4R9h1x99aQWIZZX1CD3am68gApU= 11 | github.com/likexian/whois v1.15.1/go.mod h1:/nxmQ6YXvLz+qTxC/QFtEJNAt0zLuRxJrKiWpBJX8X0= 12 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 13 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 14 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 15 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 16 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 17 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 18 | golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= 19 | golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= 20 | golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 21 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 22 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 23 | golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= 24 | golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 25 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 26 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 27 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 28 | golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 29 | golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= 30 | golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 31 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 32 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 33 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 34 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 35 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 36 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 37 | -------------------------------------------------------------------------------- /src/osint/osint_tools.go: -------------------------------------------------------------------------------- 1 | package osint 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "net" 7 | "net/http" 8 | "os" 9 | "strings" 10 | 11 | "github.com/likexian/whois" 12 | ) 13 | 14 | func GetDNSRecords(host string) { 15 | addrs, err := net.LookupHost(host) 16 | if err != nil { 17 | fmt.Println("Error resolving A records:", err) 18 | } else { 19 | fmt.Printf("A (IPv4) addresses for %v:\n", host) 20 | for _, addr := range addrs { 21 | fmt.Println(addr) 22 | } 23 | } 24 | 25 | nsRecords, err := net.LookupNS(host) 26 | if err != nil { 27 | fmt.Println("Error resolving NS records:", err) 28 | } else { 29 | fmt.Printf("NS (Name Server) records for %v:\n", host) 30 | for _, ns := range nsRecords { 31 | fmt.Println(ns.Host) 32 | } 33 | } 34 | 35 | cname, err := net.LookupCNAME(host) 36 | if err != nil { 37 | fmt.Println("Error resolving CNAME records:", err) 38 | } else { 39 | fmt.Printf("CNAME (Canonical Name) for %v: %v\n", host, cname) 40 | } 41 | 42 | txtRecords, err := net.LookupTXT(host) 43 | if err != nil { 44 | fmt.Println("Error resolving TXT records:", err) 45 | } else { 46 | fmt.Printf("TXT (Text) records for %v:\n", host) 47 | for _, txt := range txtRecords { 48 | fmt.Println(txt) 49 | } 50 | } 51 | } 52 | 53 | func getInternalIP() (string, error) { 54 | addrs, err := net.InterfaceAddrs() 55 | if err != nil { 56 | return "", err 57 | } 58 | 59 | for _, addr := range addrs { 60 | if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { 61 | if ipnet.IP.To4() != nil { 62 | return ipnet.IP.String(), nil 63 | } 64 | } 65 | } 66 | 67 | return "", nil 68 | } 69 | 70 | func getPublicIP() (string, error) { 71 | resp, err := http.Get("https://ifconfig.co/ip") 72 | if err != nil { 73 | return "", err 74 | } 75 | defer resp.Body.Close() 76 | 77 | body, err := io.ReadAll(resp.Body) 78 | if err != nil { 79 | return "", err 80 | } 81 | 82 | publicIP := strings.TrimSpace(string(body)) 83 | return publicIP, nil 84 | } 85 | 86 | func ShowIP() { 87 | internalIP, err := getInternalIP() 88 | if err != nil { 89 | fmt.Println("Error getting internal IP:", err) 90 | } else { 91 | fmt.Println("Internal IP:", internalIP) 92 | } 93 | 94 | publicIP, err := getPublicIP() 95 | if err != nil { 96 | fmt.Println("Error getting public IP:", err) 97 | } else { 98 | fmt.Println("Public IP:", publicIP) 99 | } 100 | } 101 | 102 | const ( 103 | hostName = "ipinfo.io" 104 | port = "80" 105 | ) 106 | 107 | func GetIpInfo(host string) { 108 | path := "/" + host + "/json" 109 | url := "http://" + hostName + ":" + port + path 110 | 111 | resp, err := http.Get(url) 112 | if err != nil { 113 | fmt.Println("Error:", err) 114 | os.Exit(1) 115 | } 116 | defer resp.Body.Close() 117 | 118 | if resp.StatusCode != http.StatusOK { 119 | fmt.Printf("HTTP request failed with status code: %v\n", resp.StatusCode) 120 | os.Exit(1) 121 | } 122 | 123 | buffer := make([]byte, 4096) 124 | for { 125 | n, err := resp.Body.Read(buffer) 126 | if n > 0 { 127 | fmt.Print(string(buffer[:n])) 128 | } 129 | if err != nil { 130 | break 131 | } 132 | } 133 | } 134 | 135 | func Getwhois(host string) { 136 | result, err := whois.Whois(host) 137 | if err == nil { 138 | fmt.Println(result) 139 | } 140 | } 141 | 142 | func getWebsiteHeaders(url string) (http.Header, error) { 143 | response, err := http.Head(url) 144 | if err != nil { 145 | return nil, err 146 | } 147 | defer response.Body.Close() 148 | 149 | return response.Header, nil 150 | } 151 | 152 | func HeaderRetrieve(url string) { 153 | headers, err := getWebsiteHeaders(url) 154 | if err != nil { 155 | fmt.Printf("Error: %v\n", err) 156 | return 157 | } 158 | 159 | fmt.Printf("Headers for %v:\n", url) 160 | for key, values := range headers { 161 | fmt.Printf("%v: %v\n", key, values) 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pegasus - OS-Based Hacking Shell 2 | 3 |

4 | pegasus logo 5 |

6 | 7 | ## IMPORTANT NOTICE 8 | I want to inform you that we're transitioning the project to a full Docker setup. This move will significantly reduce our concerns, providing a more streamlined and reliable environment. Consequently, the current shell version on the main branch (4.4.2) marks the final update for this branch. 9 | 10 | 11 | - [Introduction](#introduction) 12 | - [Requirements](#requirements) 13 | - [Usage](#usage) 14 | - [Prompt Styles](#prompt-styles) 15 | - [Docker Installation](#docker-installation) 16 | - [Local Install](#local-install) 17 | - [Docker Hub Install](#docker-hub-install) 18 | - [Binary Install](#install-the-binary-recommend) 19 | - [Contribution](#contribution) 20 | - [License](#license) 21 | - [Disclaimer](#disclaimer) 22 | - [Todo](#todo) 23 | 24 | 25 | ## Introduction 26 | 27 | Pegasus is a powerful hacking shell designed for Unix-based operating systems. It provides various tools and functionalities that can be used for security testing and ethical hacking purposes. This tool is intended for educational and responsible use only. Please use it responsibly and with proper authorization. 28 | 29 | ## Requirements 30 |
31 | Linux 32 | 33 | bash install/install-pcap 34 | 35 |
36 | 37 |
38 | Windows 39 | 40 | Install [npcap](https://npcap.com/) 41 | 42 |
43 | 44 | ## Usage 45 | 46 | ### Note 47 | If you install the binary for any OS you will need to make the file a sudo binary 48 | - Linux 49 | 50 | `sudo chown root:root /path/to/your/executable` 51 | 52 | `sudo chmod u+s /path/to/your/executable` 53 | 54 | - Mac 55 | 56 | 57 | `sudo visudo` 58 | 59 | `yourusername ALL=(ALL) NOPASSWD: /path/to/your/executable` 60 | 61 | - Windows 62 | 63 | `Run as Administrator` 64 | 65 | Once Pegasus is successfully installed, you can run it by executing the `go run main.go` command in your terminal: 66 | 67 | ![Pegasus Terminal](images/recent.png) 68 | 69 | If you want a new style prompt run `./pegasus -style=` 70 | ## Prompt styles 71 | 72 | - windows 73 | - root 74 | - zsh, zsh-git 75 | - mac 76 | - hacker 77 | 78 | ## Docker installation 79 | 80 | ### Local install 81 | If you prefer to build the Docker image locally, execute the following commands: 82 | 83 | `docker build -t pegasus .` 84 | 85 | `docker run -it pegasus` 86 | 87 | ### Docker hub install (recommend for arm) 88 | For a more straightforward installation, you can pull the Docker image from Docker Hub: 89 | 90 | `docker pull nebrix/pegasus:4.4.2` 91 | 92 | `docker run -it docker.io/nebrix/pegasus:4.4.2` 93 | 94 | Using the Docker Hub image is the recommended and easier approach for most users. 95 | 96 | ## Install the binary (recommend) 97 | 98 | Download the binary [pegasus](https://github.com/Nebrix/Pegasus/releases) 99 | 100 | ## Todo 101 | 102 | - [X] Whois- [Description: Retrieve detailed registration information for a domain, including contact details] 103 | - [X] DNS - [Description: Perform DNS enumeration on a domain to gather information about its DNS records] 104 | - [X] Hashing - [Description: Generate a cryptographic hash value for a given input] 105 | - [X] IP/IP Information - [Description: Retrieve basic information about an IP address, such as its geolocation and ISP] 106 | - [X] Subnet Calculator - [Description: Calculate subnet details, including network and broadcast addresses, and IP ranges] 107 | 108 | - [X] Port Scanner - [Description: Scan for open ports on a specified IP address or domain] 109 | - [X] Packet Sniffer - [Description: Capture and analyze network packets on a specified interface] 110 | - [ ] Discover WiFi Networks - [Description: Discover networks] 111 | 112 | - [X] Ping - [Description: Send ICMP echo requests to check the reachability of a host and measure round-trip times] 113 | - [X] Traceroute - [Description: Reveal the network path and measure transit times of packets to a destination IP address] 114 | - [X] Web Header - [Description: Retrieve basic header information via an HTTP web request] 115 | - [X] IP Addresses - [Description: Display local and public IP addresses for the currently connected network] 116 | 117 | - [X] Shell Prompt Styles - [Description: Customize the style of the shell prompt] 118 | - [ ] Custom Prompt Styles - [Description: Create custom shell prompts] 119 | 120 | - [X] Install Script - [Description: Installer for libpcap (Unix only)] 121 | 122 | ## Contribution 123 | 124 | If you find any bugs or want to contribute to Pegasus, please feel free to open an issue or submit a pull request on the GitHub repository. We welcome your feedback and suggestions to make this tool even better. 125 | 126 | ## License 127 | 128 | Pegasus is open-source software licensed under the [MIT License](https://github.com/Nebrix/Pegasus/blob/main/COPYING). You are free to use, modify, and distribute this software with proper attribution and in compliance with the license terms. 129 | 130 | ## Disclaimer 131 | 132 | Pegasus is provided for educational and ethical hacking purposes only. The authors and contributors of Pegasus are not responsible for any misuse or illegal activities performed using this tool. Please use it responsibly and in compliance with the laws and regulations of your country. 133 | -------------------------------------------------------------------------------- /src/network/network_tools.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "crypto/md5" 5 | "crypto/sha1" 6 | "crypto/sha256" 7 | "crypto/sha512" 8 | "encoding/hex" 9 | "fmt" 10 | "hash" 11 | "net" 12 | "os" 13 | "time" 14 | 15 | "golang.org/x/net/icmp" 16 | "golang.org/x/net/ipv4" 17 | ) 18 | 19 | const ( 20 | md5Size = 16 * 2 21 | sha1Size = 20 * 2 22 | sha256Size = 32 * 2 23 | sha512Size = 64 * 2 24 | ) 25 | 26 | func Ping(host string, count int, timeout time.Duration) { 27 | addr, err := net.ResolveIPAddr("ip", host) 28 | if err != nil { 29 | fmt.Println(err.Error()) 30 | return 31 | } 32 | 33 | conn, err := net.DialIP("ip4:icmp", nil, addr) 34 | if err != nil { 35 | fmt.Println(err.Error()) 36 | return 37 | } 38 | defer conn.Close() 39 | 40 | for i := 1; i <= count; i++ { 41 | msg := make([]byte, 64) 42 | msg[0] = 8 43 | msg[1] = 0 44 | msg[2] = 0 45 | msg[3] = 0 46 | msg[4] = 0 47 | msg[5] = 0 48 | msg[6] = 0 49 | msg[7] = byte(i) 50 | checksum := checkSum(msg) 51 | msg[2] = byte(checksum >> 8) 52 | msg[3] = byte(checksum & 0xFF) 53 | 54 | startTime := time.Now() 55 | 56 | _, err = conn.Write(msg) 57 | if err != nil { 58 | fmt.Println(err) 59 | return 60 | } 61 | 62 | reply := make([]byte, 64) 63 | conn.SetReadDeadline(time.Now().Add(timeout)) 64 | _, err = conn.Read(reply) 65 | if err != nil { 66 | fmt.Println("Request timed out") 67 | } else { 68 | duration := time.Since(startTime) 69 | fmt.Printf("Reply from %v: time=%v\n", addr.String(), duration) 70 | } 71 | 72 | time.Sleep(1 * time.Second) 73 | } 74 | } 75 | 76 | func checkSum(msg []byte) uint16 { 77 | sum := uint32(0) 78 | for i := 0; i < len(msg); i += 2 { 79 | sum += uint32(msg[i+1]) | (uint32(msg[i]) << 8) 80 | } 81 | sum = (sum >> 16) + (sum & 0xffff) 82 | sum += (sum >> 16) 83 | return uint16(^sum) 84 | } 85 | 86 | func Hash(method, data string) { 87 | var hasher hash.Hash 88 | 89 | switch method { 90 | case "md5": 91 | hasher = md5.New() 92 | case "sha1": 93 | hasher = sha1.New() 94 | case "sha256": 95 | hasher = sha256.New() 96 | case "sha512": 97 | hasher = sha512.New() 98 | default: 99 | fmt.Printf("Unsupported hash method: %s\n", method) 100 | return 101 | } 102 | 103 | hasher.Write([]byte(data)) 104 | hash := hex.EncodeToString(hasher.Sum(nil)) 105 | fmt.Printf("%v\n", hash) 106 | } 107 | 108 | func DecodeHash(data string) string { 109 | switch len(data) { 110 | case md5Size: 111 | return "MD5" 112 | case sha1Size: 113 | return "SHA-1" 114 | case sha256Size: 115 | return "SHA-256" 116 | case sha512Size: 117 | return "SHA-512" 118 | default: 119 | return "Unknown" 120 | } 121 | } 122 | 123 | func subnetCalculator(ipAddress string, cidr int) { 124 | ip := net.ParseIP(ipAddress) 125 | if ip == nil { 126 | fmt.Println("Invalid IP address") 127 | return 128 | } 129 | 130 | if cidr < 0 || cidr > 32 { 131 | fmt.Println("Invalid CIDR") 132 | return 133 | } 134 | 135 | ipInt := ipToUint32(ip) 136 | ones, bits := cidr, 32 137 | mask := (1<>24), byte(ipInt>>16), byte(ipInt>>8), byte(ipInt)) 164 | } 165 | 166 | func ShowCalculation(host string, cidr int) { 167 | if cidr < 0 || cidr > 32 { 168 | fmt.Println("Invalid CIDR") 169 | os.Exit(1) 170 | } 171 | 172 | subnetCalculator(host, cidr) 173 | } 174 | 175 | func Traceroute(host string) { 176 | fmt.Printf("Traceroute to %v...\n", host) 177 | 178 | ipAddr, err := net.ResolveIPAddr("ip", host) 179 | if err != nil { 180 | fmt.Println("Error resolving target host:", err) 181 | os.Exit(1) 182 | } 183 | 184 | conn, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") 185 | if err != nil { 186 | fmt.Println("Error opening scoket:", err) 187 | os.Exit(1) 188 | } 189 | defer conn.Close() 190 | 191 | ttl := 1 192 | 193 | for { 194 | message := icmp.Message{ 195 | Type: ipv4.ICMPTypeEcho, 196 | Code: 0, 197 | Body: &icmp.Echo{ 198 | ID: os.Getpid() & 0xffff, 199 | Seq: ttl, 200 | Data: []byte(""), 201 | }, 202 | } 203 | 204 | messageBytes, err := message.Marshal(nil) 205 | if err != nil { 206 | fmt.Println("Error marshalling ICMP message:", err) 207 | os.Exit(1) 208 | } 209 | 210 | if err := conn.IPv4PacketConn().SetTTL(ttl); err != nil { 211 | fmt.Println("Error setting TTL:", err) 212 | os.Exit(1) 213 | } 214 | 215 | _, err = conn.WriteTo(messageBytes, ipAddr) 216 | if err != nil { 217 | fmt.Println("Error sending ICMP message:", err) 218 | os.Exit(1) 219 | } 220 | 221 | reply := make([]byte, 1500) 222 | _, _, err = conn.ReadFrom(reply) 223 | if err != nil { 224 | fmt.Println("Error receiving ICMP reply:", err) 225 | os.Exit(1) 226 | } 227 | 228 | fmt.Printf("%d. %s\n", ttl, ipAddr.String()) 229 | 230 | if ipAddr.String() == host { 231 | break 232 | } 233 | 234 | ttl++ 235 | 236 | if ttl > 30 { 237 | fmt.Println("Max hops reached. Exiting.") 238 | break 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /src/shell.go: -------------------------------------------------------------------------------- 1 | package shell 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "os/user" 8 | "path/filepath" 9 | "shell/src/cmd" 10 | "shell/src/helper" 11 | "strings" 12 | ) 13 | 14 | const ( 15 | WindowsPrompt = "windows" 16 | ZshPrompt = "zsh" 17 | ZshGitPrompt = "zsh-git" 18 | RootPrompt = "root" 19 | MacPrompt = "mac" 20 | HackerPrompt = "hacker" 21 | DefaultPrompt = "default" 22 | 23 | EscapeWindows = "%v> \033[0m" 24 | EscapeZsh = "\033[1;32m➜ \033[1;34m%v\033[0m " 25 | EscapeZshGit = "\033[1;32m➜ \033[1;34m%v \033[31m(%v)\033[0m " 26 | EscapeRoot = "%v# " 27 | EscapeMac = "%v:%v$ " 28 | EscapeHacker = "\033[32m%v=%v?\033[0m " 29 | EscapeDefault = "[%v@%v %v]$ " 30 | ) 31 | 32 | type ShellConfig struct { 33 | PromptStyle string 34 | } 35 | 36 | var ShellDefaults = ShellConfig{ 37 | PromptStyle: DefaultPrompt, 38 | } 39 | 40 | type Shell struct { 41 | UserInfo UserInfo 42 | ShellConfig ShellConfig 43 | shellName string 44 | } 45 | 46 | type UserInfo struct { 47 | Username string 48 | Directory string 49 | Hostname string 50 | Home string 51 | } 52 | 53 | type OSINTShell struct { 54 | mainShell *Shell 55 | } 56 | 57 | func NewShell(config ShellConfig) (*Shell, error) { 58 | currentUser, err := user.Current() 59 | if err != nil { 60 | return nil, fmt.Errorf("error getting current user: %v", err) 61 | } 62 | 63 | currentWorkingDir, err := os.Getwd() 64 | if err != nil { 65 | return nil, fmt.Errorf("error getting current working directory: %v", err) 66 | } 67 | 68 | hostname, err := os.Hostname() 69 | if err != nil { 70 | return nil, fmt.Errorf("error getting hostname: %v", err) 71 | } 72 | 73 | username := helper.ExtractUsername(currentUser.Username) 74 | 75 | return &Shell{ 76 | UserInfo: UserInfo{ 77 | Username: username, 78 | Directory: currentWorkingDir, 79 | Hostname: hostname, 80 | Home: currentUser.HomeDir, 81 | }, 82 | ShellConfig: config, 83 | shellName: "default", 84 | }, nil 85 | } 86 | 87 | func setPrompt(s *Shell) { 88 | switch strings.ToLower(s.ShellConfig.PromptStyle) { 89 | case WindowsPrompt: 90 | setEscapePrompt(EscapeWindows, s.UserInfo.Directory) 91 | case ZshPrompt: 92 | setEscapePrompt(EscapeZsh, filepath.Base(s.UserInfo.Directory)) 93 | case ZshGitPrompt: 94 | gitBranch := helper.GetGitBranch(s.UserInfo.Directory) 95 | setEscapePrompt(EscapeZshGit, filepath.Base(s.UserInfo.Directory), gitBranch) 96 | case RootPrompt: 97 | setEscapePrompt(EscapeRoot, filepath.Base(s.UserInfo.Directory)) 98 | case MacPrompt: 99 | setEscapePrompt(EscapeMac, s.UserInfo.Username, filepath.Base(s.UserInfo.Directory)) 100 | case HackerPrompt: 101 | setEscapePrompt(EscapeHacker, s.UserInfo.Username, filepath.Base(s.UserInfo.Directory)) 102 | default: 103 | setEscapePrompt(EscapeDefault, s.UserInfo.Username, s.UserInfo.Hostname, filepath.Base(s.UserInfo.Directory)) 104 | } 105 | } 106 | 107 | func setEscapePrompt(escapeFormat string, args ...interface{}) { 108 | fmt.Printf(escapeFormat, args...) 109 | } 110 | 111 | func (s *Shell) setOSINTPrompt() { 112 | fmt.Printf("[%v %v]$ ", s.shellName, filepath.Base(s.UserInfo.Directory)) 113 | } 114 | 115 | func (s *Shell) Start() { 116 | s.commandLine() 117 | } 118 | 119 | func (s *Shell) commandLine() { 120 | reader := bufio.NewReader(os.Stdin) 121 | helper.Ascii() 122 | 123 | for { 124 | setPrompt(s) 125 | 126 | userInput, err := reader.ReadString('\n') 127 | if handleInputError(err) { 128 | continue 129 | } 130 | 131 | args := strings.Fields(userInput) 132 | if len(args) == 0 { 133 | continue 134 | } 135 | 136 | command := args[0] 137 | arguments := args[1:] 138 | 139 | switch command { 140 | case "exit": 141 | os.Exit(0) 142 | case "cls", "clear", "Clear-Host": 143 | clearScreen() 144 | case "cd", "Set-Location": 145 | s.changeDirectory(arguments) 146 | case "ls", "dir": 147 | s.listDirectory() 148 | case "ping": 149 | cmd.Ping(arguments) 150 | case "hash": 151 | cmd.Hash(arguments) 152 | case "subnet": 153 | cmd.ShowSubnet(arguments) 154 | case "sniff": 155 | cmd.ShowSnifferPackets(arguments) 156 | case "scan": 157 | cmd.PortScanner(arguments) 158 | case "traceroute": 159 | cmd.Traceroute(arguments) 160 | case "help", "man": 161 | helper.MainHelp() 162 | case "osint": 163 | s.shellName = "osint" 164 | osintShell := newOSINTShell(s) 165 | osintShell.start() 166 | default: 167 | helper.HandleWarn("Command not found", userInput) 168 | } 169 | } 170 | } 171 | 172 | func (osintShell *OSINTShell) start() { 173 | reader := bufio.NewReader(os.Stdin) 174 | for { 175 | osintShell.mainShell.setOSINTPrompt() 176 | 177 | userInput, err := reader.ReadString('\n') 178 | if handleInputError(err) { 179 | continue 180 | } 181 | 182 | args := strings.Fields(userInput) 183 | if len(args) == 0 { 184 | continue 185 | } 186 | 187 | command := args[0] 188 | arguments := args[1:] 189 | 190 | switch command { 191 | case "exit": 192 | return 193 | case "cls", "clear", "Clear-Host": 194 | clearScreen() 195 | case "cd", "Set-Location": 196 | osintShell.mainShell.changeDirectory(arguments) 197 | case "ls", "dir": 198 | osintShell.mainShell.listDirectory() 199 | case "whois": 200 | cmd.Whois(arguments) 201 | case "ip": 202 | cmd.ShowIP() 203 | case "dig": 204 | cmd.GetDNSRecords(arguments) 205 | case "lookup": 206 | cmd.GetIPInfo(arguments) 207 | case "webheader": 208 | cmd.Webheader(arguments) 209 | case "help", "man": 210 | helper.OsintHelp() 211 | default: 212 | helper.HandleWarn("Command not found", userInput) 213 | } 214 | } 215 | } 216 | 217 | func handleInputError(err error) bool { 218 | helper.HandleErr("Error reading input", err) 219 | return false 220 | } 221 | 222 | func clearScreen() { 223 | fmt.Print("\033[H\033[2J") 224 | } 225 | 226 | func newOSINTShell(mainShell *Shell) *OSINTShell { 227 | return &OSINTShell{mainShell: mainShell} 228 | } 229 | 230 | func (s *Shell) changeDirectory(arguments []string) { 231 | newDir := arguments[0] 232 | if newDir == ".." { 233 | newDir = filepath.Dir(s.UserInfo.Directory) 234 | } 235 | 236 | if helper.HandleErr("Error changing directory", os.Chdir(newDir)) { 237 | return 238 | } 239 | 240 | s.UserInfo.Directory = newDir 241 | } 242 | 243 | func (s *Shell) listDirectory() { 244 | if files, err := helper.OSReadDir(s.UserInfo.Directory); !helper.HandleErr("Error listing directory", err) { 245 | fmt.Println(strings.Join(files, "\n")) 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/network/scanning/port_scanner.go: -------------------------------------------------------------------------------- 1 | package scanning 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "sync" 7 | "time" 8 | 9 | "github.com/go-ping/ping" 10 | ) 11 | 12 | var PortsMap = map[int]string{ 13 | 6: "zeronet", 14 | 7: "echo", 15 | 9: "WOL", 16 | 20: "ftp data", 17 | 21: "ftp control", 18 | 22: "ssh", 19 | 23: "telnet", 20 | 25: "smtp", 21 | 43: "whois", 22 | 49: "TACACS", 23 | 53: "DNS", 24 | 67: "BOOTP", 25 | 69: "TFTP", 26 | 70: "Gopher", 27 | 71: "NETRJS", 28 | 80: "http", 29 | 81: "TorPark", 30 | 82: "TorPark", 31 | 88: "Kerberos", 32 | 110: "POP3", 33 | 115: "sFTP", 34 | 143: "imap", 35 | 220: "imap3", 36 | 123: "NTP", 37 | 135: "RPC", 38 | 443: "https", 39 | 445: "Microsoft-ds, Samba", 40 | 465: "SMTP over TLS", 41 | 514: "Syslog", 42 | 520: "RIP", 43 | 521: "RIPng", 44 | 540: "UUCP", 45 | 543: "klogin", 46 | 544: "kshell", 47 | 587: "submission", 48 | 993: "IMAP over TLS", 49 | 995: "POP3 over TLS", 50 | 1433: "Microsoft SQL Server", 51 | 3306: "MySQL", 52 | 3389: "rdp", 53 | 5432: "postgres", 54 | 6667: "irc", 55 | 25565: "minecraft server", 56 | } 57 | 58 | var ( 59 | ip string 60 | hostname string 61 | err error 62 | ) 63 | 64 | func top1000ports() []int { 65 | return []int{ 66 | 1, 3, 4, 6, 7, 9, 13, 17, 19, 20, 21, 22, 23, 24, 25, 26, 30, 32, 33, 37, 42, 43, 49, 53, 70, 79, 80, 81, 82, 83, 84, 85, 88, 89, 90, 99, 100, 106, 109, 110, 111, 113, 119, 125, 135, 139, 143, 144, 146, 161, 163, 179, 199, 211, 212, 222, 254, 255, 256, 259, 264, 280, 301, 306, 311, 340, 366, 389, 406, 407, 416, 417, 425, 427, 443, 444, 445, 458, 464, 465, 481, 497, 500, 512, 513, 514, 515, 524, 541, 543, 544, 545, 548, 554, 555, 563, 587, 593, 616, 617, 625, 631, 636, 646, 648, 666, 667, 668, 683, 687, 691, 700, 705, 711, 714, 720, 722, 726, 749, 765, 777, 783, 787, 800, 801, 808, 843, 873, 880, 888, 898, 900, 901, 902, 903, 911, 912, 981, 987, 990, 992, 993, 995, 999, 1000, 1001, 1002, 1007, 1009, 1010, 1011, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1102, 1104, 1105, 1106, 1107, 1108, 1110, 1111, 1112, 1113, 1114, 1117, 1119, 1121, 1122, 1123, 1124, 1126, 1130, 1131, 1132, 1137, 1138, 1141, 1145, 1147, 1148, 1149, 1151, 1152, 1154, 1163, 1164, 1165, 1166, 1169, 1174, 1175, 1183, 1185, 1186, 1187, 1192, 1198, 1199, 1201, 1213, 1216, 1217, 1218, 1233, 1234, 1236, 1244, 1247, 1248, 1259, 1271, 1272, 1277, 1287, 1296, 1300, 1301, 1309, 1310, 1311, 1322, 1328, 1334, 1352, 1417, 1433, 1434, 1443, 1455, 1461, 1494, 1500, 1501, 1503, 1521, 1524, 1533, 1556, 1580, 1583, 1594, 1600, 1641, 1658, 1666, 1687, 1688, 1700, 1717, 1718, 1719, 1720, 1721, 1723, 1755, 1761, 1782, 1783, 1801, 1805, 1812, 1839, 1840, 1862, 1863, 1864, 1875, 1900, 1914, 1935, 1947, 1971, 1972, 1974, 1984, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013, 2020, 2021, 2022, 2030, 2033, 2034, 2035, 2038, 2040, 2041, 2042, 2043, 2045, 2046, 2047, 2048, 2049, 2065, 2068, 2099, 2100, 2103, 2105, 2106, 2107, 2111, 2119, 2121, 2126, 2135, 2144, 2160, 2161, 2170, 2179, 2190, 2191, 2196, 2200, 2222, 2251, 2260, 2288, 2301, 2323, 2366, 2381, 2382, 2383, 2393, 2394, 2399, 2401, 2492, 2500, 2522, 2525, 2557, 2601, 2602, 2604, 2605, 2607, 2608, 2638, 2701, 2702, 2710, 2717, 2718, 2725, 2800, 2809, 2811, 2869, 2875, 2909, 2910, 2920, 2967, 2968, 2998, 3000, 3001, 3003, 3005, 3006, 3007, 3011, 3013, 3017, 3030, 3031, 3052, 3071, 3077, 3128, 3168, 3211, 3221, 3260, 3261, 3268, 3269, 3283, 3300, 3301, 3306, 3322, 3323, 3324, 3325, 3333, 3351, 3367, 3369, 3370, 3371, 3372, 3389, 3390, 3404, 3476, 3493, 3517, 3527, 3546, 3551, 3580, 3659, 3689, 3690, 3703, 3737, 3766, 3784, 3800, 3801, 3809, 3814, 3826, 3827, 3828, 3851, 3869, 3871, 3878, 3880, 3889, 3905, 3914, 3918, 3920, 3945, 3971, 3986, 3995, 3998, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4045, 4111, 4125, 4126, 4129, 4224, 4242, 4279, 4321, 4343, 4443, 4444, 4445, 4446, 4449, 4550, 4567, 4662, 4848, 4899, 4900, 4998, 5000, 5001, 5002, 5003, 5004, 5009, 5030, 5033, 5050, 5051, 5054, 5060, 5061, 5080, 5087, 5100, 5101, 5102, 5120, 5190, 5200, 5214, 5221, 5222, 5225, 5226, 5269, 5280, 5298, 5357, 5405, 5414, 5431, 5432, 5440, 5500, 5510, 5544, 5550, 5555, 5560, 5566, 5631, 5633, 5666, 5678, 5679, 5718, 5730, 5800, 5801, 5802, 5810, 5811, 5815, 5822, 5825, 5850, 5859, 5862, 5877, 5900, 5901, 5902, 5903, 5904, 5906, 5907, 5910, 5911, 5915, 5922, 5925, 5950, 5952, 5959, 5960, 5961, 5962, 5963, 5987, 5988, 5989, 5998, 5999, 6000, 6001, 6002, 6003, 6004, 6005, 6006, 6007, 6009, 6025, 6059, 6100, 6101, 6106, 6112, 6123, 6129, 6156, 6346, 6389, 6502, 6510, 6543, 6547, 6565, 6566, 6567, 6580, 6646, 6666, 6667, 6668, 6669, 6689, 6692, 6699, 6779, 6788, 6789, 6792, 6839, 6881, 6901, 6969, 7000, 7001, 7002, 7004, 7007, 7019, 7025, 7070, 7100, 7103, 7106, 7200, 7201, 7402, 7435, 7443, 7496, 7512, 7625, 7627, 7676, 7741, 7777, 7778, 7800, 7911, 7920, 7921, 7937, 7938, 7999, 8000, 8001, 8002, 8007, 8008, 8009, 8010, 8011, 8021, 8022, 8031, 8042, 8045, 8080, 8081, 8082, 8083, 8084, 8085, 8086, 8087, 8088, 8089, 8090, 8093, 8099, 8100, 8180, 8181, 8192, 8193, 8194, 8200, 8222, 8254, 8290, 8291, 8292, 8300, 8333, 8383, 8400, 8402, 8443, 8500, 8600, 8649, 8651, 8652, 8654, 8701, 8800, 8873, 8888, 8899, 8994, 9000, 9001, 9002, 9003, 9009, 9010, 9011, 9040, 9050, 9071, 9080, 9081, 9090, 9091, 9099, 9100, 9101, 9102, 9103, 9110, 9111, 9200, 9207, 9220, 9290, 9415, 9418, 9485, 9500, 9502, 9503, 9535, 9575, 9593, 9594, 9595, 9618, 9666, 9876, 9877, 9878, 9898, 9900, 9917, 9929, 9943, 9944, 9968, 9998, 9999, 10000, 10001, 10002, 10003, 10004, 10009, 10010, 10012, 10024, 10025, 10082, 10180, 10215, 10243, 10566, 10616, 10617, 10621, 10626, 10628, 10629, 10778, 11110, 11111, 11967, 12000, 12174, 12265, 12345, 13456, 13722, 13782, 13783, 14000, 14238, 14441, 14442, 15000, 15002, 15003, 15004, 15660, 15742, 16000, 16001, 16012, 16016, 16018, 16080, 16113, 16992, 16993, 17877, 17988, 18040, 18101, 18988, 19101, 19283, 19315, 19350, 19780, 19801, 19842, 20000, 20005, 20031, 20221, 20222, 20828, 21571, 22939, 23502, 24444, 24800, 25734, 25735, 26214, 27000, 27352, 27353, 27355, 27356, 27715, 28201, 30000, 30718, 30951, 31038, 31337, 32768, 32769, 32770, 32771, 32772, 32773, 32774, 32775, 32776, 32777, 32778, 32779, 32780, 32781, 32782, 32783, 32784, 32785, 33354, 33899, 34571, 34572, 34573, 35500, 38292, 40193, 40911, 41511, 42510, 44176, 44442, 44443, 44501, 45100, 48080, 49152, 49153, 49154, 49155, 49156, 49157, 49158, 49159, 49160, 49161, 49163, 49165, 49167, 49175, 49176, 49400, 49999, 50000, 50001, 50002, 50003, 50006, 50300, 50389, 50500, 50636, 50800, 51103, 51493, 52673, 52822, 52848, 52869, 54045, 54328, 55055, 55056, 55555, 55600, 56737, 56738, 57294, 57797, 58080, 60020, 60443, 61532, 61900, 62078, 63331, 64623, 64680, 65000, 65129, 65389, 67 | } 68 | } 69 | 70 | func getService(port int) string { 71 | return PortsMap[port] 72 | } 73 | 74 | func measureLatency(ip string, timeout time.Duration) (time.Duration, error) { 75 | pinger, err := ping.NewPinger(ip) 76 | if err != nil { 77 | return 0, err 78 | } 79 | 80 | pinger.Timeout = timeout 81 | pinger.Count = 1 82 | 83 | startTime := time.Now() 84 | 85 | err = pinger.Run() 86 | if err != nil { 87 | return 0, err 88 | } 89 | 90 | elapsedTime := time.Since(startTime) 91 | return elapsedTime, nil 92 | } 93 | 94 | func ScanPort(ip string, port int, wg *sync.WaitGroup) { 95 | defer wg.Done() 96 | address := fmt.Sprintf("%v:%v", ip, port) 97 | conn, err := net.DialTimeout("tcp", address, time.Second) 98 | if err != nil { 99 | return 100 | } 101 | defer conn.Close() 102 | 103 | service := getService(port) 104 | fmt.Printf("%v\topen\t%v\n", port, service) 105 | } 106 | 107 | func getHostname(ip string) (string, error) { 108 | names, err := net.LookupAddr(ip) 109 | if err != nil { 110 | return "", err 111 | } 112 | 113 | if len(names) > 0 { 114 | return names[0], nil 115 | } 116 | 117 | return "", fmt.Errorf("no hostname found for %v", ip) 118 | } 119 | 120 | func PortScanner(target string) { 121 | if net.ParseIP(target) != nil { 122 | ip = target 123 | hostname, err = getHostname(target) 124 | if err != nil { 125 | fmt.Println("Error:", err) 126 | return 127 | } 128 | } else { 129 | ipAddrs, err := net.LookupHost(target) 130 | if err != nil { 131 | fmt.Println("Error:", err) 132 | return 133 | } 134 | ip = ipAddrs[0] 135 | hostname = target 136 | } 137 | 138 | timeout := 2 * time.Second 139 | portList := top1000ports() 140 | 141 | var wg sync.WaitGroup 142 | 143 | latency, err := measureLatency(ip, timeout) 144 | if err != nil { 145 | fmt.Println("Error measuring latency:", err) 146 | return 147 | } 148 | 149 | fmt.Printf("Scan report for (%v) %v\n", hostname, ip) 150 | fmt.Printf("Host is up (%v)\n", latency) 151 | fmt.Print("PORT\tSTATE\tSERIVCE\n") 152 | 153 | for _, port := range portList { 154 | wg.Add(1) 155 | go ScanPort(ip, port, &wg) 156 | } 157 | 158 | wg.Wait() 159 | } 160 | --------------------------------------------------------------------------------