Merge pull request #21 from robert-todora/dev

Runbook build
This commit is contained in:
Robert Todora
2023-07-24 12:57:12 -05:00
committed by GitHub
5 changed files with 70 additions and 15 deletions
@@ -6,6 +6,5 @@ Description = "Skips scanning inside shares ending with these words."
MatchLocation = "ShareName"
WordListType = "EndsWith"
MatchLength = 0
WordList = ["\\\\print\\$",
"\\\\ipc\\$"]
WordList = ["\\\\print\\$", "\\\\ipc\\$", "PRINT\\$", "IPC\\$"]
Triage = "Green"
@@ -7,5 +7,5 @@ MatchLocation = "ShareName"
WordListType = "EndsWith"
MatchLength = 0
WordList = ["\\\\C\\$",
"\\\\ADMIN\\$"]
"\\\\ADMIN\\$", "ADMIN\\$", "C\\$"]
Triage = "Black"
+45 -2
View File
@@ -12,7 +12,8 @@ log = logging.getLogger('snafflepy.classifier')
# TODO
class Rules:
class Rules:
def __init__(self) -> None:
self.classifier_rules = []
self.share_classifiers = []
@@ -53,7 +54,7 @@ class Rules:
# TODO
def is_interest(file, rules):
def is_interest_file(file, rules) -> bool:
# massive_wordlist = prepare_classifiers()
# print(massive_wordlist)
# for root, dirs, files in os.walk(snafflepy_path, topdown=False):
@@ -66,3 +67,45 @@ def is_interest(file, rules):
return True
else:
return False
def is_interest_share(share, rules: Rules):
regex_rules = []
# Tedium City to find match in wordlist. Did not prepare rules beforehand except by putting each MatchLocation in its own list
# so I have to do more work here before I can find the match
for rule in rules.share_classifiers:
if rule['WordListType'] == "Regex":
regex_rules = rule['WordList']
for pattern in regex_rules:
if re.search(str(pattern), str(share)) is not None:
log.info(f"{share} matched {rule['RuleName']}:{rule['Description']}")
elif rule['WordListType'] == "EndsWith":
regex_rules = rule['WordList']
for pattern in regex_rules:
if re.search(str(pattern + "$"), str(share)) is not None:
if rule['MatchAction'] == 'Snaffle':
log.info(f"{share} matched rule {rule['RuleName']}:{rule['Description']}")
else:
log.debug(f"{rule['MatchAction']} {share} matched rule {rule['RuleName']}:{rule['Description']}")
elif rule['WordListType'] == "StartsWith":
regex_rules = rule['WordList']
for pattern in regex_rules:
if re.search(str("^" + pattern), str(share)) is not None:
log.warning(f"{share} matched rule {rule['RuleName']}: {rule['Description']}")
elif rule['WordListType'] == "Contains":
regex_rules = rule['WordList']
for pattern in regex_rules:
if re.search(str(pattern), str(share)) is not None:
log.warning(f"{share} matched rule {rule['RuleName']}:{rule['Description']}")
elif rule['WordListType'] == "Exact":
regex_rules = rule['WordList']
for pattern in regex_rules:
if re.search(str("^" + pattern + "$"), str(share)) is not None:
print(f"{share} matched {rule['RuleName']}:{rule['Description']}")
else:
log.warning(f"{rule['RuleName']} has an invalid WordListType - valid values are Regex, EndsWith, StartsWith, Contains, or Exact")
+18 -9
View File
@@ -18,7 +18,7 @@ def begin_snaffle(options):
# Prepare classifiers for use in naive_classify()
snaff_rules = Rules()
prepped_rules = snaff_rules.prepare_classifiers()
snaff_rules.prepare_classifiers()
# for dict_rules in prepped_rules:
# for actual_rule in dict_rules['ClassifierRules']:
# pprint.pprint(actual_rule['Triage'])
@@ -78,15 +78,21 @@ def begin_snaffle(options):
options.targets[0], options.username, options.password, options.domain, options.hash)
except:
log.error(f"Error logging in to SMB on {options.targets[0]}")
log.warning("[GO LOUD ACTIVATED] Enumerating all shares for all files...")
if options.go_loud:
log.warning("[GO LOUD ACTIVATED] Enumerating all shares for all files...")
for target in options.targets:
try:
smb_client = SMBClient(
target, options.username, options.password, options.domain, options.hash)
smb_client.login()
if not smb_client.login():
log.error(f" Unable to login to{target}")
for share in smb_client.shares:
try:
if not options.go_loud:
classify_share(share, snaff_rules)
# else:
# log.info(f"Found share: {share}")
files = smb_client.ls(share, "")
for file in files:
@@ -95,7 +101,7 @@ def begin_snaffle(options):
if options.go_loud:
log.info(f"{target}: {share}\\{file.get_longname()}")
else:
naive_classify(share, file, prepped_rules)
classify_file(share, file, snaff_rules)
except FileListError:
log.error(
@@ -152,7 +158,7 @@ def list_computers(connection: Connection, domain):
# connection.search(search_base=dn,search_filter=filter,search_scope=SUBTREE,attributes=ALL_ATTRIBUTES)
domain_names = []
log.debug(connection.entries)
# log.debug(connection.entries)
for entry in connection.entries:
sep = str(entry).strip().split(':')
domain_names.append(sep[6])
@@ -166,12 +172,15 @@ def list_computers(connection: Connection, domain):
# TODO
def naive_classify(share, file, rules: Rules):
log.info(f"{share}: {file.get_longname()}")
def classify_file(share, file, rules: Rules):
# log.info(f"{share}: {file.get_longname()}")
if is_interest(file, rules):
if is_interest_file(file, rules):
log.info(f"Found interesting file: {share}/{file}")
def classify_share(share, rules: Rules):
is_interest_share(share, rules)
# These functions resolve to public IP Address:
'''
+5 -1
View File
@@ -42,7 +42,11 @@ class SMBClient:
for i in range(len(resp)):
sharename = resp[i]['shi1_netname'][:-1]
remarkname = resp[i]['shi1_remark'][:-1]
log.info(f'{self.server}: Share: {sharename}, Remark: {remarkname}')
# fullname = resp[i]
# print(fullname)
log.info(f'Found share {sharename} on {self.server}, remark {remarkname}')
# log.info(f'{self.server}: Share: {sharename}')
yield sharename
except Exception as e: