Skip to content
This repository was archived by the owner on Dec 6, 2023. It is now read-only.

Commit 3988708

Browse files
author
byt3bl33d3r
committed
Added file content searching support when spidering shares
1 parent 1699fae commit 3988708

File tree

1 file changed

+49
-18
lines changed

1 file changed

+49
-18
lines changed

crackmapexec.py

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from impacket.nt_errors import STATUS_MORE_ENTRIES
2525
from impacket.nmb import NetBIOSError
2626
from impacket.smbconnection import *
27+
from impacket.smb3structs import FILE_READ_DATA, FILE_WRITE_DATA
2728
from BaseHTTPServer import BaseHTTPRequestHandler
2829
from argparse import RawTextHelpFormatter
2930
from binascii import unhexlify, hexlify
@@ -34,6 +35,7 @@
3435

3536
import StringIO
3637
import csv
38+
import re
3739
import ntpath
3840
import socket
3941
import hashlib
@@ -461,15 +463,17 @@ def deriveKey(self, baseKey):
461463
return self.transformKey(key1),self.transformKey(key2)
462464

463465
class 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):
25972603
def 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('\tSHARE\t\t\tPermissions')
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

Comments
 (0)