~josephjamesmills/+junk/quickrecon

« back to all changes in this revision

Viewing changes to usr/sbin/quickrecon.py

  • Committer: Joseph Mills
  • Date: 2012-06-10 20:09:38 UTC
  • Revision ID: josephjamesmills@gmail.com-20120610200938-xuax26tsa54cbae1
1st build

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
# -*- coding: utf-8 -*-
 
3
#
 
4
# QuickRecon v0.2.3
 
5
# Copyright (C) 2011 Filip Szymański <f.szymanski@hotmail.com>
 
6
#
 
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.
 
11
#
 
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.
 
16
#
 
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/>.
 
19
#
 
20
# For help run 'python quickrecon.py'
 
21
#
 
22
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
23
#
 
24
# Please note that this tool was created and published for educational purposes only.
 
25
#
 
26
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
27
 
 
28
import getopt
 
29
import httplib
 
30
import os
 
31
import random
 
32
import re
 
33
import socket
 
34
import StringIO
 
35
import sys
 
36
import time
 
37
import urllib2
 
38
 
 
39
buffer = StringIO.StringIO()
 
40
 
 
41
usage = u'''
 
42
 ****************************
 
43
 * QuickRecon v0.2.3        *
 
44
 * Coded by Filip Szymański *
 
45
 * f.szymanski@hotmail.com  *
 
46
 * remastered by josephmills*
 
47
 ****************************
 
48
 
 
49
 Usage: quickrecon [options]
 
50
 
 
51
                      -m, --mode= {s, z, e, r}   Working mode.
 
52
 
 
53
                                        s        Bruteforce subdomains.
 
54
                                        z        Zone transfer.
 
55
                                        e        Gather email addresses from Google and Bing.
 
56
                                        r        Find human relationships using XHTML Friends Network.
 
57
 
 
58
                      -d, --domain=              Domain name.
 
59
                      -u, --url=                 Blogs url.
 
60
                      -l, --limit=               Google and Bing search limit (default = 50).
 
61
                      -i, --input=               Input file.
 
62
                      -o, --output=              Output file.
 
63
 
 
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/
 
70
                        '''
 
71
 
 
72
def find_subdomains(ifile):
 
73
        test_wildcard()
 
74
 
 
75
        found = 0
 
76
 
 
77
        try:
 
78
                file = open(ifile, 'r')
 
79
        except IOError:
 
80
                print 'No such file or directory: \'%s\'.' % ifile
 
81
                sys.exit(2)
 
82
 
 
83
        print ' / SUBDOMAIN: /\n'
 
84
        buffer.write(' / SUBDOMAIN: /\n\n')
 
85
 
 
86
        for line in file.readlines():
 
87
                sub = line.rstrip('\n')
 
88
                subdomain = sub + '.' + domain
 
89
                try:
 
90
                        ip = socket.gethostbyname(subdomain)
 
91
                        found = found + 1
 
92
                #       reverse = socket.gethostbyaddr(ip)
 
93
                        print subdomain #, ip, reverse[0]
 
94
                        buffer.write(subdomain + '\n')
 
95
                except:
 
96
                        pass
 
97
 
 
98
        print '\n  Found %s subdomain(s).' % found
 
99
        buffer.write('\n  Found ' + str(found) + ' subdomain(s).\n')
 
100
 
 
101
 
 
102
def test_wildcard():
 
103
        container = []
 
104
        scode = []
 
105
        charset = 'abcdefghijklmnopqrstuvwxyz0123456789'
 
106
 
 
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)
 
112
 
 
113
        for tsubdomain in container:
 
114
                try:
 
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)')
 
118
                        conn.endheaders()
 
119
                        response = conn.getresponse()
 
120
                #       print response.msg
 
121
                        scode.append(response.status)
 
122
                except:
 
123
                        pass
 
124
 
 
125
        if len(scode) > 0:
 
126
                print 'The target domain has a DNS wildcard configuration.'
 
127
                sys.exit(1)
 
128
 
 
129
def zone_transfer():
 
130
        try:
 
131
                import dns.resolver
 
132
                import dns.query
 
133
                import dns.zone
 
134
        except ImportError:
 
135
                print 'Please install \'dnspython\' from http://www.dnspython.org/.'
 
136
                sys.exit(2)
 
137
 
 
138
        ns = []
 
139
        data = ''
 
140
 
 
141
        print ' / ZONE TRANSFER: /\n'
 
142
        buffer.write(' / ZONE TRANSFER: /\n\n')
 
143
 
 
144
        try:
 
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')
 
149
                return
 
150
 
 
151
        for server in nsrecords:
 
152
                ns.append(str(server))
 
153
 
 
154
        for target in ns:
 
155
                try:
 
156
                        zt = dns.zone.from_xfr(dns.query.xfr(target.rstrip('.'), domain))
 
157
                        names = zt.nodes.keys()
 
158
                        names.sort()
 
159
                        for name in names:
 
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')
 
163
                except:
 
164
                        pass
 
165
 
 
166
        if data == '':
 
167
                print '  Zone transfer is not possible.'
 
168
                buffer.write('  Zone transfer is not possible.\n')
 
169
 
 
170
def generate_urls(limit):
 
171
        global urls
 
172
 
 
173
        urls = []
 
174
 
 
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))
 
178
 
 
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))
 
181
 
 
182
def find_emails(urls):
 
183
        patterns = [re.compile('[\w.]+@' + string + domain) for string in ['<b>', '<strong>']]
 
184
        results = {}
 
185
 
 
186
        print ' / EMAIL: /\n'
 
187
        buffer.write(' / EMAIL: /\n\n')
 
188
 
 
189
        for url in urls:
 
190
                try:
 
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)
 
199
                                        results[uemail] = 1
 
200
                except httplib.IncompleteRead:
 
201
                        print 'Error while reading data. Try again.'
 
202
                        sys.exit(2)
 
203
 
 
204
        for key in results.keys():
 
205
                print key
 
206
                buffer.write(key + '\n')
 
207
 
 
208
        print '\n  Found %s email(s).' % str(len(results))
 
209
        buffer.write('\n  Found ' + str(len(results)) + ' email(s).\n')
 
210
 
 
211
def find_human_relationships(url):
 
212
        import HTMLParser
 
213
        try:
 
214
                import BeautifulSoup
 
215
        except ImportError:
 
216
                print 'Please install \'BeautifulSoup\' from http://www.crummy.com/software/BeautifulSoup/.'
 
217
                sys.exit(2)
 
218
 
 
219
        results = {}
 
220
        xfn_values = [
 
221
                                        'friend', 'acquaintance', 'contact', 'met', 'co-worker', 'colleague',
 
222
                                        'co-resident', 'neighbor', 'child', 'parent', 'sibling', 'spouse',
 
223
                                        'kin', 'muse', 'crush', 'date', 'sweetheart', 'me'
 
224
                                        ]
 
225
 
 
226
        print ' / RESULT: /\n'
 
227
        buffer.write(' / RESULT: /\n\n')
 
228
 
 
229
        try:
 
230
                response = urllib2.urlopen(url)
 
231
        except:
 
232
                print 'Connection problem. Try again.'
 
233
                sys.exit(2)
 
234
 
 
235
        try:
 
236
                rawdata = BeautifulSoup.BeautifulSoup(response)
 
237
        except HTMLParser.HTMLParseError:
 
238
                print 'Error while reading data. Try again.'
 
239
                sys.exit(2)
 
240
 
 
241
        data = rawdata.findAll('a')
 
242
 
 
243
        for item in data:
 
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']
 
247
 
 
248
        if len(results) == 0:
 
249
                print '  Nothing found.'
 
250
                buffer.write('  Nothing found.\n')
 
251
        else:
 
252
                for key, val in results.items():
 
253
                        print 'NAME:          ' + key
 
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')
 
259
 
 
260
def save_output(ofile):
 
261
        try:
 
262
                log = open(ofile, 'w')
 
263
        except IOError:
 
264
                print 'No such directory: \'%s\'.' % os.path.dirname(ofile)
 
265
                sys.exit(2)
 
266
 
 
267
        log.write('# Logfile: ' + time.strftime('%a, %d %b %Y, %H:%M:%S\n\n'))
 
268
        log.write(buffer.getvalue())
 
269
        log.close()
 
270
 
 
271
 
 
272
def main(argv):
 
273
        global domain
 
274
 
 
275
        limit = 50
 
276
        ifile = 'subdomain.plugin'
 
277
        ofile = None
 
278
 
 
279
        if len(sys.argv) < 2:
 
280
                print usage
 
281
                sys.exit(1)
 
282
 
 
283
        try:
 
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.'
 
287
        #       print usage
 
288
                sys.exit(2)
 
289
        for option, argument in options:
 
290
                if option in ('-m', '--mode'):
 
291
                        mode = str(argument)
 
292
                elif option in ('-d', '--domain'):
 
293
                        domain = str(argument)
 
294
                elif option in ('-u', '--url'):
 
295
                        url = str(argument)
 
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)
 
302
 
 
303
        try:
 
304
                if mode == 's':
 
305
                        find_subdomains(ifile)
 
306
                elif mode == 'z':
 
307
                        zone_transfer()
 
308
                elif mode == 'e':
 
309
                        generate_urls(limit)
 
310
                        find_emails(urls)
 
311
                elif mode == 'r':
 
312
                        find_human_relationships(url)
 
313
                else:
 
314
                        print 'Mode not recognized. Try again.'
 
315
                #       print usage
 
316
                        sys.exit(1)
 
317
        except UnboundLocalError:
 
318
                print 'Please select working mode.'
 
319
        #       print usage
 
320
                sys.exit(2)
 
321
 
 
322
        if ofile != None:
 
323
                save_output(ofile)
 
324
 
 
325
if __name__ == '__main__':
 
326
        try:
 
327
                main(sys.argv[1:])
 
328
        except KeyboardInterrupt:
 
329
                print '\nInterrupted by user...'
 
330
                sys.exit(2)
 
331
        finally:
 
332
                buffer.close()