Skip to content

Commit 848da44

Browse files
authored
Merge pull request Pennyw0rth#663 from Pennyw0rth/ippsec_video
Fix bunch of stuff from ippsec and 0xdf writeup for vintage box
2 parents c34c581 + 61277c8 commit 848da44

5 files changed

Lines changed: 57 additions & 16 deletions

File tree

nxc/protocols/ldap.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def create_conn_obj(self):
168168
target_domain = ""
169169
base_dn = ""
170170
try:
171-
proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap"
171+
proto = "ldaps" if self.port == 636 else "ldap"
172172
ldap_url = f"{proto}://{self.host}"
173173
self.logger.info(f"Connecting to {ldap_url} with no baseDN")
174174
try:
@@ -309,9 +309,9 @@ def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="",
309309

310310
try:
311311
# Connect to LDAP
312-
self.logger.extra["protocol"] = "LDAPS" if (self.args.gmsa or self.port == 636) else "LDAP"
313-
self.logger.extra["port"] = "636" if (self.args.gmsa or self.port == 636) else "389"
314-
proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap"
312+
self.logger.extra["protocol"] = "LDAPS" if self.port == 636 else "LDAP"
313+
self.logger.extra["port"] = "636" if self.port == 636 else "389"
314+
proto = "ldaps" if self.port == 636 else "ldap"
315315
ldap_url = f"{proto}://{self.target}"
316316
self.logger.info(f"Connecting to {ldap_url} - {self.baseDN} - {self.host} [1]")
317317
self.ldap_connection = ldap_impacket.LDAPConnection(url=ldap_url, baseDN=self.baseDN, dstIp=self.host)
@@ -425,9 +425,9 @@ def plaintext_login(self, domain, username, password):
425425

426426
try:
427427
# Connect to LDAP
428-
self.logger.extra["protocol"] = "LDAPS" if (self.args.gmsa or self.port == 636) else "LDAP"
429-
self.logger.extra["port"] = "636" if (self.args.gmsa or self.port == 636) else "389"
430-
proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap"
428+
self.logger.extra["protocol"] = "LDAPS" if self.port == 636 else "LDAP"
429+
self.logger.extra["port"] = "636" if self.port == 636 else "389"
430+
proto = "ldaps" if self.port == 636 else "ldap"
431431
ldap_url = f"{proto}://{self.target}"
432432
self.logger.info(f"Connecting to {ldap_url} - {self.baseDN} - {self.host} [3]")
433433
self.ldap_connection = ldap_impacket.LDAPConnection(url=ldap_url, baseDN=self.baseDN, dstIp=self.host)
@@ -515,9 +515,9 @@ def hash_login(self, domain, username, ntlm_hash):
515515

516516
try:
517517
# Connect to LDAP
518-
self.logger.extra["protocol"] = "LDAPS" if (self.args.gmsa or self.port == 636) else "LDAP"
519-
self.logger.extra["port"] = "636" if (self.args.gmsa or self.port == 636) else "389"
520-
proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap"
518+
self.logger.extra["protocol"] = "LDAPS" if self.port == 636 else "LDAP"
519+
self.logger.extra["port"] = "636" if self.port == 636 else "389"
520+
proto = "ldaps" if self.port == 636 else "ldap"
521521
ldaps_url = f"{proto}://{self.target}"
522522
self.logger.info(f"Connecting to {ldaps_url} - {self.baseDN} - {self.host}")
523523
self.ldap_connection = ldap_impacket.LDAPConnection(url=ldaps_url, baseDN=self.baseDN, dstIp=self.host)

nxc/protocols/smb.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from impacket.dcerpc.v5.samr import SID_NAME_USE
2727
from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED
2828
from impacket.krb5.ccache import CCache
29-
from impacket.krb5.kerberosv5 import SessionKeyDecryptionError
29+
from impacket.krb5.kerberosv5 import SessionKeyDecryptionError, getKerberosTGT
3030
from impacket.krb5.types import KerberosException, Principal
3131
from impacket.krb5 import constants
3232
from impacket.dcerpc.v5.dtypes import NULL
@@ -675,6 +675,34 @@ def gen_relay_list(self):
675675
if self.host not in relay_list.read():
676676
relay_list.write(self.host + "\n")
677677

678+
def generate_tgt(self):
679+
self.logger.info(f"Attempting to get TGT for {self.username}@{self.domain}")
680+
userName = Principal(self.username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
681+
682+
try:
683+
tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(
684+
clientName=userName,
685+
password=self.password,
686+
domain=self.domain.upper(),
687+
lmhash=binascii.unhexlify(self.lmhash) if self.lmhash else "",
688+
nthash=binascii.unhexlify(self.nthash) if self.nthash else "",
689+
aesKey=self.aesKey,
690+
kdcHost=self.kdcHost
691+
)
692+
693+
self.logger.debug(f"TGT successfully obtained for {self.username}@{self.domain}")
694+
self.logger.debug(f"Using cipher: {cipher}")
695+
696+
ccache = CCache()
697+
ccache.fromTGT(tgt, oldSessionKey, sessionKey)
698+
tgt_file = f"{self.args.generate_tgt}.ccache"
699+
ccache.saveFile(tgt_file)
700+
701+
self.logger.success(f"TGT saved to: {tgt_file}")
702+
self.logger.success(f"Run the following command to use the TGT: export KRB5CCNAME={tgt_file}")
703+
except Exception as e:
704+
self.logger.fail(f"Failed to get TGT: {e}")
705+
678706
@requires_admin
679707
def execute(self, payload=None, get_output=False, methods=None) -> str:
680708
"""

nxc/protocols/smb/proto_args.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def proto_args(parser, parents):
2222
smb_parser.add_argument("--laps", dest="laps", metavar="LAPS", type=str, help="LAPS authentification", nargs="?", const="administrator")
2323
smb_parser.add_argument("--generate-hosts-file", type=str, help="Generate a hosts file like from a range of IP")
2424
smb_parser.add_argument("--generate-krb5-file", type=str, help="Generate a krb5 file like from a range of IP")
25+
smb_parser.add_argument("--generate-tgt", type=str, help="Generate a tgt ticket")
2526
self_delegate_arg.make_required = [delegate_arg]
2627

2728
cred_gathering_group = smb_parser.add_argument_group("Credential Gathering", "Options for gathering credentials")

nxc/protocols/winrm.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
from datetime import datetime
1010
from pypsrp.wsman import NAMESPACES
1111
from pypsrp.client import Client
12+
from termcolor import colored
1213

1314
from impacket.examples.secretsdump import LocalOperations, LSASecrets, SAMHashes
1415

15-
from nxc.config import process_secret
16+
from nxc.config import process_secret, host_info_colors
1617
from nxc.connection import connection
1718
from nxc.helpers.bloodhound import add_user_bh
1819
from nxc.helpers.misc import gen_random_string
@@ -35,6 +36,8 @@ def __init__(self, args, db, host):
3536
self.nthash = ""
3637
self.ssl = False
3738
self.challenge_header = None
39+
self.targetDomain = None
40+
self.no_ntlm = False
3841

3942
connection.__init__(self, args, db, host)
4043

@@ -52,7 +55,15 @@ def proto_logger(self):
5255
)
5356

5457
def enum_host_info(self):
55-
ntlm_info = parse_challenge(base64.b64decode(self.challenge_header.split(" ")[1].replace(",", "")))
58+
try:
59+
ntlm_info = parse_challenge(base64.b64decode(self.challenge_header.split(" ")[1].replace(",", "")))
60+
except Exception as e:
61+
self.logger.debug(f"Error parsing NTLM challenge: {e!s}")
62+
self.logger.debug(f"Raw challenge: {self.challenge_header.split(' ')[1].replace(',', '')[:20]}...")
63+
self.logger.error("Invalid NTLM challenge received from server. This may indicate NTLM is not supported and nxc winrm only support NTLM currently")
64+
self.no_ntlm = True
65+
return False
66+
5667
self.targetDomain = self.domain = ntlm_info["domain"]
5768
self.hostname = ntlm_info["hostname"]
5869
self.server_os = ntlm_info["os_version"]
@@ -70,7 +81,8 @@ def enum_host_info(self):
7081
def print_host_info(self):
7182
self.logger.extra["protocol"] = "WINRM-SSL" if self.ssl else "WINRM"
7283
self.logger.extra["port"] = self.port
73-
self.logger.display(f"{self.server_os} (name:{self.hostname}) (domain:{self.targetDomain})")
84+
ntlm = colored(f"(NTLM:{not self.no_ntlm})", host_info_colors[2], attrs=["bold"]) if self.no_ntlm else ""
85+
self.logger.display(f"{self.server_os} (name:{self.hostname}) (domain:{self.targetDomain}) {ntlm}")
7486

7587
def create_conn_obj(self):
7688
if self.is_link_local_ipv6:

poetry.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)