Guest User

Untitled

a guest
Jul 8th, 2018
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.96 KB | None | 0 0
  1. from impacket.smbconnection import SMBConnection, SessionError
  2. from impacket.smb3structs import FILE_READ_DATA
  3. from time import strftime, localtime
  4. import re
  5.  
  6. import logging
  7. log = logging.getLogger()
  8. logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s',
  9. level=logging.DEBUG, datefmt='%I:%M:%S')
  10.  
  11. # log.setLevel(logging.DEBUG)
  12. log.setLevel(logging.INFO)
  13.  
  14. def get_fullpath(conn, share, path):
  15. return '//{}/{}{}'.format(conn.getRemoteHost(), share, path)
  16.  
  17. class Spider():
  18. class Match():
  19. def __init__(self, conn, share, path, pattern, match_type):
  20. self.conn = conn
  21. self.share = share
  22. self.path = path
  23. self.pattern = pattern
  24. self.match_type = match_type
  25. self.obj = self.conn.listPath(self.share, path)[0]
  26. self.mtime = strftime('%Y-%m-%d %H:%M', localtime(self.obj.get_mtime_epoch()))
  27.  
  28. def __str__(self):
  29. output = ''
  30. output += "<path='{}'".format(get_fullpath(self.conn, self.share, self.path))
  31. output += ", mtime='{}'".format(self.mtime)
  32. output += ", pattern='{}'".format(self.pattern)
  33. output += ", match='{}'".format(self.match_type)
  34. output += '>'
  35. return output
  36.  
  37. def __repr__(self):
  38. return self.__str__()
  39.  
  40. def __init__(self, conn, share, path, extensions=None, path_re=None, content_re=None, path_re_ex=None):
  41. # 32MB Blocksize
  42. self.BLOCKSIZE = 32000000
  43.  
  44. self.conn = conn
  45.  
  46. if extensions and not isinstance(extensions, list):
  47. extensions = [extensions]
  48. self.extensions = extensions
  49.  
  50. if path_re and not isinstance(path_re, list):
  51. path_re = [path_re]
  52. self.path_re = path_re
  53.  
  54. if content_re and not isinstance(content_re, list):
  55. content_re = [content_re]
  56. self.content_re = content_re
  57.  
  58. if path_re_ex and not isinstance(path_re_ex, list):
  59. path_re_ex = [path_re_ex]
  60. self.path_re_ex = path_re_ex
  61.  
  62. if path == '.' or path == '/' or path == './':
  63. path = ''
  64. self.path = path
  65.  
  66. self.matches = []
  67. self.share = share
  68. self.__tid = None
  69.  
  70. def __fullpath(self, path):
  71. return get_fullpath(self.conn, self.share, path)
  72.  
  73. def __smbpath(self, path):
  74. if path == '':
  75. return '*/'
  76. else:
  77. return '{}/*'.format(path)
  78.  
  79. def spider(self):
  80. try:
  81. self.__tid = self.conn.connectTree(self.share)
  82. except SessionError as e:
  83. log.warning('Unable to spider: {} - {}'.format(self.__fullpath(self.path), str(e)))
  84. return
  85. log.info('Spidering: {}'.format(self.__fullpath(self.path)))
  86. self.__spider(path=self.path)
  87.  
  88. def __spider(self, path):
  89. log.debug('Directory: {}'.format(self.__fullpath(path)))
  90.  
  91. try:
  92. entries = self.conn.listPath(self.share, self.__smbpath(path))
  93. except SessionError as e:
  94. if not 'STATUS_ACCESS_DENIED' in str(e):
  95. log.warning('Path "{}", error: {}'.format(self.__fullpath(path), str(e)))
  96. return
  97.  
  98. for entry in entries:
  99. name = entry.get_longname()
  100. entrypath = '{}/{}'.format(path, name)
  101. if name == '.' or name == '..':
  102. continue
  103.  
  104. # Directory
  105. if entry.is_directory():
  106. if not self.__match_path_ex('{}/'.format(entrypath)):
  107. self.__match_path(entrypath)
  108. self.__spider(entrypath)
  109. # File
  110. else:
  111. if not self.__match_path_ex('{}'.format(entrypath)):
  112. self.__match_path(entrypath, True)
  113. self.__match_content(entrypath)
  114. log.debug('File: {}'.format(self.__fullpath(entrypath)))
  115.  
  116. def __match_path_ex(self, path):
  117. if self.path_re_ex is not None:
  118. for pattern in self.path_re_ex:
  119. if re.search(pattern, path, re.IGNORECASE):
  120. log.debug("Exlusion matched: '{}'\tPattern: '{}'".format(self.__fullpath(path), pattern))
  121. return True
  122. return False
  123.  
  124. def __match_path(self, path, isFile=False):
  125. if self.path_re:
  126. for pattern in self.path_re:
  127. if re.findall(pattern, path, re.IGNORECASE):
  128. # log.info("Path matched: '{}'\tPattern: '{}'".format(self.__fullpath(path), pattern))
  129. match = self.Match(self.conn, self.share, path, pattern, "Path Match")
  130. self.matches.append(match)
  131. return
  132.  
  133. def __match_content(self, path):
  134. if self.extensions:
  135. found = False
  136. for extension in self.extensions:
  137. if path.lower().endswith(extension.lower()):
  138. log.debug("Extension matched: '{}'\tPattern: '{}'".format(self.__fullpath(path), extension))
  139. found = True
  140. break
  141. if found != True:
  142. return
  143.  
  144. tid = self.__tid
  145.  
  146. try:
  147. fid = self.conn.openFile(tid, path, desiredAccess=FILE_READ_DATA)
  148. cur = 0
  149. data = self.conn.readFile(tid, fid, cur, self.BLOCKSIZE)
  150. while data is not None and data is not '':
  151. cur = cur + len(data)
  152. for pattern in self.content_re:
  153. if re.findall(pattern, data, re.IGNORECASE):
  154. # log.info("Content matched: '{}'\tPattern: '{}'".format(self.__fullpath(path), pattern))
  155. match = self.Match(self.conn, self.share, path, pattern, "Content Match")
  156. self.matches.append(match)
  157. return
  158. data = self.conn.readFile(tid, fid, cur, self.BLOCKSIZE)
  159. self.conn.closeFile(tid, fid)
  160. except:
  161. log.debug('Could not open: {0}'.format(self.__fullpath(path)))
  162.  
  163.  
  164. # Example usage:
  165. address = '10.0.0.1'
  166. target_ip = address
  167. user = 'user01'
  168. password = 'Password123!'
  169. domain = 'lab.test'
  170. port = 445
  171. path = '.'
  172.  
  173. # Share to scan, use * for all shares
  174. share = '*'
  175. # Add to matches if it contains path_re
  176. path_re = ['secret', 'password']
  177. # Exclude spidering if one of these get hit
  178. path_re_ex = ['/system32/', '/.*?assembly.*?/', '/WInsxs.*?/', '/syswow.*?/']
  179. # Search for the following contents
  180. content_re = ['password', 'wacHtwoord']
  181. # But only if the file endswith
  182. extensions = ['.txt', '.RtF', '.ini', '.config', '.cfg', '.docx']
  183.  
  184. # Connect
  185. conn = SMBConnection(address, target_ip, sess_port=int(port))
  186. conn.login(user, password, domain)
  187.  
  188. # Check if the shares should be enumerated.
  189. if share == '*':
  190. for share in [share['shi1_netname'][:-1] for share in conn.listShares()]:
  191. spider = Spider(conn, share, path, extensions, path_re, content_re, path_re_ex)
  192. spider.spider()
  193. for match in spider.matches:
  194. print(match)
  195. else:
  196. # Single share spider
  197. spider = Spider(conn, share, path, extensions, path_re, content_re, path_re_ex)
  198. spider.spider()
  199. for match in spider.matches:
  200. print(match)
Add Comment
Please, Sign In to add comment