class SmbAnalyzer(): def __init__(self, input, filters, out="print"): self.input = input self.out = out self.outwriter = StandardOutWriter() if len(input) > 7 and input[0:7] == "sqlite:": self.filepath = input.split(':')[1] self.func_getvalue = self.sqlite_getvalue self.filters = [ line.strip() for line in open(filters, 'r').readlines() if line[0] != '#' ] def analyze(self): for val in self.func_getvalue(): host = val[0] nbtname = val[1] attributes = val[2] mtime = val[3] size = val[4] share = val[5] filepath = val[6] filename = filepath.replace('\\', '/').split('/')[-1] smbfile = smb.SharedFile(int(time.time()), int(time.time()), int(mtime), int(size), int(size), int(attributes), filename, filename) for filter in self.filters: if filter.lower() in filepath.lower(): self.outwriter.write(host, nbtname, share, smbfile, filepath) def sqlite_getvalue(self): self.dbconn = sqlite3.connect(self.filepath) self.cur = self.dbconn.cursor() self.cur.execute("SELECT * FROM Entries") for row in self.cur.fetchall(): yield row
class SmbCrawler(): def __init__(self, verbose=False, out="print"): self.host = '' self.nbtname = '' self.smb = None self.maxdepth = 999 self.password = None self.lmhash = None self.nthash = None self.username = '' self.domain = '' self.verbose = verbose if len(out) > 4 and out[0:4] == "csv:": filepath = out.split(':')[1] self.outwriter = CsvOutWriter(filepath) elif len(out) > 7 and out[0:7] == "sqlite:": filepath = out.split(':')[1] self.outwriter = SqliteOutWriter(filepath) else: self.outwriter = StandardOutWriter() def resolveNbtName(self): nbt = NetBIOS() try: name = nbt.getnetbiosname(self.host) return name except: return '' def open(self, host, port): self.host = host self.nbtname = self.resolveNbtName() if port == 139: self.smb = SMBConnection('*SMBSERVER', host, sess_port=port) else: self.smb = SMBConnection(host, host, sess_port=port) dialect = self.smb.getDialect() if dialect == SMB_DIALECT: logging.info("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.info("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.info("SMBv2.1 dialect used") else: logging.info("SMBv3.0 dialect used") def login(self, domain, username, password): if self.smb is None: logging.error("No connection open") return try: self.smb.login(username, password, domain=domain) except Exception as e: print ("Authentication failed : " + str(e)) raise self.username = username self.domain = domain if self.smb.isGuestSession() > 0: logging.info("GUEST Session Granted") else: logging.info("USER Session Granted") def login_hash(self, domain, username, hashes): if self.smb is None: logging.error("No connection open") return try: lmhash, nthash = hashes.split(':') self.smb.login(username, '', domain,lmhash=lmhash, nthash=nthash) except Exception as e: print ("Authentication failed : " + str(e)) raise self.username = username self.domain = domain if self.smb.isGuestSession() > 0: logging.info("GUEST Session Granted") else: logging.info("USER Session Granted") def shares(self): shares = [] rpctransport = transport.SMBTransport(self.smb.getRemoteHost(), self.smb.getRemoteHost(), filename = r'\srvsvc', smb_connection = self.smb) dce = rpctransport.get_dce_rpc() dce.connect() dce.bind(srvs.MSRPC_UUID_SRVS) res = srvs.hNetrShareEnum(dce,1) resp = res['InfoStruct']['ShareInfo']['Level1']['Buffer'] for i in range(len(resp)): shares += [resp[i]['shi1_netname'][:-1]] return shares def ls(self, share, pwd): files = [] f_pwd = '' f_pwd = ntpath.join(pwd, '*') f_pwd = string.replace(f_pwd,'/','\\') f_pwd = ntpath.normpath(f_pwd) for f in self.smb.listPath(share, f_pwd): if f.get_longname() not in ['.', '..']: files += [f] return files def use(self,share): tid = self.smb.connectTree(share) self.ls(share, '\\') return tid def spider(self, share, root, maxdepth): if maxdepth < 0: return [] try: files = self.ls(share, root) except Exception as e: if self.verbose: print ("Error in ls("+share+","+root+","+str(maxdepth)+") : " + str(e)) return [] for f in files: new_root = ntpath.join(root, f.get_longname()) new_root = ntpath.normpath(new_root) self.outwriter.write(self.host, self.nbtname, share, f, new_root) if f.is_directory(): self.spider(share, root + f.get_longname() + '\\', maxdepth - 1) def crawl(self, maxdepth, thread = 1): self.maxdepth = maxdepth shares = self.shares() for share in shares: print ('[+] Spidering ' + share) try: tid = self.use(share) except Exception as e: if self.verbose: print ("Error in use("+share+") : " + str(e)) self.spider(share, '\\', maxdepth) self.outwriter.commit()
class SmbCrawler: def __init__(self, verbose=False, out="print"): self.host = "" self.nbtname = "" self.smb = None self.maxdepth = 999 self.password = None self.lmhash = None self.nthash = None self.username = "" self.domain = "" self.verbose = verbose if len(out) > 4 and out[0:4] == "csv:": filepath = out.split(":")[1] self.outwriter = CsvOutWriter(filepath) elif len(out) > 7 and out[0:7] == "sqlite:": filepath = out.split(":")[1] self.outwriter = SqliteOutWriter(filepath) else: self.outwriter = StandardOutWriter() def resolveNbtName(self): nbt = NetBIOS() try: name = nbt.getnetbiosname(self.host) return name except: return "" def open(self, host, port): self.host = host self.nbtname = self.resolveNbtName() if port == 139: self.smb = SMBConnection("*SMBSERVER", host, sess_port=port) else: self.smb = SMBConnection(host, host, sess_port=port) dialect = self.smb.getDialect() if dialect == SMB_DIALECT: logging.info("SMBv1 dialect used") elif dialect == SMB2_DIALECT_002: logging.info("SMBv2.0 dialect used") elif dialect == SMB2_DIALECT_21: logging.info("SMBv2.1 dialect used") else: logging.info("SMBv3.0 dialect used") def login(self, domain, username, password): if self.smb is None: logging.error("No connection open") return try: self.smb.login(username, password, domain=domain) except Exception as e: print("Authentication failed : " + str(e)) raise self.username = username self.domain = domain if self.smb.isGuestSession() > 0: logging.info("GUEST Session Granted") else: logging.info("USER Session Granted") def login_hash(self, domain, username, hashes): if self.smb is None: logging.error("No connection open") return try: lmhash, nthash = hashes.split(":") self.smb.login(username, "", domain, lmhash=lmhash, nthash=nthash) except Exception as e: print("Authentication failed : " + str(e)) raise self.username = username self.domain = domain if self.smb.isGuestSession() > 0: logging.info("GUEST Session Granted") else: logging.info("USER Session Granted") def shares(self): shares = [] rpctransport = transport.SMBTransport( self.smb.getRemoteHost(), self.smb.getRemoteHost(), filename=r"\srvsvc", smb_connection=self.smb ) dce = rpctransport.get_dce_rpc() dce.connect() dce.bind(srvs.MSRPC_UUID_SRVS) res = srvs.hNetrShareEnum(dce, 1) resp = res["InfoStruct"]["ShareInfo"]["Level1"]["Buffer"] for i in range(len(resp)): shares += [resp[i]["shi1_netname"][:-1]] return shares def ls(self, share, pwd): files = [] f_pwd = "" f_pwd = ntpath.join(pwd, "*") f_pwd = string.replace(f_pwd, "/", "\\") f_pwd = ntpath.normpath(f_pwd) for f in self.smb.listPath(share, f_pwd): if f.get_longname() not in [".", ".."]: files += [f] return files def use(self, share): tid = self.smb.connectTree(share) self.ls(share, "\\") return tid def spider(self, share, root, maxdepth): if maxdepth < 0: return [] try: files = self.ls(share, root) except Exception as e: if self.verbose: print("Error in ls(" + share + "," + root + "," + str(maxdepth) + ") : " + str(e)) return [] for f in files: new_root = ntpath.join(root, f.get_longname()) new_root = ntpath.normpath(new_root) self.outwriter.write(self.host, self.nbtname, share, f, new_root) if f.is_directory(): self.spider(share, root + f.get_longname() + "\\", maxdepth - 1) def crawl(self, maxdepth, thread=1): self.maxdepth = maxdepth shares = self.shares() for share in shares: print("[+] Spidering " + share) try: tid = self.use(share) except Exception as e: if self.verbose: print("Error in use(" + share + ") : " + str(e)) self.spider(share, "\\", maxdepth) self.outwriter.commit()