├── hosthunter_logo.png ├── requirements.txt ├── LICENSE ├── README.md └── hosthunter.py /hosthunter_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpiderLabs/HostHunter/HEAD/hosthunter_logo.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | validator_collection 3 | urllib3 4 | fake_useragent 5 | pyOpenSSL 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 ANDREAS GEORGIOU (@superhedgy) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Python Version](https://img.shields.io/static/v1.svg?label=Python&message=3.x&color=blue)]() 2 | [![GitHub release](https://img.shields.io/github/release/SpiderLabs/HostHunter.svg?color=orange&style=popout)](https://github.com/SpiderLabs/HostHunter/releases) 3 | [![License](https://img.shields.io/github/license/spiderlabs/hosthunter.svg)](https://github.com/SpiderLabs/HostHunter/blob/master/LICENSE) 4 | [![Issues](https://img.shields.io/github/issues/SpiderLabs/HostHunter?style=popout)](https://github.com/SpiderLabs/HostHunter/issues) 5 | [![Twitter Follow](https://img.shields.io/twitter/follow/superhedgy.svg?style=social)](https://twitter.com/superhedgy) 6 | 7 | HostHunter v2.0 8 | ====== 9 | logo 10 | A tool to efficiently discover and extract hostnames providing a large set of target IPv4 or IPv6 addresses. HostHunter utilises simple OSINT and active reconaissance techniques to map IP targets with virtual hostnames. This is especially useful for discovering the true attack surface of your organisation. 11 | Output can be generated in multiple formats including CSV, TXT or Nessus file formats. 12 | 13 | ## Demo 14 | asciicast 15 | 16 | __Click on the thumbnail above to view the demo.__ 17 | 18 | ## Installation 19 | * Tested with Python 3.10.8. 20 | 21 | ### Linux / Mac OS 22 | * Install Python dependencies. 23 | ```bash 24 | $ python3.10 -m pip install -r requirements.txt 25 | ``` 26 | 27 | ## Simple Usage Example 28 | ```bash 29 | $ python3.10 hosthunter.py 30 | ``` 31 | 32 | ```bash 33 | $ cat vhosts.csv 34 | ``` 35 | 36 | ## More Examples 37 | HostHunter Help Page 38 | ```bash 39 | $ python3.10 ./hosthunter.py -h 40 | usage: hosthunter.py [-h] [-f FORMAT] [-o OUTPUT] [-t TARGET] [-g GRAB] [-v] [-V] [-d] [targets] 41 | 42 | [?] HostHunter v2.0 - Help Page 43 | 44 | positional arguments: 45 | targets Sets the path of the target IPs file. 46 | 47 | options: 48 | -h, --help show this help message and exit 49 | -f FORMAT, --format FORMAT 50 | Choose between .CSV and .TXT output file formats. 51 | -o OUTPUT, --output OUTPUT 52 | Sets the path of the output file. 53 | -t TARGET, --target TARGET 54 | Hunt a Single IP. 55 | -g GRAB, --grab GRAB Choose which SSL ports to actively scan. Default ports: 21/tcp, 25/tcp, 443/tcp, 993/tcp, 8443/tcp 56 | -v, --verify Attempts to resolve IP Address 57 | -V, --version Displays the current version. 58 | -d, --debug Displays additional output and debugging information. 59 | 60 | Author: Andreas Georgiou (@superhedgy) 61 | ``` 62 | 63 | Run HostHunter Screen Capture module and output a Nessus file: 64 | ```bash 65 | $ python3.10 hosthunter.py --nessus -o hosts.csv 66 | ``` 67 | Display Results 68 | ```bash 69 | $ cat hosts.csv 70 | ``` 71 | View Screenshots 72 | ```bash 73 | $ open ./screen_captures/ 74 | ``` 75 | 76 | ## Features 77 | - [x] Works with Python3.10 78 | - [x] Extracts information from SSL/TLS certificates. 79 | - [x] Supports Free HackerTarget API requests. 80 | - [x] Takes Screenshots of the target applications. 81 | - [x] Validates the targets IPv4 address. 82 | - [x] Supports .txt and .csv output file formats 83 | - [x] Gathers information from HTTP headers. 84 | - [x] Verifies Internet access. 85 | - [x] Retrieves hostname values from services at 21/tcp, 25/tcp, 80/tcp and 443/tcp ports. 86 | - [x] Supports Nessus target format output. 87 | - [x] Improve output (IPs, HostNames, FQDNs) 88 | - [X] Actively pull SSL certificates from other TCP ports 89 | - [X] Select with SSL ports to target 90 | - [X] Verify discovered hostnames against target IPs 91 | - [x] Support for IPv6 92 | 93 | ## Coming Next 94 | - [ ] Pause and Resume Execution 95 | - [ ] Support for a Premium HackerTarget API key 96 | - [ ] Gather information from additional APIs 97 | 98 | ## Notes 99 | * Free APIs throttle the amount of requests per day per source IP address. 100 | 101 | ## License 102 | This project is licensed under the MIT License. 103 | 104 | ## Authors 105 | * **Andreas Georgiou** - follow me on twitter - [@superhedgy](https://twitter.com/superhedgy) 106 | 107 | ## Contribute 108 | Feel free to create a Pull Request if you have any ideas or features you would like to add. Otherwise reach me out on twitter @superhedgy. 109 | 110 | ## StarGazers 111 | Thank you for all the support & feedback! 112 | [![Stargazers over time](https://starchart.cc/SpiderLabs/HostHunter.svg)](https://starchart.cc/SpiderLabs/HostHunter) 113 | -------------------------------------------------------------------------------- /hosthunter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # 3 | # | $$ | $$ | $$ | $$ 4 | # | $$ | $$ | $$ | $$ | $$ | $$ 5 | # | $$ | $$ /$$$$$$ /$$$$$$$ /$$$$$$ | $$ | $$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ 6 | # | $$$$$$$$ /$$__ $$ /$$_____/|_ $$_/ | $$$$$$$$| $$ | $$| $$__ $$|_ $$_/ /$$__ $$ /$$__ $$ 7 | # | $$__ $$| $$ \ $$| $$$$$$ | $$ | $$__ $$| $$ | $$| $$ \ $$ | $$ | $$$$$$$$| $$ \__/ 8 | # | $$ | $$| $$__| $$ \____ $$ | $$ /$$| $$ | $$| $$__| $$| $$ | $$ | $$ /$$| $$_____/| $$ 9 | # | $$ | $$| $$$$$$/ /$$$$$$$/ | $$$$/| $$ | $$| $$$$$$/| $$ | $$ | $$$$/| $$$$$$$| $$ 10 | # |__/ |__/ \______/ |_______/ \___/ |__/ |__/ \______/ |__/ |__/ \___/ \_______/|__/ v1.5 11 | # 12 | # Author : Andreas Georgiou (@superhedgy) 13 | # Email : ageorgiou@trustwave.com 14 | # Twitter : @superhedgy 15 | # Version: v2.0 16 | # 17 | # [+] Simple Usage Example: 18 | # 19 | # $ python3.10 hosthunter.py 20 | # 21 | # $ cat vhosts.csv 22 | 23 | # Standard Python Libraries 24 | import argparse 25 | import sys 26 | import os 27 | import ssl 28 | import socket 29 | import signal 30 | import platform 31 | import ipaddress 32 | import re 33 | from datetime import datetime 34 | from time import time, sleep 35 | # External Python Libraries 36 | from validator_collection import checkers 37 | import OpenSSL 38 | import urllib3 39 | import requests 40 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 41 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 42 | 43 | # Constants 44 | __version__ = "v2.0" 45 | __author__ = "Andreas Georgiou (@superhedgy)" 46 | # Hack to make things faster 47 | socket.setdefaulttimeout(3) 48 | global appsf 49 | global vhostsf 50 | global ipv6_enabled 51 | ipv6_enabled=False 52 | regx = "
  • " 53 | pattern_url = re.compile(r"https?://(www\.)?|(/.*)?") 54 | pattern = re.compile(regx) 55 | custom_headers = { 56 | "Accept": "*/*", 57 | "Accept-Encoding": "gzip, deflate", 58 | "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8", 59 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36", 60 | } 61 | 62 | 63 | def initialise(): 64 | global args 65 | # Argument Parser 66 | parser = argparse.ArgumentParser( 67 | description='[?] HostHunter ' + __version__ + ' - Help Page', 68 | epilog="Author: " + __author__) 69 | parser.add_argument( 70 | "-f", 71 | "--format", 72 | type=str, 73 | help="Choose between .CSV, .TXT, Nessus output file formats.", 74 | default="txt") 75 | parser.add_argument( 76 | "-o", 77 | "--output", 78 | help="Sets the path of the output file.", 79 | type=str, 80 | default="") 81 | parser.add_argument("-t", "--target", help="Hunt a Single IP.") 82 | parser.add_argument( 83 | "targets", 84 | nargs='?', 85 | help="Sets the path of the target IPs file.", 86 | type=str, 87 | default="") 88 | parser.add_argument( 89 | "-g", 90 | "--grab", 91 | help="Choose which SSL ports to actively scan. Default ports: 21/tcp, 25/tcp, 443/tcp, 993/tcp, 8443/tcp", 92 | type=str, 93 | default="21,25,443,993,8443") 94 | parser.add_argument( 95 | "-v", 96 | "--verify", 97 | help="Attempts to resolve IP Address", 98 | action="store_true", 99 | default=False) 100 | parser.add_argument( 101 | "-V", 102 | "--version", 103 | help="Displays the current version.", 104 | action="store_true", 105 | default=False) 106 | parser.add_argument( 107 | "-d", 108 | "--debug", 109 | help="Displays additional output and debugging information.", 110 | action="store_true", 111 | default=False) 112 | args = parser.parse_args() 113 | 114 | if len(sys.argv) < 2: 115 | print("\n[*] Error: No Arguments provided. ") 116 | print("Example Usage: python3.10 hosthunter.py -t 8.8.8.8 -o vhosts.csv \n") 117 | exit() 118 | 119 | list_format=args.format.split(',') 120 | 121 | for type in list_format: 122 | if type.lower() != "txt" and type.lower() != "csv" and type.lower()!= "nessus" and type.lower()!= "all": 123 | print("\n[*] Error: Output File Format is not supported. Choose between 'txt' or 'csv' or 'Nessus' or all .\n") 124 | print("Example Usage: python3 hosthunter.py targets.txt -f \"txt,csv,Nessus\" \n") 125 | exit() 126 | 127 | if args.version: 128 | print("HostHunter version", __version__) 129 | print("Author:", __author__) 130 | exit() 131 | 132 | if args.target and args.targets: 133 | print( 134 | "\n[*] Error: Too many arguments! Either select single target or specify a list of targets.") 135 | print("Example Usage: python3.10 hosthunter.py -t 8.8.8.8 -o vhosts.csv\n") 136 | exit() 137 | # Targets Input File 138 | if args.targets and not os.path.exists(args.targets): 139 | print("\n[*] Error: targets file", args.targets, "does not exist.\n") 140 | exit() 141 | 142 | if os.path.exists(args.output): 143 | print( 144 | "\n[?] {} file already exists, would you like to overwrite it?".format( 145 | args.output)) 146 | answer = input("Answer with [Y]es or [N]o : ").lower() 147 | if (answer == 'yes' or answer == 'y'): 148 | pass 149 | else: 150 | exit() 151 | 152 | if ipv6_on(): 153 | global ipv6_enabled 154 | ipv6_enabled=True 155 | else: 156 | ipv6_enabled=False 157 | 158 | def read_targets(): 159 | targets = [] 160 | if args.target: 161 | targets.append(args.target) 162 | else: 163 | targets_fp = open(args.targets, "rt") # Read File 164 | for target in targets_fp: 165 | targets.append(target) 166 | targets_fp.close() 167 | return targets 168 | 169 | 170 | # Prints HostHunter Banner 171 | def display_banner(): 172 | banner = ( 173 | "\n | $$ | $$ | $$ | $$ \n" 174 | " | $$ | $$ | $$ | $$ | $$ | $$\n" 175 | " | $$ | $$ /$$$$$$ /$$$$$$$ /$$$$$$ | $$ | $$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$\n" 176 | " | $$$$$$$$ /$$__ $$ /$$_____/|_ $$_/ | $$$$$$$$| $$ | $$| $$__ $$|_ $$_/ /$$__ $$ /$$__ $$\n" 177 | " | $$__ $$| $$ \\ $$| $$$$$$ | $$ | $$__ $$| $$ | $$| $$ \\ $$ | $$ | $$$$$$$$| $$ \\__/\n" 178 | " | $$ | $$| $$__| $$ \\____ $$ | $$ /$$| $$ | $$| $$__| $$| $$ | $$ | $$ /$$| $$_____/| $$\n" 179 | " | $$ | $$| $$$$$$/ /$$$$$$$/ | $$$$/| $$ | $$| $$$$$$/| $$ | $$ | $$$$/| $$$$$$$| $$\n" 180 | " |__/ |__/ \\______/ |_______/ \\___/ |__/ |__/ \\______/ |__/ |__/ \\___/ \\_______/|__/ " + 181 | __version__ + 182 | "\n") 183 | 184 | print("%s" % banner) 185 | print("\n", "HostHunter: ", __version__) 186 | print(" Author : ", __author__) 187 | print("\n" + "|" + "-" * 100 + "|", end="\n\n") 188 | if ipv6_enabled: 189 | print("[+] IPv6 Hunting is Enabled") 190 | else: 191 | print("[!] IPv6 Hunting is Disabled") 192 | 193 | class target: 194 | def __init__(self, address): 195 | self.address = address 196 | self.hname = [] 197 | self.apps = [] 198 | self.ipv6 = False 199 | 200 | data_dict = {} 201 | 202 | 203 | # Validate Input Targets - Needs to be Replaced 204 | def validate(hostx): 205 | if not checkers.is_ipv4(hostx.address): 206 | if checkers.is_ipv6(hostx.address): 207 | hostx.ipv6 = True 208 | return True 209 | else: 210 | print( 211 | "\n[*] \"", 212 | hostx.address, 213 | "\" is not a valid IPv4/IPv6 address and will be ignored.") 214 | return False 215 | else: 216 | return True 217 | 218 | 219 | ## sslGrabber - IPv6 220 | def sslGrabber6(hostx,port): 221 | context = ssl.create_default_context() 222 | context.check_hostname = False 223 | context.verify_mode = ssl.CERT_OPTIONAL 224 | context.load_default_certs() 225 | conn = context.wrap_socket(socket.socket(socket.AF_INET6), server_hostname=hostx.address) 226 | conn.connect((hostx.address, port)) 227 | cert = conn.getpeercert() 228 | return cert['subjectAltName'][0][1] 229 | 230 | 231 | # sslGrabber Function 232 | def sslGrabber(hostx, port): 233 | 234 | try: 235 | cert = ssl.get_server_certificate((hostx.address, port)) 236 | x509 = OpenSSL.crypto.load_certificate( 237 | OpenSSL.crypto.FILETYPE_PEM, cert) 238 | cert_hostname = x509.get_subject().CN 239 | # Get SAN 240 | alt_names = [] 241 | for i in range(0, x509.get_extension_count()): 242 | ext = x509.get_extension(i) 243 | if "subjectAltName" in str(ext.get_short_name()): 244 | content = ext.__str__() 245 | for alt_name in content.split(","): 246 | alt_names.append(alt_name.strip()[4:]) 247 | 248 | # Add New HostNames to List 249 | if cert_hostname: 250 | for host in cert_hostname.split('\n'): 251 | if (host == "") or (host in hostx.hname): 252 | pass 253 | else: 254 | if args.debug == True: 255 | print(host) 256 | try: 257 | host = host.replace('*.', '') 258 | finally: 259 | hostx.hname.append(host) 260 | for alt_name in alt_names: 261 | if (alt_name not in hostx.hname): 262 | hostx.hname.append(alt_name) 263 | except (urllib3.exceptions.ReadTimeoutError, 264 | requests.ConnectionError, 265 | urllib3.connection.ConnectionError, 266 | urllib3.exceptions.MaxRetryError, 267 | urllib3.exceptions.ConnectTimeoutError, 268 | urllib3.exceptions.TimeoutError, 269 | socket.error, socket.timeout): 270 | pass 271 | 272 | 273 | # analyze_header Function 274 | def analyze_header(header, hostx): 275 | try: 276 | r2 = requests.get("http://" + hostx.address, 277 | allow_redirects=False, 278 | headers=custom_headers, timeout=5).text 279 | r2.close() 280 | if (r2.status_code in range(300, 400)): 281 | try: 282 | webapp = (r2.headers['Location']) 283 | hostx.apps.append(webapp) 284 | hn = pattern_url.sub('', webapp) 285 | 286 | if hn not in hostx.hname: 287 | hostx.hname.append(hn) 288 | except BaseException: 289 | return 290 | except BaseException: 291 | return 292 | 293 | 294 | # queryAPI Function 295 | def queryAPI(url, hostx): 296 | try: 297 | r2 = requests.get(url + hostx.address, custom_headers).text 298 | if (r2.find("No DNS A records found") == - 299 | 1) and (r2.find("API count exceeded") == - 300 | 1 and r2.find("error") == - 301 | 1): 302 | for host in r2.split('\n'): 303 | if (host == "") or (host in hostx.hname): 304 | pass 305 | else: 306 | hostx.hname.append(host) 307 | # Add API count exceed detection 308 | else: 309 | pass 310 | except (requests.exceptions.ConnectionError, 311 | urllib3.connection.ConnectionError, 312 | urllib3.exceptions.ConnectTimeoutError, 313 | urllib3.exceptions.MaxRetryError, 314 | urllib3.exceptions.TimeoutError, socket.error, socket.timeout): 315 | print("\n[*] Error: connecting with HackerTarget.com API") 316 | finally: 317 | sleep(0.5) 318 | 319 | 320 | def reverseiplookup(hostx): 321 | try: 322 | rhostname = socket.gethostbyaddr(hostx.address)[0] 323 | except socket.error: 324 | return 325 | if (rhostname not in hostx.hname): 326 | hostx.hname.append(rhostname) 327 | return 328 | 329 | 330 | # Capture SIGINT 331 | def sig_handler(signal, frame): 332 | print("\n[!] HostHunter is shutting down!") 333 | try: 334 | driver.close() 335 | driver.quit() 336 | signal.pause() 337 | except BaseException: 338 | pass 339 | print("\n[!] See you soon...\n") 340 | sys.exit(0) 341 | 342 | 343 | # Write Function 344 | def write_results(): 345 | base_path="" 346 | list_format=args.format.split(',') 347 | list_format=[format_type.lower() for format_type in list_format] 348 | # Output File Naming & Path 349 | if not args.output: 350 | base_path = "hh_"+ datetime.now().strftime("%d_%m_%Y-%H.%M.%S") 351 | appsf = open(args.output+base_path+".webapps", "wt") # Write File 352 | vhostsf = open(args.output+base_path+".vhosts", "wt") 353 | vhostsf_csv = open(args.output+base_path+".vhosts.csv", "wt") 354 | nessusf = open(args.output+base_path+".nessus", 'wt') 355 | 356 | for format in list_format: 357 | match format: 358 | case "csv": 359 | # Write Header in CSV File 360 | vhostsf_csv.write( 361 | "\"" + 362 | "IP Address" + 363 | "\",\"" + 364 | "Port/Protocol" + 365 | "\",\"" + 366 | "Domains" + 367 | "\",\"" + 368 | "Operating System" + 369 | "\",\"" + 370 | "OS Version" + 371 | "\",\"" + 372 | "Notes" + 373 | "\"\n") # vhosts.csv Header 374 | # Merging the lists prooved Faster than list iterations 375 | for item in data_dict: 376 | for host in data_dict[item].hname: 377 | hostnames = ','.join(data_dict[item].hname) 378 | row = "\"" + data_dict[item].address + "\"," + "\"443/tcp\"" + \ 379 | "," + "\"" + hostnames + "\",\"\",\"\",\"\"" + "\n" 380 | vhostsf_csv.write(row) 381 | case "nessus": 382 | # Nessus Function - Generates IP/Hostname pairs in Nessus tool format. 383 | for item in data_dict: 384 | for host in data_dict[item].hname: 385 | row = host + "[" + data_dict[item].address + "], " 386 | nessusf.write(row) 387 | if not data_dict[item].hname: 388 | nessusf.write(data_dict[item].address) 389 | nessusf.close() 390 | 391 | case "txt": 392 | for item in data_dict: 393 | for hname in data_dict[item].hname: 394 | vhostsf.write(hname + "\n") 395 | vhostsf.close() 396 | 397 | # Write Results in TXT File 398 | for item in data_dict: 399 | #print(data_dict[item].address) 400 | 401 | 402 | if (data_dict[item].apps): 403 | apps = ','.join(data_dict[item].apps) 404 | row = "\"" + data_dict[item].address 405 | + "\"," + "\"" + apps + "\"" + "\n" 406 | appsf.write(row) 407 | # Write Results in HTML File 408 | 409 | 410 | # stats Function - Prints Statistics cause metrics are fun 411 | def stats(start_time,counter,target_list): 412 | print("\n" + "|" + "-" * 100 + "|", end="\n\n") 413 | print(" Hunting Completed!", end="\n\n") 414 | print(" Searched against",len(target_list),"targets",end="\n\n") 415 | if counter == 0: 416 | print(" 0 hostname was discovered in %s sec" % 417 | (round(time() - start_time, 2)), end="\n\n") 418 | else: 419 | print(" %s hostnames were discovered in %s sec" % 420 | (counter, round(time() - start_time, 2)), end="\n\n") 421 | print("|" + "-" * 100 + "|") 422 | 423 | # verify Function - Attempts to Verify Target IP Matches Hostname 424 | def verify(hostx): 425 | for item in hostx.hname: 426 | try: 427 | resolved = socket.gethostbyname_ex(item) 428 | if hostx.address in resolved[2]: 429 | print(item) 430 | except: 431 | continue 432 | 433 | return len(hostx.hname) 434 | 435 | def ipv6_on(): 436 | try: 437 | # Create a socket for IPv6 and connect to ipv6.google.com on port 80 438 | sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) 439 | sock.connect(("ipv6.google.com", 443)) 440 | return True 441 | except socket.error: 442 | return False 443 | finally: 444 | sock.close() 445 | 446 | # Main Function 447 | def main(argc, targets): 448 | counter = 0 449 | ports=args.grab.split(',') 450 | 451 | if args.debug == True: 452 | print("[!] Debug Mode: ON") 453 | 454 | for ip in targets: 455 | hostx = target(ip.replace("\n", "")) 456 | 457 | if validate(hostx): 458 | print("\n[+] Target: %s" % hostx.address) 459 | else: 460 | continue 461 | # Reverse DNS Lookup 462 | reverseiplookup(hostx) 463 | 464 | if ipv6_enabled==True & hostx.ipv6==True: 465 | sslGrabber6(hostx,443) 466 | 467 | # Fetch SSL Certificates [Default: 21, 25, 443, 993, 8443] 468 | for port in ports: 469 | sslGrabber(hostx, port) 470 | 471 | # Check 80/tcp over HTTP 472 | analyze_header("Location", hostx) 473 | 474 | # Querying HackerTarget.com API 475 | queryAPI("https://api.hackertarget.com/reverseiplookup/?q=", hostx) 476 | 477 | if hostx.hname: 478 | if args.verify: 479 | counter = verify(hostx) 480 | else: 481 | print("[+] Hostnames: ") 482 | for item in hostx.hname: 483 | print(item) 484 | counter += 1 485 | 486 | else: 487 | print("[-] Hostnames: no results") 488 | continue 489 | 490 | if (hostx.apps): 491 | print("[+] Web Apps:") 492 | for url in hostx.apps: 493 | print(url) 494 | 495 | data_dict["hostx.address"] = hostx 496 | # END FOR LOOP 497 | # END IF 498 | 499 | write_results() 500 | return counter 501 | # End of Main Function 502 | 503 | 504 | # Main Module 505 | if __name__ == "__main__": 506 | signal.signal(signal.SIGINT, sig_handler) # Signal Listener 507 | start_time = time() # Start Counter 508 | initialise() # Input Argument Checks 509 | display_banner() # Banner 510 | targets = read_targets() 511 | counter = main(sys.argv,targets) # Main Function 512 | stats(start_time,counter,targets) 513 | # EOF 514 | --------------------------------------------------------------------------------