├── 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 | []()
2 | [](https://github.com/SpiderLabs/HostHunter/releases)
3 | [](https://github.com/SpiderLabs/HostHunter/blob/master/LICENSE)
4 | [](https://github.com/SpiderLabs/HostHunter/issues)
5 | [](https://twitter.com/superhedgy)
6 |
7 | HostHunter v2.0
8 | ======
9 |
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 |
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 | [](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 |
--------------------------------------------------------------------------------