2
# -*- coding: utf-8 -*-
5
# Copyright (C) 2011 Filip Szymański <f.szymanski@hotmail.com>
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
20
# For help run 'python quickrecon.py'
22
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
24
# Please note that this tool was created and published for educational purposes only.
26
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
39
buffer = StringIO.StringIO()
42
****************************
44
* Coded by Filip Szymański *
45
* f.szymanski@hotmail.com *
46
* remastered by josephmills*
47
****************************
49
Usage: quickrecon [options]
51
-m, --mode= {s, z, e, r} Working mode.
53
s Bruteforce subdomains.
55
e Gather email addresses from Google and Bing.
56
r Find human relationships using XHTML Friends Network.
58
-d, --domain= Domain name.
60
-l, --limit= Google and Bing search limit (default = 50).
61
-i, --input= Input file.
62
-o, --output= Output file.
64
Examples: quickrecon.py -m s -d example.com -o out.log
65
quickrecon.py -m s -d example.com -i your_subdomains.txt
66
quickrecon.py -m z -d example.com
67
quickrecon.py -m e -d example.com -o emails.log
68
quickrecon.py -m e -d example.com -l 200
69
quickrecon.py -m r -u http://blog.example.com/
72
def find_subdomains(ifile):
78
file = open(ifile, 'r')
80
print 'No such file or directory: \'%s\'.' % ifile
83
print ' / SUBDOMAIN: /\n'
84
buffer.write(' / SUBDOMAIN: /\n\n')
86
for line in file.readlines():
87
sub = line.rstrip('\n')
88
subdomain = sub + '.' + domain
90
ip = socket.gethostbyname(subdomain)
92
# reverse = socket.gethostbyaddr(ip)
93
print subdomain #, ip, reverse[0]
94
buffer.write(subdomain + '\n')
98
print '\n Found %s subdomain(s).' % found
99
buffer.write('\n Found ' + str(found) + ' subdomain(s).\n')
105
charset = 'abcdefghijklmnopqrstuvwxyz0123456789'
107
for count in range(3):
108
rcharset = random.sample(charset, random.randint(6, 12))
109
rsub = ''.join(rcharset)
110
rsubdomain = rsub + '.' + domain
111
container.append(rsubdomain)
113
for tsubdomain in container:
115
conn = httplib.HTTPConnection(tsubdomain)
116
conn.putrequest('GET', '/')
117
conn.putheader('User-Agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)')
119
response = conn.getresponse()
121
scode.append(response.status)
126
print 'The target domain has a DNS wildcard configuration.'
135
print 'Please install \'dnspython\' from http://www.dnspython.org/.'
141
print ' / ZONE TRANSFER: /\n'
142
buffer.write(' / ZONE TRANSFER: /\n\n')
145
nsrecords = dns.resolver.query(domain, 'NS')
146
except dns.resolver.NXDOMAIN:
147
print ' Zone transfer is not possible.'
148
buffer.write(' Zone transfer is not possible.\n')
151
for server in nsrecords:
152
ns.append(str(server))
156
zt = dns.zone.from_xfr(dns.query.xfr(target.rstrip('.'), domain))
157
names = zt.nodes.keys()
160
data += zt[name].to_text(name)
161
print re.sub(' ', ' ', zt[name].to_text(name))
162
buffer.write(re.sub(' ', ' ', zt[name].to_text(name)) + '\n')
167
print ' Zone transfer is not possible.'
168
buffer.write(' Zone transfer is not possible.\n')
170
def generate_urls(limit):
175
for ngoogle in range(0, limit, 10):
176
urls.append('http://www.google.com/search?hl=en&ie=UTF-8&num=10&q=%40' + domain + '&start=' + str(ngoogle))
177
urls.append('http://groups.google.com/groups?hl=en&ie=UTF-8&num=10&q=%40' + domain + '&start=' + str(ngoogle))
179
for nbing in range(1, limit + 1, 10):
180
urls.append('http://www.bing.com/search?q=%40' + domain + '&go=&count=10&first=' + str(nbing))
182
def find_emails(urls):
183
patterns = [re.compile('[\w.]+@' + string + domain) for string in ['<b>', '<strong>']]
186
print ' / EMAIL: /\n'
187
buffer.write(' / EMAIL: /\n\n')
191
request = urllib2.Request(url)
192
request.add_header('User-agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)')
193
response = urllib2.urlopen(request)
194
data = response.read()
195
for pattern in patterns:
196
rawemails = re.findall(pattern, data)
197
for email in rawemails:
198
uemail = re.sub('<b>|<strong>', '', email)
200
except httplib.IncompleteRead:
201
print 'Error while reading data. Try again.'
204
for key in results.keys():
206
buffer.write(key + '\n')
208
print '\n Found %s email(s).' % str(len(results))
209
buffer.write('\n Found ' + str(len(results)) + ' email(s).\n')
211
def find_human_relationships(url):
216
print 'Please install \'BeautifulSoup\' from http://www.crummy.com/software/BeautifulSoup/.'
221
'friend', 'acquaintance', 'contact', 'met', 'co-worker', 'colleague',
222
'co-resident', 'neighbor', 'child', 'parent', 'sibling', 'spouse',
223
'kin', 'muse', 'crush', 'date', 'sweetheart', 'me'
226
print ' / RESULT: /\n'
227
buffer.write(' / RESULT: /\n\n')
230
response = urllib2.urlopen(url)
232
print 'Connection problem. Try again.'
236
rawdata = BeautifulSoup.BeautifulSoup(response)
237
except HTMLParser.HTMLParseError:
238
print 'Error while reading data. Try again.'
241
data = rawdata.findAll('a')
244
for value in xfn_values:
245
if item.has_key('rel') and re.search(value, item['rel']) != None:
246
results[item.string] = item['href'], item['rel']
248
if len(results) == 0:
249
print ' Nothing found.'
250
buffer.write(' Nothing found.\n')
252
for key, val in results.items():
254
buffer.write('NAME: ' + key + '\n')
255
print 'URL: ' + val[0]
256
buffer.write('URL: ' + val[0] + '\n')
257
print 'RELATIONSHIP: ' + re.sub(' ', ', ', val[1]) + '\n'
258
buffer.write('RELATIONSHIP: ' + re.sub(' ', ', ', val[1]) + '\n\n')
260
def save_output(ofile):
262
log = open(ofile, 'w')
264
print 'No such directory: \'%s\'.' % os.path.dirname(ofile)
267
log.write('# Logfile: ' + time.strftime('%a, %d %b %Y, %H:%M:%S\n\n'))
268
log.write(buffer.getvalue())
276
ifile = 'subdomain.plugin'
279
if len(sys.argv) < 2:
284
options, arguments = getopt.getopt(argv, 'm:d:u:l:i:o:', ['mode=', 'domain=', 'url=', 'limit=', 'input=', 'output='])
285
except getopt.GetoptError:
286
print 'Option not recognized. Try again.'
289
for option, argument in options:
290
if option in ('-m', '--mode'):
292
elif option in ('-d', '--domain'):
293
domain = str(argument)
294
elif option in ('-u', '--url'):
296
elif option in ('-l', '--limit'):
297
limit = int(argument)
298
elif option in ('-i', '--input'):
299
ifile = str(argument)
300
elif option in ('-o', '--output'):
301
ofile = str(argument)
305
find_subdomains(ifile)
312
find_human_relationships(url)
314
print 'Mode not recognized. Try again.'
317
except UnboundLocalError:
318
print 'Please select working mode.'
325
if __name__ == '__main__':
328
except KeyboardInterrupt:
329
print '\nInterrupted by user...'