mirror of
https://github.com/Pennyw0rth/NetExec.git
synced 2026-11-08 17:38:43 -10:00
Compare commits
35
Commits
kali
...
smb-enum-feature
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4188751e62 | ||
|
|
48c9472cca | ||
|
|
d5cb6f8f0d | ||
|
|
1af282888c | ||
|
|
f2311b308b | ||
|
|
d44ed75076 | ||
|
|
271268a092 | ||
|
|
cdffba942d | ||
|
|
15f29a9c4f | ||
|
|
08e3f17365 | ||
|
|
e4ca4f9fef | ||
|
|
5f79c176ea | ||
|
|
3e18d2f588 | ||
|
|
c956dba3ab | ||
|
|
fbeab5fb5c | ||
|
|
665f778dd0 | ||
|
|
791733853e | ||
|
|
eedbce83b6 | ||
|
|
2bc18c5786 | ||
|
|
e25988275a | ||
|
|
f3fb3d431f | ||
|
|
0983df94db | ||
|
|
bd8620125c | ||
|
|
aa38c7a18a | ||
|
|
3797ccf888 | ||
|
|
cfe231a9a1 | ||
|
|
67da598b11 | ||
|
|
efa0b75c10 | ||
|
|
2fa3e83ae9 | ||
|
|
94e0ab62ea | ||
|
|
061ee498bf | ||
|
|
7afb4afd35 | ||
|
|
4e0b44f6a6 | ||
|
|
bec4831cfb | ||
|
|
d691cbc6bd |
No files matched your search
+15
-5
@@ -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:
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -0,0 +1,365 @@
|
||||
# Module by @syl
|
||||
# https://twitter.com/5yrull
|
||||
# S-1-5-21-3750225908-897271529-2201778708-1103
|
||||
# 'S-1-5-21-3750225908-897271529-2201778708'
|
||||
# (Pdb) resp = lsad.hLsarQueryInformationPolicy2(dce, policyHandle, lsad.POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation)
|
||||
# (Pdb) domainSid = resp['PolicyInformation']['PolicyAccountDomainInfo']['DomainSid'].formatCanonical()
|
||||
# (Pdb) domainSid
|
||||
# 'S-1-5-21-3750225908-897271529-2201778708'
|
||||
# (Pdb) lsat.hLsarLookupSids(dce, policyHandle, ['S-1-5-21-3750225908-897271529-2201778708-1103'],lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
|
||||
# <impacket.dcerpc.v5.lsat.LsarLookupSidsResponse object at 0x7f041cba9d50>
|
||||
# (Pdb) resp = lsat.hLsarLookupSids(dce, policyHandle, ['S-1-5-21-3750225908-897271529-2201778708-1103'],lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
|
||||
# (Pdb) resp
|
||||
# <impacket.dcerpc.v5.lsat.LsarLookupSidsResponse object at 0x7f041cba9de0>
|
||||
# (Pdb) resp.__dict__
|
||||
# {'_isNDR64': False, 'fields': {'ReferencedDomains': <impacket.dcerpc.v5.lsat.PLSAPR_REFERENCED_DOMAIN_LIST object at 0x7f041cba9ea0>, 'TranslatedNames': <impacket.dcerpc.v5.lsat.LSAPR_TRANSLATED_NAMES object at 0x7f041cba9450>, 'MappedCount': <impacket.dcerpc.v5.ndr.NDRULONG object at 0x7f041cba9270>, 'ErrorCode': <impacket.dcerpc.v5.ndr.NDRULONG object at 0x7f041cba8460>}}
|
||||
# (Pdb) resp.TranslatedNames
|
||||
# *** AttributeError: 'LsarLookupSidsResponse' object has no attribute 'TranslatedNames'
|
||||
# (Pdb) resp["TranslatedNames"]
|
||||
# <impacket.dcerpc.v5.lsat.LSAPR_TRANSLATED_NAMES object at 0x7f041cba9450>
|
||||
# (Pdb) resp["TranslatedNames"].__dict__
|
||||
# {'_isNDR64': False, 'fields': {'Entries': <impacket.dcerpc.v5.ndr.NDRULONG object at 0x7f041cba9960>, 'Names': <impacket.dcerpc.v5.lsat.PLSAPR_TRANSLATED_NAME_ARRAY object at 0x7f041cba9a80>}}
|
||||
# (Pdb) resp["TranslatedNames"]["Names"]
|
||||
# [<impacket.dcerpc.v5.lsat.LSAPR_TRANSLATED_NAME object at 0x7f041cba8a60>]
|
||||
# (Pdb) resp["TranslatedNames"]["Names"][0].__dict_
|
||||
# *** AttributeError: 'LSAPR_TRANSLATED_NAME' object has no attribute '__dict_'
|
||||
# (Pdb) resp["TranslatedNames"]["Names"][0].__dict__
|
||||
# {'_isNDR64': False, 'fields': {'Use': <impacket.dcerpc.v5.samr.SID_NAME_USE object at 0x7f041cba8c70>, 'Name': <impacket.dcerpc.v5.dtypes.RPC_UNICODE_STRING object at 0x7f041cba8be0>, 'DomainIndex': <impacket.dcerpc.v5.ndr.NDRLONG object at 0x7f041cba8ca0>}}
|
||||
# (Pdb) resp["TranslatedNames"]["Names"][0]["name"]
|
||||
# *** KeyError: 'name'
|
||||
# (Pdb) resp["TranslatedNames"]["Names"][0]["Name"]
|
||||
# 'George.Hotz'
|
||||
# (Pdb)
|
||||
|
||||
from impacket.smbconnection import SessionError
|
||||
from impacket.dcerpc.v5 import transport, lsat, lsad
|
||||
from impacket.dcerpc.v5.samr import SID_NAME_USE
|
||||
from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED
|
||||
from impacket.dcerpc.v5.rpcrt import DCERPCException
|
||||
from winacl.dtyp.security_descriptor import SECURITY_DESCRIPTOR
|
||||
from winacl.functions.constants import SE_OBJECT_TYPE
|
||||
from winacl.dtyp.ace import FILE_ACCESS_MASK
|
||||
from termcolor import colored
|
||||
|
||||
def get_dce_from_smb(conn):
|
||||
string_binding = rf"ncacn_np:{conn.remoteName}[\pipe\lsarpc]"
|
||||
rpctransport = transport.DCERPCTransportFactory(string_binding)
|
||||
rpctransport.set_dport(conn.port)
|
||||
rpctransport.setRemoteHost(conn.host)
|
||||
rpctransport.set_credentials(conn.username, conn.password, conn.domain, conn.lmhash, conn.nthash)
|
||||
return rpctransport.get_dce_rpc()
|
||||
|
||||
def lookup_sid(dce, sid):
|
||||
dce.connect()
|
||||
dce.bind(lsat.MSRPC_UUID_LSAT)
|
||||
policy_response = lsad.hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
|
||||
policy_handle = policy_response["PolicyHandle"]
|
||||
sid_response = lsat.hLsarLookupSids(dce, policy_handle, [sid],lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
|
||||
sid_name = sid_response["TranslatedNames"]["Names"][0]["Name"]
|
||||
dce.disconnect()
|
||||
return sid_name
|
||||
|
||||
AVAILABLE_FILTERS = ["ace_mask", "ace_sid", "owner", "group"]
|
||||
READ_CONTROL = 0x00020000
|
||||
FILE_SHARE_READ = 0x00000001
|
||||
FILE_NON_DIRECTORY_FILE = 0x00000040
|
||||
FILE_DIRECTORY_FILE = 0x00000001
|
||||
IMPERSONATION = 0x00000002
|
||||
|
||||
class SMBACLEnumerator:
|
||||
|
||||
AVAILABLE_FILTERS = ["ace_mask", "ace_sid", "owner", "group"]
|
||||
|
||||
def __init__(self, connection, context, module_options) -> None:
|
||||
self.connection = connection
|
||||
self.smb_connection = connection.conn
|
||||
self.context = context
|
||||
self.module_options = module_options
|
||||
self.filters = self.parse_filters(self.module_options)
|
||||
self.shares = self.get_shares()
|
||||
|
||||
def get_shares(self):
|
||||
shares = self.connection.shares()
|
||||
|
||||
def parse_filters(self, options: dict) -> dict:
|
||||
...
|
||||
|
||||
def get_security_descriptor() -> None:
|
||||
...
|
||||
|
||||
# def get_security_descriptor(file, smb_connection, context, share_name, file_path, filters=None):
|
||||
# """
|
||||
# Retrieve the security descriptor of a file on a share.
|
||||
|
||||
# Parameters
|
||||
# ----------
|
||||
# file: File object.
|
||||
# smb_connection: SMB connection instance.
|
||||
# context: Context for logging.
|
||||
# share_name: Name of the SMB share.
|
||||
# file_path: Path of the file.
|
||||
# filters: Optional filters for security descriptor components.
|
||||
|
||||
# Returns
|
||||
# -------
|
||||
# None: If the file does not meet the filter criteria.
|
||||
# """
|
||||
# file_full_path = file_path + file.get_longname()
|
||||
# tree_id = smb_connection.connectTree(share_name)
|
||||
# file_id = create_file(smb_connection, tree_id, file_full_path)
|
||||
|
||||
# try:
|
||||
# security_descriptor = smb_connection._SMBConnection.query_sec_info(tree_id, file_id)
|
||||
# security_descriptor_obj = parse_security_descriptor(security_descriptor)
|
||||
|
||||
# if filters and not passes_filters(security_descriptor_obj, filters):
|
||||
# return
|
||||
|
||||
# log_security_descriptor(context, file_full_path, security_descriptor_obj)
|
||||
# except SessionError as e:
|
||||
# context.log.debug(e)
|
||||
|
||||
|
||||
# def create_file(smb_connection, tree_id, file_full_path):
|
||||
# """Create a file in the SMB share and return its ID."""
|
||||
# return smb_connection.createFile(
|
||||
# tree_id,
|
||||
# file_full_path,
|
||||
# desiredAccess=READ_CONTROL,
|
||||
# shareMode=FILE_SHARE_READ,
|
||||
# creationOption=FILE_NON_DIRECTORY_FILE,
|
||||
# creationDisposition=FILE_DIRECTORY_FILE,
|
||||
# fileAttributes=0,
|
||||
# impersonationLevel=IMPERSONATION,
|
||||
# )
|
||||
|
||||
|
||||
# def parse_security_descriptor(security_descriptor):
|
||||
# """Parse the security descriptor from bytes to an object."""
|
||||
# return SECURITY_DESCRIPTOR.from_bytes(
|
||||
# security_descriptor, object_type=SE_OBJECT_TYPE.SE_FILE_OBJECT
|
||||
# )
|
||||
|
||||
|
||||
# def passes_filters(security_descriptor_obj, filters):
|
||||
# """
|
||||
# Check if the security descriptor object passes the given filter criteria.
|
||||
|
||||
# Parameters
|
||||
# ----------
|
||||
# security_descriptor_obj: The security descriptor object.
|
||||
# filters: Dictionary of filter criteria.
|
||||
|
||||
# Returns
|
||||
# -------
|
||||
# bool: True if the descriptor passes all filters, False otherwise.
|
||||
# """
|
||||
# for filter_type, values in filters.items():
|
||||
# if filter_type == "owner" and str(security_descriptor_obj.Owner) not in values:
|
||||
# return False
|
||||
# if filter_type == "group" and str(security_descriptor_obj.Group) not in values:
|
||||
# return False
|
||||
# if filter_type == "ace_sid":
|
||||
# sids = [str(ace.Sid) for ace in security_descriptor_obj.Dacl.aces]
|
||||
# if not any(sid in sids for sid in values):
|
||||
# return False
|
||||
# if filter_type == "ace_mask":
|
||||
# masks = [FILE_ACCESS_MASK(ace.Mask).name for ace in security_descriptor_obj.Dacl.aces]
|
||||
# if not any(mask in masks for mask in values):
|
||||
# return False
|
||||
# return True
|
||||
|
||||
|
||||
def log_security_descriptor(context, file_path, descriptor_obj):
|
||||
"""
|
||||
Log details about the security descriptor.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
context: Context for logging.
|
||||
file_path: Path of the file.
|
||||
descriptor_obj: The security descriptor object.
|
||||
"""
|
||||
context.log.success(file_path)
|
||||
context.log.highlight(f"\t Owner: {descriptor_obj.Owner}")
|
||||
context.log.highlight(f"\t Group: {descriptor_obj.Group}")
|
||||
context.log.highlight(f"\t SACL: {descriptor_obj.Sacl}")
|
||||
|
||||
if descriptor_obj.Dacl is not None:
|
||||
context.log.highlight(f"\t ACEs[{len(descriptor_obj.Dacl.aces)}]: ")
|
||||
for ace in descriptor_obj.Dacl.aces:
|
||||
ace_str = str(ace)
|
||||
if "\r\n" in ace_str:
|
||||
ace_formatted = ace_str.split("\r\n")[:-1]
|
||||
for line in ace_formatted:
|
||||
context.log.highlight(f"\t\t {line}")
|
||||
context.log.highlight("\t\t " + len(ace_formatted[0]) * "=")
|
||||
else:
|
||||
context.log.highlight(f"\t\t {ace_str}")
|
||||
|
||||
def get_security_descriptor(conn, file, smb_connection, context, share_name, file_path, filters=None):
|
||||
"""Retrieving the security descriptor of a certain file on a share"""
|
||||
tree_id = smb_connection.connectTree(share_name)
|
||||
dce = get_dce_from_smb(conn)
|
||||
desired_access = 0x00020000 # READ_CONTROL
|
||||
share_mode = 0x00000001 # FILE_SHARE_READ
|
||||
create_options = 0x00000040 # FILE_NON_DIRECTORY_FILE
|
||||
file_attrs = 0
|
||||
create_disposition = 0x00000001 # FILE_DIRECTORY_FILE
|
||||
file_full_path = file_path + file.get_longname()
|
||||
try:
|
||||
file_id = smb_connection.createFile(
|
||||
tree_id,
|
||||
file_full_path,
|
||||
desiredAccess=desired_access,
|
||||
shareMode=share_mode,
|
||||
creationOption=create_options,
|
||||
creationDisposition=create_disposition,
|
||||
fileAttributes=file_attrs,
|
||||
impersonationLevel=0x00000002, # Impersonation
|
||||
)
|
||||
|
||||
security_descriptor = smb_connection._SMBConnection.query_sec_info(tree_id, file_id)
|
||||
security_descriptor_obj = SECURITY_DESCRIPTOR.from_bytes(
|
||||
security_descriptor, object_type=SE_OBJECT_TYPE.SE_FILE_OBJECT
|
||||
)
|
||||
|
||||
if filters:
|
||||
for _filter, values in filters.items():
|
||||
if _filter == "owner" and str(security_descriptor_obj.Owner) not in values:
|
||||
return
|
||||
if _filter == "group" and str(security_descriptor_obj.Group) not in values:
|
||||
return
|
||||
if _filter == "ace_sid":
|
||||
sids = [str(_ace.Sid) for _ace in security_descriptor_obj.Dacl.aces]
|
||||
for sid in values:
|
||||
if sid in sids:
|
||||
continue
|
||||
else:
|
||||
return
|
||||
if _filter == "ace_mask":
|
||||
masks = [FILE_ACCESS_MASK(_ace.Mask).name for _ace in security_descriptor_obj.Dacl.aces]
|
||||
for mask in values:
|
||||
if mask in masks:
|
||||
continue
|
||||
else:
|
||||
return
|
||||
|
||||
context.log.success(file_full_path)
|
||||
# Also get the user's group to mark it as Owned
|
||||
# smb_connection._SMBConnection._SMB__userName
|
||||
username = smb_connection._SMBConnection._SMB__userName
|
||||
|
||||
owner = lookup_sid(dce, str(security_descriptor_obj.Owner))
|
||||
if owner == username:
|
||||
owner = owner + colored("Pwn3d!", "red")
|
||||
group = lookup_sid(dce, str(security_descriptor_obj.Group))
|
||||
context.log.highlight(f"\t Owner: {owner}")
|
||||
context.log.highlight(f"\t Group: {group}")
|
||||
context.log.highlight(f"\t SACL: {security_descriptor_obj.Sacl}")
|
||||
|
||||
if security_descriptor_obj.Dacl is not None:
|
||||
context.log.highlight("\t ACEs:")
|
||||
for ace in security_descriptor_obj.Dacl.aces:
|
||||
ace_sid_name = lookup_sid(dce, str(ace.Sid))
|
||||
mask_formatted = FILE_ACCESS_MASK(ace.Mask).name
|
||||
if mask_formatted is None:
|
||||
continue
|
||||
owned = colored(" (Own3d!)", "red") if ace_sid_name == username else ""
|
||||
context.log.highlight(f"\t\t {ace_sid_name} - {mask_formatted}{owned}")
|
||||
except SessionError as e:
|
||||
context.log.debug(e)
|
||||
|
||||
def enumerate_files(conn, smb_connection, share_name, current_path, context, filters=None):
|
||||
"""Recursive function that enumerates the directories"""
|
||||
try:
|
||||
print(f"{smb_connection=} {share_name=} {current_path=}")
|
||||
file_list = smb_connection.listPath(share_name, current_path + "*")
|
||||
for file in file_list:
|
||||
if (
|
||||
file.is_directory()
|
||||
and not file.is_system()
|
||||
and file.get_longname() not in [".", ".."]
|
||||
):
|
||||
next_path = current_path + file.get_longname() + "/"
|
||||
context.log.debug(f"Trying to enumrate files in {next_path}")
|
||||
enumerate_files(conn, smb_connection, share_name, next_path, context, filters)
|
||||
if not file.is_directory() and not file.is_system():
|
||||
context.log.debug(f"File Found {file.get_longname()}")
|
||||
get_security_descriptor(conn, file, smb_connection, context, share_name, current_path, filters)
|
||||
except SessionError as e:
|
||||
context.log.error(e)
|
||||
|
||||
|
||||
class NXCModule:
|
||||
"""
|
||||
A module to enumerate the ACLs of the files in a share.
|
||||
|
||||
Module by @syl, thanks to @Skelsec and @NeffIsBack
|
||||
"""
|
||||
name = "enum_share_acls"
|
||||
description = ""
|
||||
supported_protocols = ["smb"]
|
||||
opsec_safe = False
|
||||
multiple_hosts = True
|
||||
|
||||
def __init__(self, context=None, module_options=None):
|
||||
self.context = context
|
||||
self.module_options = module_options
|
||||
self.server = None
|
||||
self.file_path = None
|
||||
self.lnk_path = None
|
||||
self.lnk_name = None
|
||||
self.cleanup = None
|
||||
|
||||
def options(self, context, module_options):
|
||||
"""
|
||||
group-mem: Specify group-mem to call the module
|
||||
GROUP: Specify the GROUP option to query for that group's members
|
||||
Usage:
|
||||
nxc smb 127.0.0.1 -u administrator -p 'Password123!' -M enum_share_acls -o FILTER="ace_mask=FILE_ALL_ACCESS,ace_sid=S-1-5-32-544"
|
||||
nxc smb 127.0.0.1 -u administrator -p 'Password123!' -M enum_share_acls -o FILTER="ace_mask=FILE_ALL_ACCESS|READ_CONTROL,ace_sid=S-1-5-32-544"
|
||||
nxc smb 127.0.0.1 -u administrator -p 'Password123!' -M enum_share_acls -o FILTER="owner=S-1-5-32-544"
|
||||
"""
|
||||
self.FILTER = None
|
||||
if "FILTER" in module_options:
|
||||
self.FILTER = module_options["FILTER"]
|
||||
|
||||
def parse_filters(self):
|
||||
parsed_filters = self.FILTER.split(",")
|
||||
filters_dict = {}
|
||||
masks = [m.name for m in FILE_ACCESS_MASK]
|
||||
for _filter in parsed_filters:
|
||||
|
||||
splitted_filter = _filter.split("=")
|
||||
|
||||
if splitted_filter[0] not in AVAILABLE_FILTERS:
|
||||
return None, f"{_filter} filter isn't available, please choose between {AVAILABLE_FILTERS}"
|
||||
|
||||
for __filter in AVAILABLE_FILTERS:
|
||||
if __filter in _filter:
|
||||
filters_dict[__filter] = splitted_filter[1]
|
||||
if "|" in filters_dict[__filter]:
|
||||
filters_dict[__filter] = filters_dict[__filter].split("|")
|
||||
else:
|
||||
filters_dict[__filter] = [splitted_filter[1],]
|
||||
|
||||
# Verify the filters
|
||||
if "ace_mask" in filters_dict:
|
||||
for mask_name in filters_dict["ace_mask"]:
|
||||
if mask_name not in masks:
|
||||
return None, f"{mask_name} ace_mask isn't valid, please choose between {mask_name}"
|
||||
return filters_dict, None
|
||||
|
||||
def on_login(self, context, connection):
|
||||
shares = connection.shares()
|
||||
smb_connection = connection.conn
|
||||
filters = None
|
||||
if self.FILTER:
|
||||
filters, err = self.parse_filters()
|
||||
if err is not None:
|
||||
context.log.error(err)
|
||||
for share in shares:
|
||||
share_name = share["name"]
|
||||
context.log.display(f"Enumerating ACLs on share: {share_name}")
|
||||
enumerate_files(connection, smb_connection, share_name, "/", context, filters)
|
||||
@@ -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("-------------------------------------")
|
||||
@@ -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 = """
|
||||
|
||||
@@ -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
|
||||
|
||||
+41
-8
@@ -34,6 +34,7 @@ from nxc.helpers.misc import gen_random_string, validate_ntlm
|
||||
from nxc.logger import NXCAdapter
|
||||
from nxc.protocols.smb.firefox import FirefoxTriage
|
||||
from nxc.protocols.smb.kerberos import kerberos_login_with_S4U
|
||||
from nxc.protocols.smb.smb_share import SMB_Share_Enumeration
|
||||
from nxc.servers.smb import NXCSMBServer
|
||||
from nxc.protocols.smb.wmiexec import WMIEXEC
|
||||
from nxc.protocols.smb.atexec import TSCH_EXEC
|
||||
@@ -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,11 @@ 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 +405,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 +465,17 @@ class smb(connection):
|
||||
self.nthash = nthash
|
||||
|
||||
self.conn.login(self.username, "", domain, lmhash, nthash)
|
||||
|
||||
self.check_if_admin()
|
||||
user_id = self.db.add_credential("hash", domain, self.username, 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=}")
|
||||
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 +555,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 +569,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
|
||||
@@ -729,6 +755,10 @@ class smb(connection):
|
||||
return response
|
||||
|
||||
def shares(self):
|
||||
if self.args.shares != True:
|
||||
smb_enumeration = SMB_Share_Enumeration(self, self.conn)
|
||||
return smb_enumeration.enumerate_path(self.args.shares)
|
||||
|
||||
temp_dir = ntpath.normpath("\\" + gen_random_string())
|
||||
permissions = []
|
||||
|
||||
@@ -1774,3 +1804,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 "")
|
||||
@@ -33,7 +33,7 @@ def proto_args(parser, parents):
|
||||
cred_gathering_group.add_argument("--user", dest="userntds", type=str, help="Dump selected user from DC")
|
||||
|
||||
mapping_enum_group = smb_parser.add_argument_group("Mapping/Enumeration", "Options for Mapping/Enumerating")
|
||||
mapping_enum_group.add_argument("--shares", action="store_true", help="enumerate shares and access")
|
||||
mapping_enum_group.add_argument("--shares", nargs="?", default=False, const=True, help="enumerate shares and access")
|
||||
mapping_enum_group.add_argument("--no-write-check", action="store_true", help="Skip write check on shares (avoid leaving traces when missing delete permissions)")
|
||||
mapping_enum_group.add_argument("--filter-shares", nargs="+", help="Filter share by access, option 'read' 'write' or 'read,write'")
|
||||
mapping_enum_group.add_argument("--sessions", action="store_true", help="enumerate active sessions")
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
from nxc.protocols import smb
|
||||
from impacket.smbconnection import SMBConnection, SessionError
|
||||
from impacket.smb import SharedFile
|
||||
from impacket.dcerpc.v5 import transport, lsat, lsad
|
||||
from winacl.dtyp.security_descriptor import SECURITY_DESCRIPTOR
|
||||
from winacl.functions.constants import SE_OBJECT_TYPE
|
||||
from winacl.dtyp.ace import FILE_ACCESS_MASK
|
||||
from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED
|
||||
from termcolor import colored
|
||||
from typing import List
|
||||
|
||||
|
||||
class SMB_Share_Enumeration:
|
||||
def __init__(self, nxc_conn: smb, smb_conn: SMBConnection):
|
||||
self.nxc_conn = nxc_conn
|
||||
self.smb_conn = smb_conn
|
||||
self.logger = nxc_conn.logger
|
||||
|
||||
def enumerate_path(self, path: str):
|
||||
self.share = path.split(":")[0]
|
||||
self.path = path.split(":")[1]
|
||||
self.shares = [share["shi1_netname"][:-1] for share in self.nxc_conn.conn.listShares()]
|
||||
if self.share not in self.shares:
|
||||
self.logger.fail(f"Share {self.share} not found")
|
||||
return
|
||||
else:
|
||||
self.logger.display(f"Enumerating ACLs on share: {self.share}")
|
||||
self.enumerate_files(self.share, self.path, recursive=True)
|
||||
|
||||
def enumerate_files(self, share, path: str, recursive: bool = False):
|
||||
"""Recursive function that enumerates the directories"""
|
||||
self.logger.debug(f"Trying to enumrate files in {path}")
|
||||
if path[-2:] not in ["\\", "/"]:
|
||||
path += "/"
|
||||
path.replace("\\", "/")
|
||||
try:
|
||||
file_list: List[SharedFile] = self.smb_conn.listPath(share, path + "*")
|
||||
for file in file_list:
|
||||
if (
|
||||
file.is_directory()
|
||||
and not file.is_system()
|
||||
and file.get_longname() not in [".", ".."]
|
||||
and recursive
|
||||
):
|
||||
next_path = path + file.get_longname() + "/"
|
||||
self.enumerate_files(share, next_path, recursive=True)
|
||||
if not file.is_directory() and not file.is_system():
|
||||
self.logger.debug(f"File Found {file.get_longname()}")
|
||||
self.get_security_descriptor(file, share, path)
|
||||
except SessionError as e:
|
||||
self.logger.error(e)
|
||||
|
||||
|
||||
def get_security_descriptor(self, file, share, path, filters=None):
|
||||
"""Retrieving the security descriptor of a certain file on a share"""
|
||||
tree_id = self.smb_conn.connectTree(share)
|
||||
dce = self.get_dce_from_smb()
|
||||
desired_access = 0x00020000 # READ_CONTROL
|
||||
share_mode = 0x00000001 # FILE_SHARE_READ
|
||||
create_options = 0x00000040 # FILE_NON_DIRECTORY_FILE
|
||||
file_attrs = 0
|
||||
create_disposition = 0x00000001 # FILE_DIRECTORY_FILE
|
||||
file_full_path = path + file.get_longname()
|
||||
try:
|
||||
file_id = self.smb_conn.createFile(
|
||||
tree_id,
|
||||
file_full_path,
|
||||
desiredAccess=desired_access,
|
||||
shareMode=share_mode,
|
||||
creationOption=create_options,
|
||||
creationDisposition=create_disposition,
|
||||
fileAttributes=file_attrs,
|
||||
impersonationLevel=0x00000002, # Impersonation
|
||||
)
|
||||
|
||||
security_descriptor = self.smb_conn._SMBConnection.query_sec_info(tree_id, file_id)
|
||||
security_descriptor_obj = SECURITY_DESCRIPTOR.from_bytes(
|
||||
security_descriptor, object_type=SE_OBJECT_TYPE.SE_FILE_OBJECT
|
||||
)
|
||||
|
||||
if filters:
|
||||
for _filter, values in filters.items():
|
||||
if _filter == "owner" and str(security_descriptor_obj.Owner) not in values:
|
||||
return
|
||||
if _filter == "group" and str(security_descriptor_obj.Group) not in values:
|
||||
return
|
||||
if _filter == "ace_sid":
|
||||
sids = [str(_ace.Sid) for _ace in security_descriptor_obj.Dacl.aces]
|
||||
for sid in values:
|
||||
if sid in sids:
|
||||
continue
|
||||
else:
|
||||
return
|
||||
if _filter == "ace_mask":
|
||||
masks = [FILE_ACCESS_MASK(_ace.Mask).name for _ace in security_descriptor_obj.Dacl.aces]
|
||||
for mask in values:
|
||||
if mask in masks:
|
||||
continue
|
||||
else:
|
||||
return
|
||||
|
||||
self.logger.success(file_full_path)
|
||||
# Also get the user's group to mark it as Owned
|
||||
# self.smb_conn._SMBConnection._SMB__userName
|
||||
username = self.smb_conn._SMBConnection._SMB__userName
|
||||
|
||||
owner = self.lookup_sid(dce, str(security_descriptor_obj.Owner))
|
||||
if owner == username:
|
||||
owner = owner + colored("Pwn3d!", "red")
|
||||
group = self.lookup_sid(dce, str(security_descriptor_obj.Group))
|
||||
self.logger.highlight(f"\t Owner: {owner}")
|
||||
self.logger.highlight(f"\t Group: {group}")
|
||||
self.logger.highlight(f"\t SACL: {security_descriptor_obj.Sacl}")
|
||||
|
||||
if security_descriptor_obj.Dacl is not None:
|
||||
self.logger.highlight("\t ACEs:")
|
||||
for ace in security_descriptor_obj.Dacl.aces:
|
||||
ace_sid_name = self.lookup_sid(dce, str(ace.Sid))
|
||||
mask_formatted = FILE_ACCESS_MASK(ace.Mask).name
|
||||
if mask_formatted is None:
|
||||
continue
|
||||
owned = colored(" (Own3d!)", "red") if ace_sid_name == username else ""
|
||||
self.logger.highlight(f"\t\t {ace_sid_name} - {mask_formatted}{owned}")
|
||||
except SessionError as e:
|
||||
self.logger.debug(e)
|
||||
|
||||
def get_dce_from_smb(self):
|
||||
string_binding = rf"ncacn_np:{self.nxc_conn.remoteName}[\pipe\lsarpc]"
|
||||
rpctransport = transport.DCERPCTransportFactory(string_binding)
|
||||
rpctransport.set_dport(self.nxc_conn.port)
|
||||
rpctransport.setRemoteHost(self.nxc_conn.host)
|
||||
rpctransport.set_credentials(self.nxc_conn.username, self.nxc_conn.password, self.nxc_conn.domain, self.nxc_conn.lmhash, self.nxc_conn.nthash)
|
||||
return rpctransport.get_dce_rpc()
|
||||
|
||||
def lookup_sid(self, dce, sid):
|
||||
dce.connect()
|
||||
dce.bind(lsat.MSRPC_UUID_LSAT)
|
||||
policy_response = lsad.hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
|
||||
policy_handle = policy_response["PolicyHandle"]
|
||||
sid_response = lsat.hLsarLookupSids(dce, policy_handle, [sid],lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
|
||||
sid_name = sid_response["TranslatedNames"]["Names"][0]["Name"]
|
||||
dce.disconnect()
|
||||
return sid_name
|
||||
|
||||
Generated
+6
-6
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aardwolf"
|
||||
@@ -2092,7 +2092,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""}
|
||||
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
|
||||
typing-extensions = ">=4.6.0"
|
||||
|
||||
[package.extras]
|
||||
@@ -2310,13 +2310,13 @@ watchdog = ["watchdog (>=2.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "winacl"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
description = "ACL/ACE/Security Descriptor manipulation library in pure Python"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "winacl-0.1.8-py3-none-any.whl", hash = "sha256:f17028422c0b2dc6752c801350d37878919804728b776289521dc83622982a45"},
|
||||
{file = "winacl-0.1.8.tar.gz", hash = "sha256:44271a302562de51629f68ef1540d40f3a26e7bc0173646b01a6779cedad644c"},
|
||||
{file = "winacl-0.1.9-py3-none-any.whl", hash = "sha256:31ba781a35f3b1bd3c2ece994816c0a5fe113c73018689ab6118010ac0d15099"},
|
||||
{file = "winacl-0.1.9.tar.gz", hash = "sha256:af70c2ec30178bf9e3c8a1c48c25e8781235fe2c1b321adb46e2f2ae1f8d4aab"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2351,4 +2351,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.8.0"
|
||||
content-hash = "7bde962ed54681c55a1249f2f8272ebf64109417f2a28293eab3eea90ce05c6f"
|
||||
content-hash = "87a6d3ee944dc3aa0122c51ec72fbdc6e6070eda5b812232a1c84ca967f9397e"
|
||||
@@ -64,6 +64,7 @@ rich = "^13.3.5"
|
||||
sqlalchemy = "^2.0.4"
|
||||
termcolor = ">=2.4.0"
|
||||
terminaltables = "^3.1.0"
|
||||
winacl = "^0.1.9"
|
||||
xmltodict = "^0.13.0"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
DEADBEEFDEADBEEFDEADBEEFDEADBEEF
|
||||
DEADBEEFDEADBEEFDEADBEEFDEADBEEF:DEADBEEFDEADBEEFDEADBEEFDEADBEEF
|
||||
TooShort
|
||||
ToooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooLong
|
||||
fc525c9683e8fe067095ba2ddc971889
|
||||
aad3b435b51404eeaad3b435b51404ee:fc525c9683e8fe067095ba2ddc971889
|
||||
@@ -137,7 +137,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
|
||||
|
||||
Reference in new issue
Block a user