Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 202 lines (164 sloc) 6.73 KB
#!/usr/bin/env python
"""
findvhosts 0.9.6 / 2012 by mitchell <mitchell@csc.bg>.
"""
# Copyright (c) 2012, Cyber Security Consulting, Ltd. (csc.bg)
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of the nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import requests
import json
import sys
import re
import dns.zone, dns.query, dns.resolver
import argparse
import lxml.html
import urllib, urllib2
API_ID = ''
API_URL = 'https://api.datamarket.azure.com/Data.ashx/Bing/Search/v1/Web?Query=%27ip:'
API_PARAMS = '%27&$format=json&$top=500'
ewhois_email = ''
ewhois_pass = ''
def get_Options():
"""Parses the command line options."""
parser = argparse.ArgumentParser()
parser.add_argument('address', help="address can be a domain name or an IP address", type=str)
args = parser.parse_args()
return args.address
def exit(error = ""):
"""Exists with a custom error message"""
print error
sys.exit()
def unique(seq):
"""Returns a sorted and uniqued list"""
set = {}
map(set.__setitem__, seq, [])
return sorted(set.keys())
def host_Resolve(host_name):
"""Returns the IP addresses for a hostname."""
ip_addresses = []
try:
a_records = dns.resolver.query(host_name, 'A')
except(dns.resolver.NXDOMAIN):
ip_addresses.append(host_name)
return ip_addresses
for ipaddr in a_records:
ip_addresses.append(ipaddr.to_text(ipaddr))
return ip_addresses
def zone_Transfer(domain_name):
"""Attempts to get the DNS Zone for a domain name."""
name_servers = []
records = []
try:
nservers = dns.resolver.query(domain_name, 'NS')
except(dns.resolver.NXDOMAIN):
exit("Cannot resolve the domain.")
except(dns.resolver.NoAnswer):
exit("Cannot get the NS records.")
print "==> Getting the name servers..."
for nserver in nservers:
name_servers.append(nserver)
print nserver
print "\n==> Attempting zone transfer...\n"
for i in name_servers:
print "--> Using %s" % (i)
try:
ztransfer = dns.zone.from_xfr(dns.query.xfr(str(i), domain_name))
for res in ztransfer:
record = str(res) + '.' +domain_name
records.append(record.replace('@.', ''))
for r in unique(records):
ip = host_Resolve(r)
print "%s: %s" % (r, ip)
except:
print "** Cannot perform zone transfer. **\n"
pass
def bing_Search(ip_address):
"""Get domain names for the IP address from Bing."""
print "\n==> Enumerating virtual hosts on %s using Bing...\n" % (ip_address)
domain_list = []
dom = requests.get(API_URL + ip_address + API_PARAMS, auth=(API_ID, API_ID)).json
for url in dom['d']['results']:
if not 'https:' in url['DisplayUrl']:
domain_list.append(url['DisplayUrl'].encode('utf-8', 'ignore').split('/')[0])
for site in unique(domain_list):
print site
def sameip_Search(ip_address):
"""Get domains names for the IP address from sameip.org."""
print "\n==> Enumerating virtual hosts on %s using SameIP...\n" % (ip_address)
url = 'http://sameip.org/ip/%s' % (ip_address)
page = urllib2.urlopen(url)
doc = lxml.html.document_fromstring(page.read())
for col in doc.cssselect('td'):
if '.' in col.text.strip():
print col.text.strip()
def ewhois_Get_Domains(username, password, ip_address):
"""Returns a list of ewhois domains."""
print "\n==> Enumerating virtual hosts on %s using ewhois...\n" % (ip_address)
login_url = 'http://www.ewhois.com/login/'
cookies = urllib2.HTTPCookieProcessor()
opener = urllib2.build_opener(cookies)
urllib2.install_opener(opener)
opener.open(login_url)
params = {'data[User][email]':username, 'data[User][password]':password}
encoded_params = urllib.urlencode(params)
p = opener.open(login_url, encoded_params).read()
opener.close()
export_url = 'http://www.ewhois.com/export/ip-address/' + ip_address + '/'
r = urllib2.urlopen(export_url)
data = r.read()
for i in data.strip().split('\n')[1:]:
if not 'No records' in i:
print i.split('"')[1]
else:
print i
def main():
ip_match = "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
dname = get_Options()
a_match = re.search(ip_match, dname)
ips = host_Resolve(dname)
if a_match:
print "\n==> Option is an IP address\n"
else:
for ip in ips:
print "\n==> Resolving the domain name..."
print "%s resolves to %s" % (dname, ip)
print
zone_Transfer(dname)
for ip in ips:
if API_ID:
bing_Search(str(ip))
else:
print "If you want to use Bing, enter your API Key in the script."
sameip_Search(str(ip))
if ewhois_email and ewhois_pass:
ewhois_Get_Domains(ewhois_email, ewhois_pass, ip)
else:
print "\nIf you want to use ehois, enter your ewhois.com username (email) and password in the script."
print
if __name__ == '__main__':
main()