Personal tools
You are here: Home Misc SMBv2Harvest SMBv2Harvest.py

SMBv2Harvest.py

SMBv2Harvest.py — Python Source, 9Kb

File contents

#!/usr/bin/env python
# SMBv2Harvest - A SMBv2 detection tool w/ google harvest
#
# SMBv2Harvest - Written by Sean Arries
# sarries {at} hexsec {dot} com
# 
#    Copyright (C) 2009  Sean Arries
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    See <http://www.gnu.org/licenses/> for details.

import sys
import re
import urllib2
import socket
import random
import time
import threading

## SET THESE VARS ##
webtechs = ['asp','aspx','cfm']
keywords = ['the','be','to','of','and','in','that','have']
TLDs = ['ca','mx','uk','ru','cn','my']

maxgoogle = 1000
numthreads = 25

class Google:
    """    
    This is a class that Gets google results and returns just domains
    It needs to be supplied with 3 arrays and 1 numeric value
    webtechs = asp,php etc... filetype:
    keywords = words for intext:
    TLDs = com,net,edu, etc... site:
    maxgoogle = Max google results per query. it can be 100 - 1000 
    results are stored in final_results 
    """
    CXdic = ('013269018370076798483:gg7jrrhpsy4',
             '008548304570556886379:0vtwavbfaqe',
             '017478300291956931546:v0vo-1jh2y4',
             '002877699081652281083:klnfl5og4kg',
             '009758108896363993364:wnzqtk1afdo',
             '014345598409501589908:mplknj4r1bu')
    
    agents = ["Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)",
            "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)",
            "Microsoft Internet Explorer/4.0b1 (Windows 95)",
            "Opera/8.00 (Windows NT 5.1; U; en)",
            "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.6)"]
    
    rSA = [2,3,4,5]
    gcount = 0

    def __init__(self, webtechs, keywords, TLDs, maxgoogle):
        self.webtechs = webtechs
        self.keywords = keywords
        self.TLDs = TLDs
        self.final_results = []
        self.maxgoogle = maxgoogle
    
    def run(self):
        searchItems = []
        for x in self.webtechs:
             for y in self.keywords:
                for z in self.TLDs:
                    searchItems.append(("filetype:"+x+"+intext:"+y+"+site:"+z))
        for x in searchItems:
            try:
                results = self.Search(x)
            except(KeyboardInterrupt):
                print "\n\n^^ Searching has been cancelled!\n"
                break
            for y in results:
                if y not in self.final_results:
                    self.final_results.append(y)
            sys.stdout.write('\r')
            sys.stdout.flush()
            sys.stdout.write('=> Google Search #: '+str(self.gcount)+'/'+str(len(searchItems))+
                             ' | Domains Found: '+str(len(results))+' | Total Domains: '+
                             str(len(self.final_results))+' | Dork: '+str(x))
            sys.stdout.flush()
        self.final_results.sort()
            
    def Search(self, query):
        tmpDOMAINS = [];counter = 0
        cxe = random.choice(self.CXdic)
        while counter < int(self.maxgoogle):
            URL = 'http://www.google.com/cse?cx='+cxe+'&q='+query+'&num=100&hl=en&lr=&ie=UTF-8&start='+repr(counter)+'&sa=N'
            request_web = urllib2.Request(URL)
            agent = random.choice(self.agents)
            request_web.add_header('User-Agent',agent)
            try:
                source = urllib2.urlopen(request_web).read()
            except:
                break
            strreg = re.compile('(?<=href=")(.*?)(?=")')
            names = strreg.findall(source)
            for name in names:
                if 'http' in name:
                    domain = name.split('/',3)
                    domain = domain[0]+"//"+domain[2]+"/"
                    if domain not in tmpDOMAINS:
                        tmpDOMAINS.append(domain)
            if len(names) > 50:
                counter += 100
                sleeptimer = random.choice(self.rSA);time.sleep(sleeptimer)
            else:
                counter = self.maxgoogle
        self.gcount+=1
        tmpDOMAINS.sort()
        return tmpDOMAINS

class SMBv2Detector(threading.Thread):
    """
    This class detectes IIS7 banners then tries to connect on
    port 445. Its multithreaded and the only requires 1 array passed to
    it with the domains to be tested. format "http://www.site.com/"
    """
    agents = ["Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)",
            "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1)",
            "Microsoft Internet Explorer/4.0b1 (Windows 95)",
            "Opera/8.00 (Windows NT 5.1; U; en)",
            "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.6)"]
    
    def __init__(self, domains):
        self.active = True
        self.domains = domains
        self.Fdomain = 0
        self.Acount = 0
        self.IIS7 = []
        self.vulns = []
        threading.Thread.__init__(self)
        
    def run(self):
        socket.setdefaulttimeout(5)
        for URL in self.domains:
            if self.active == True:
                request_web = urllib2.Request(URL)
                agent = random.choice(self.agents)
                request_web.add_header('User-Agent',agent)
                try:
                    source = urllib2.urlopen(request_web).info()
                except:
                    source = ""
                    pass
                if re.search('Microsoft-IIS/7.0',str(source)):
                    sk=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    sk.settimeout(1)
                    host = URL.split('/',3)[2]
                    try:
                        sk.connect((host,445))
                        sk.close()
                        self.IIS7.append(URL)
                        self.vulns.append(URL)
                    except:
                        self.IIS7.append(URL)
                        pass
                self.Fdomain+=1
        self.Acount+=1
        
    def stop(self):
        self.active = False
        
if __name__ == '__main__':

    def ThreadTracker(URLListLength):
        FinishURLSCount = 0
        while URLListLength != FinishURLSCount:
            FinishURLSCount = 0;VulnCount = 0;IIS7Count = 0;time.sleep(1)
            for thread in threads:
                FinishURLSCount+=thread.Fdomain
                VulnCount+=len(thread.vulns)
                IIS7Count+=len(thread.IIS7)
            percent = int((1.0*FinishURLSCount/URLListLength)*100)
            sys.stdout.write('\r')
            sys.stdout.flush()
            sys.stdout.write("=> VulnsFound: %s | IIS7Found: %s | Tested/Total: %s/%s | Complete %s"
                             % (VulnCount,IIS7Count,FinishURLSCount,URLListLength,percent)+"%")
            sys.stdout.flush()

    def killThreads():
        for x in threads:
            x.stop()
        aThread = 0
        while aThread != len(threads):
            try:
                aThread = 0
                for thread in threads:
                    aThread+=thread.Acount
                time.sleep(1)
            except(KeyboardInterrupt):
                print "^^ Waiting for threads to die...\n"

    print "\n           (  (            (  (   )\   (" 
    print "          )\))(  (    (   )\))( ((_) ))( " 
    print "         ((_))\  )\   )\ ((_))(  _  /((_)" 
    print "          (()(_)((_) ((_) (()(_)| |(_))" 
    print "         / _` |/ _ \/ _ \/ _` | | |/ -_) Don't be evil" 
    print "+--------\__, |\___/\___/\__, | |_|\___|-------------+" 
    print "|        |___/           |___/                       |" 
    print "|    Sean Arries 11/19/09 SMBv2Harvest.py v1.0       |" 
    print "| collects domains from google based on vars inside  |" 
    print "| script. Checks banner info on web server and then  |" 
    print "| checks to see if port 445 is open. MultiThreaded   |" 
    print "+----------------------------------------------------+" 
    print "\n## Script began @",time.strftime("%X"),"##"
    print "!! Starting Google Search !!\n"
    GoogleClass = Google(webtechs, keywords, TLDs, maxgoogle)
    GoogleClass.run()
    print "\n++ Google Search Finished ++"
    print "!! Starting SMBv2 Detection !!\n"
    domains = GoogleClass.final_results
    z = 0;threads = [];sliced = []
    i = len(domains) / int(numthreads)
    m = len(domains) % int(numthreads)
    if len(threads) <= numthreads:
        for x in range(0, int(numthreads)):
            sliced = domains[x*i:(x+1)*i]
            if (z < m):
                sliced.append(domains[int(numthreads)*i+z])
                z += 1
            thread = SMBv2Detector(sliced)
            thread.start()
            threads.append(thread)
    try:
        ThreadTracker(len(domains))
    except(KeyboardInterrupt):
        print "\n\n^^ detection has been cancelled!"
        print "^^ Waiting for threads to die...\n"
        killThreads()
    print "\n\n++ SMBv2 Vuln detection completed! ++"
## Uncomment the lines below to displays the hosts with IIS7 running
#    print "\n%% Domains running Microsoft-IIS/7.0 %%\n" 
#    for thread in threads:
#        for x in thread.IIS7:
#           print "=>",x
    print "%% Domains Vulnerable to SMBv2 Exploit %%"
    for thread in threads:
        for x in thread.vulns:
            print "=>",x
    print "\n## Script Finished @",time.strftime("%X"),"##"

Document Actions