2424from impacket .nt_errors import STATUS_MORE_ENTRIES
2525from impacket .nmb import NetBIOSError
2626from impacket .smbconnection import *
27+ from impacket .smb3structs import FILE_READ_DATA , FILE_WRITE_DATA
2728from BaseHTTPServer import BaseHTTPRequestHandler
2829from argparse import RawTextHelpFormatter
2930from binascii import unhexlify , hexlify
3435
3536import StringIO
3637import csv
38+ import re
3739import ntpath
3840import socket
3941import hashlib
@@ -461,15 +463,17 @@ def deriveKey(self, baseKey):
461463 return self .transformKey (key1 ),self .transformKey (key2 )
462464
463465class RemoteFile :
464- def __init__ (self , smbConnection , fileName ):
466+ def __init__ (self , smbConnection , fileName , share = 'ADMIN$' , access = FILE_READ_DATA | FILE_WRITE_DATA ):
465467 self .__smbConnection = smbConnection
468+ self .__share = share
469+ self .__access = access
466470 self .__fileName = fileName
467- self .__tid = self .__smbConnection .connectTree ('ADMIN$' )
471+ self .__tid = self .__smbConnection .connectTree (share )
468472 self .__fid = None
469473 self .__currentOffset = 0
470474
471475 def open (self ):
472- self .__fid = self .__smbConnection .openFile (self .__tid , self .__fileName )
476+ self .__fid = self .__smbConnection .openFile (self .__tid , self .__fileName , desiredAccess = self . __access )
473477
474478 def seek (self , offset , whence ):
475479 # Implement whence, for now it's always from the beginning of the file
@@ -486,9 +490,11 @@ def read(self, bytesToRead):
486490 def close (self ):
487491 if self .__fid is not None :
488492 self .__smbConnection .closeFile (self .__tid , self .__fid )
489- self .__smbConnection .deleteFile ('ADMIN$' , self .__fileName )
490493 self .__fid = None
491494
495+ def delete (self ):
496+ self .__smbConnection .deleteFile (self .__share , self .__fileName )
497+
492498 def tell (self ):
493499 return self .__currentOffset
494500
@@ -2597,28 +2603,52 @@ def smart_login(host, smb, domain):
25972603def spider (smb_conn , ip , share , subfolder , patt , depth ):
25982604 try :
25992605 filelist = smb_conn .listPath (share , subfolder + '\\ *' )
2600- dir_list (filelist , ip , subfolder , patt )
2606+ dir_list (filelist , ip , subfolder , patt , share , smb_conn )
26012607 if depth == 0 :
2602- return 0
2608+ return
26032609 except SessionError :
2604- return 1
2610+ return
26052611
26062612 for result in filelist :
26072613 if result .is_directory () and result .get_longname () != '.' and result .get_longname () != '..' :
26082614 spider (smb_conn , ip , share ,subfolder + '/' + result .get_longname ().encode ('utf8' ), patt , depth - 1 )
2609- return 0
2615+ return
26102616
2611- def dir_list (files ,ip ,path ,pattern ):
2617+ def dir_list (files , ip , path , pattern , share , smb ):
26122618 for result in files :
26132619 for instance in pattern :
26142620 if instance in result .get_longname ():
26152621 if result .is_directory ():
2616- print_att ("//%s/%s/%s [dir]" % (ip , path .replace ("//" ,"" ), result .get_longname ().encode ('utf8' )))
2622+ print_att ("//{}/{}/{} [dir]" . format (ip , path .replace ("//" ,"" ), result .get_longname ().encode ('utf8' )))
26172623 else :
2618- print_att ("//%s/%s/%s" % (ip , path .replace ("//" ,"" ), result .get_longname ().encode ('utf8' )))
2619- return 0
2624+ print_att ("//{}/{}/{}" .format (ip , path .replace ("//" ,"" ), result .get_longname ().encode ('utf8' )))
2625+
2626+ if args .search_content :
2627+ if not result .is_directory ():
2628+ search_content (smb , path , result , share , instance , ip )
2629+
2630+ return
2631+
2632+ def search_content (smb , path , result , share , pattern , ip ):
2633+ rfile = RemoteFile (smb , path + '/' + result .get_longname (), share , access = FILE_READ_DATA )
2634+ rfile .open ()
2635+
2636+ while True :
2637+ try :
2638+ contents = rfile .read (4096 )
2639+ except SessionError as e :
2640+ if 'STATUS_END_OF_FILE' in str (e ):
2641+ return
2642+
2643+ if contents == '' :
2644+ return
2645+
2646+ if re .findall (pattern , contents , re .IGNORECASE ):
2647+ print_att ("//{}/{}/{} offset:{} pattern:{}" .format (ip , path .replace ("//" ,"" ), result .get_longname ().encode ('utf8' ), rfile .tell (), pattern ))
2648+ rfile .close ()
2649+ return
26202650
2621- def _listShares (smb ):
2651+ def enum_shares (smb ):
26222652 permissions = {}
26232653 root = ntpath .normpath ("\\ {}" .format (PERM_DIR ))
26242654
@@ -2832,7 +2862,7 @@ def connect(host):
28322862 print_att ('{}: {}' .format (user [1 ], user [0 ]))
28332863
28342864 if args .list_shares :
2835- share_list = _listShares (smb )
2865+ share_list = enum_shares (smb )
28362866 print_succ ('{}:{} {} Available shares:' .format (host , args .port , s_name ))
28372867 print_att ('\t SHARE\t \t \t Permissions' )
28382868 print_att ('\t -----\t \t \t -----------' )
@@ -3011,9 +3041,10 @@ def concurrency(hosts):
30113041
30123042 sgroup = parser .add_argument_group ("Spidering" , "Options for spidering shares" )
30133043 sgroup .add_argument ("--spider" , metavar = 'FOLDER' , type = str , default = '' , help = 'Folder to spider (defaults to share root dir)' )
3014- sgroup .add_argument ("--pattern" , type = str , default = '' , help = 'Pattern to search for in filenames and folders' )
3015- sgroup .add_argument ("--patternfile" , type = str , help = 'File containing patterns to search for' )
3016- sgroup .add_argument ("--depth" , type = int , default = 1 , help = 'Spider recursion depth (default: 1)' )
3044+ sgroup .add_argument ("--search-content" , dest = 'search_content' , action = 'store_true' , help = 'Enable file content searching' )
3045+ sgroup .add_argument ("--pattern" , type = str , default = '' , help = 'Pattern to search for in folders filenames and file content (if enabled)' )
3046+ sgroup .add_argument ("--patternfile" , type = str , help = 'File containing patterns to search for in folders, filenames and file content (if enabled)' )
3047+ sgroup .add_argument ("--depth" , type = int , default = 10 , help = 'Spider recursion depth (default: 10)' )
30173048
30183049 cgroup = parser .add_argument_group ("Command Execution" , "Options for executing commands" )
30193050 cgroup .add_argument ('--execm' , choices = {"wmi" , "smbexec" , "atexec" }, default = "smbexec" , help = "Method to execute the command (default: smbexec)" )
@@ -3101,7 +3132,7 @@ def concurrency(hosts):
31013132 line = line .rstrip ()
31023133 patterns .append (line )
31033134
3104- patterns .append (args .pattern )
3135+ patterns .extend (args .pattern . split ( ',' ) )
31053136
31063137 args .pattern = patterns
31073138
0 commit comments