Skip to content

Instantly share code, notes, and snippets.

@FrankSpierings
Last active June 18, 2019 17:10
Show Gist options
  • Save FrankSpierings/3eebfa89cce1ae0062ceb7bad1ab945f to your computer and use it in GitHub Desktop.
Save FrankSpierings/3eebfa89cce1ae0062ceb7bad1ab945f to your computer and use it in GitHub Desktop.
Playing with impacket smb and solr
import logging
import string
import os
import requests
import re
from impacket.smbconnection import *
log = logging.getLogger()
logging.basicConfig(format='%(levelname)s: %(asctime)s - %(name)s - %(process)s - %(message)s',
level=logging.INFO, datefmt='%I:%M:%S')
default_shares = [u'{0}$'.format(i) for i in string.ascii_uppercase]
default_shares.append('IPC$')
default_shares.append('ADMIN$')
extensions = ['ini', 'conf', 'config', 'xml', 'reg', 'vbs', 'ps1', 'txt', 'pdf', 'xlsx', 'xls', 'docx', 'doc']
exclude_regexes = ['desktop.ini$', '/WinSxS$', '/system32$', '/SysWow64$', '/appcompat$',
'/diagnostics$', '/DriverStore$', '/INF$', '/Microsoft.NET$', '/WindowsPowerShell/Modules/Pester$',
'/AppData/Local/Packages$', '/SystemApps$']
class SmbIndexer():
def __init__(self, url, target, username, password, domain='', maxdepth=10, maxfilesize=(100*1024*1024)):
self.url = url
self.target = target
self.username = username
self.password = password
self.domain = domain
self.maxdepth = maxdepth
self.maxfilesize = maxfilesize
self.smb = SMBConnection(target, target)
self.smb.login(username, password, domain)
def index(self, spider_default_shares=False):
for share in self.smb.listShares():
share_name = share['shi1_netname'][:-1]
share_remark = share['shi1_remark'][:-1]
if spider_default_shares or share_name not in default_shares:
log.info(u'{0}: {1}'.format(share_name, share_remark))
self.__recur(share_name, u'', self.maxdepth)
def __getfullsharepath(self, share_name, path):
return u'//{0}/{1}{2}'.format(self.smb.getRemoteHost(), share_name, path)
def __recur(self, share_name, path, maxdepth):
excluded_dirs = ['..', '.']
dirs = []
entries = []
if path == u'':
querypath = u'*'
else:
querypath = u'{0}/*'.format(path)
try:
entries = self.smb.listPath(share_name, querypath)
except (Exception) as e:
log.error('{0} - {1}'.format(self.__getfullsharepath(share_name, path), e))
for entry in entries:
name = entry.get_longname()
newpath = u'{0}/{1}'.format(path, name)
if name not in excluded_dirs:
newfullpath = self.__getfullsharepath(share_name, newpath)
if self.__exclude_re_filter(newfullpath):
log.debug(u'{0}'.format(self.__getfullsharepath(share_name, newpath)))
if entry.is_directory():
if path == '*':
dirs.append('{0}/*'.format(name))
else:
dirs.append(newpath)
else:
# It is a file
self.__examinefile(share_name, newpath)
for directory in dirs:
if maxdepth-1 != 0:
self.__recur(share_name, directory, maxdepth-1)
else:
log.info(u'Maxdepth reached, will not examine: {0}'.format(self.__getfullsharepath(share_name, directory)))
def __examinefile(self, share_name, path):
ext = os.path.splitext(path)[1][1:]
ext = ext.lower()
filename = os.path.basename(path).lower()
if ext in extensions:
file = None
try:
file = self.smb.listPath(share_name, path)[0]
except (Exception) as e:
log.error(u'Examine; {0} - {1}'.format(self.__getfullsharepath(share_name, path), e))
if file is not None:
if file.get_filesize() > self.maxfilesize:
log.info(u'Not indexing file since it is too large ({0} > {1}): {2}'.format(file.get_filesize(), self.maxfilesize,
self.__getfullsharepath(share_name, path)))
else:
self.__indexfile(share_name, path)
def __indexfile(self, share_name, path):
headers = {'Content-type': 'application/json'}
fullname = self.__getfullsharepath(share_name, path)
log.info('Indexing: {0}'.format(fullname))
data = self.__readfile(share_name, path)
if data != None and data!= '':
url = '{0}/update/extract?commit=true&literal.id={1}'.format(self.url, fullname)
files = {'file': data}
requests.post(url, files=files, headers=headers)
data = None
def __readfile(self, share_name, path):
tid = None
fid = None
try:
tid = self.smb.connectTree(share_name)
except (Exception) as e:
log.error(u'Error while connecting tree: {0}'.format(e))
try:
fid = self.smb.openFile(tid, path, desiredAccess=FILE_READ_DATA)
except (Exception) as e:
log.error(u'Error while opening file: {0}'.format(e))
self.smb.disconnectTree(tid)
if tid is not None and fid is not None:
data = ''
tmpdata = ''
while True:
tmpdata = self.smb.readFile(tid, fid, offset=len(data))
log.debug(u'Read {0} bytes'.format(len(tmpdata)))
if len(tmpdata) == 0:
break
else:
data += tmpdata
self.smb.closeFile(tid, fid)
self.smb.disconnectTree(tid)
return data
else:
return None
def __exclude_re_filter(self, fullpath):
for pattern in exclude_regexes:
if (re.search(pattern, fullpath, re.IGNORECASE)):
log.debug(u'Path excluded by pattern: "{0}" - "{1}"'.format(pattern, fullpath))
matched = True
return False
return True
si = SmbIndexer('http://localhost:8983/solr/COLLECTOR1', '10.10.10.1', "administrator", "Password123!", maxdepth=-1)
si.index(spider_default_shares=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment