Files
2026-06-22 16:23:59 +02:00

146 lines
7.3 KiB
Python

from termcolor import colored
NT35_BDC_CONTINUOUS_UPDATE = 0b10
RC4_SUPPORT = 0b100
BDC_HANDLING_CHANGELOGS = 0b10000
RESTARTING_FULL_DC_SYNC = 0b100000
NO_VALIDATION_LEVEL_2_FOR_NON_GENERIC_PASSTHROUGH = 0b10000000
DATABASE_REDO = 0b10000000
REFUSAL_OF_PASSWORD_CHANGES = 0b100000000
NETRLOGON_SEND_TO_SAM = 0b1000000000
GENERIC_PASS_THROUGH = 0b10000000000
CONCURRENT_RPC_CALLS = 0b100000000000
AVOID_USER_ACCOUNT_DATABASE_REPLICATION = 0b1000000000000
AVOID_SECURITY_AUTHORITY_DATABASE_REPLICATION = 0b10000000000000
STRONG_KEYS = 0b100000000000000
TRANSITIVE_TRUSTS = 0b1000000000000000
NETR_SERVER_PASSWORD_SET2 = 0b100000000000000000
NETR_LOGON_GET_DOMAIN_INFO = 0b1000000000000000000
CROSS_FOREST_TRUSTS = 0b10000000000000000000
NO_NT4_EMULATION = 0b100000000000000000000
RODC_PASS_THROUGH = 0b1000000000000000000000
AES_128_BIT_CFB_AND_SHA2 = 0b1000000000000000000000000
AUTHENTICATED_RPC_VIA_LSASS_SUPPORTED = 0b100000000000000000000000000000
SECURE_RPC_AUTHENTICATION = 0b1000000000000000000000000000000
KERBEROS_FOR_SECURE_CHANNEL_SETUP = 0b10000000000000000000000000000000
# 3.1.4.2 Netlogon Negotiate Options
class FLAGS:
def __init__(self, flag: int):
self.flag = flag
if flag < 0 or flag > 0xFFFFFFFF:
raise ValueError("Flags must be a 32-bit unsigned integer.")
self.flag_values = {
0b1: "A IGNORED (Account lockout)",
0b10: "B NT3.5 BDC continuous update",
0b100: "C RC4 support",
0b1000: "D IGNORED (Promotion count(deprecated))",
0b10000: "E Supports BDC handling Changelogs",
0b100000: "F Supports Restarting full DC sync",
0b1000000: "G Does not require ValidationLevel 2 for nongeneric passthrough",
0b10000000: "H Supports DatabaseRedo",
0b100000000: "I Supports refusal of password changes",
0b1000000000: "J Supports NetrLogonSendToSam",
0b10000000000: "K Supports generic pass-through",
0b100000000000: "L Supports concurrent RPC calls",
0b1000000000000: "M Supports avoid of user account database replication",
0b10000000000000: "N Supports avoid of Security Authority database replication",
0b100000000000000: "O Supports Strong keys",
0b1000000000000000: "P Supports transitive trusts",
0b10000000000000000: "Q IGNORED (Supports DNS trusts)",
0b100000000000000000: "R Supports NetrServerPasswordSet2",
0b1000000000000000000: "S Supports NetrLogonGetDomainInfo",
0b10000000000000000000: "T Supports cross-forest trusts",
0b100000000000000000000: "U No NT4 Emulation",
0b1000000000000000000000: "V Supports RODC pass-through",
0b10000000000000000000000: "0",
0b100000000000000000000000: "0",
0b1000000000000000000000000: "W Supports AES 128-bit CFB and SHA2",
0b10000000000000000000000000: "0",
0b100000000000000000000000000: "0",
0b1000000000000000000000000000: "0",
0b10000000000000000000000000000: "0",
0b100000000000000000000000000000: "X IGNORED (Authenticated RPC via lsass supported)",
0b1000000000000000000000000000000: "Y Supports secure RPC authentication",
0b10000000000000000000000000000000: "Z Supports Kerberos for secure channel setup",
}
def compare(self, other):
if not isinstance(other, FLAGS):
raise TypeError("Comparison is only supported with another FLAGS instance.")
if self.flag == other.flag:
return "Equal"
else:
out = "Self - Other - Difference:\n"
for i in range(1, 33):
if (self.flag & (1 << i)) != (other.flag & (1 << i)):
out += f"{(self.flag & (1 << i)) >> i} - {(other.flag & (1 << i)) >> i}: {self.flag_values[1 << i]}\n"
return out
def set_bit(self, flag: int):
if flag < 0 or flag > 0xFFFFFFFF:
raise ValueError("Flags must be a 32-bit unsigned integer.")
self.flag |= flag
def unset_bit(self, flag: int):
if flag < 0 or flag > 0xFFFFFFFF:
raise ValueError("Flags must be a 32-bit unsigned integer.")
self.flag &= ~flag
def __str__(self):
out = ""
out += f"{self.flag & 1}: A IGNORED (Account lockout)"
out += f"\n{(self.flag & 2) >> 1}: B NT3.5 BDC continuous update"
out += f"\n{(self.flag & 4) >> 2}: C RC4 support"
out += f"\n{(self.flag & 8) >> 3}: D IGNORED (Promotion count(deprecated))"
out += f"\n{(self.flag & 0x10) >> 4}: E Supports BDC handling Changelogs"
out += f"\n{(self.flag & 0x20) >> 5}: F Supports Restarting full DC sync"
out += f"\n{(self.flag & 0x40) >> 6}: G Does not require ValidationLevel 2 for nongeneric passthrough"
out += f"\n{(self.flag & 0x80) >> 7}: H Supports DatabaseRedo"
out += f"\n{(self.flag & 0x100) >> 8}: I Supports refusal of password changes"
out += f"\n{(self.flag & 0x200) >> 9}: J Supports NetrLogonSendToSam"
out += f"\n{(self.flag & 0x400) >> 10}: K Supports generic pass-through"
out += f"\n{(self.flag & 0x800) >> 11}: L Supports concurrent RPC calls"
out += f"\n{(self.flag & 0x1000) >> 12}: M Supports avoid of user account database replication"
out += f"\n{(self.flag & 0x2000) >> 13}: N Supports avoid of Security Authority database replication"
out += f"\n{(self.flag & 0x4000) >> 14}: O Supports Strong keys"
out += f"\n{(self.flag & 0x8000) >> 15}: P Supports transitive trusts"
out += f"\n{(self.flag & 0x10000) >> 16}: Q IGNORED (Supports DNS trusts)"
out += f"\n{(self.flag & 0x20000) >> 17}: R Supports NetrServerPasswordSet2"
out += f"\n{(self.flag & 0x40000) >> 18}: S Supports NetrLogonGetDomainInfo"
out += f"\n{(self.flag & 0x80000) >> 19}: T Supports cross-forest trusts"
out += f"\n{(self.flag & 0x100000) >> 20}: U No NT4 Emulation"
out += f"\n{(self.flag & 0x200000) >> 21}: V Supports RODC pass-through"
out += f"\n{(self.flag & 0x400000) >> 22}: 0"
out += f"\n{(self.flag & 0x800000) >> 23}: 0"
out += f"\n{(self.flag & 0x1000000) >> 24}: W Supports AES 128-bit CFB and SHA2"
out += f"\n{(self.flag & 0x2000000) >> 25}: 0"
out += f"\n{(self.flag & 0x4000000) >> 26}: 0"
out += f"\n{(self.flag & 0x8000000) >> 27}: 0"
out += f"\n{(self.flag & 0x10000000) >> 28}: 0"
out += f"\n{(self.flag & 0x20000000) >> 29}: X IGNORED (Authenticated RPC via lsass supported)"
out += f"\n{(self.flag & 0x40000000) >> 30}: Y Supports secure RPC authentication"
out += f"\n{(self.flag & 0x80000000) >> 31}: Z Supports Kerberos for secure channel setup"
return out
def __eq__(self, value):
if not isinstance(value, FLAGS):
return NotImplemented
return self.flag == value.flag
def log(message, color=None):
"""Simple logging function to print messages."""
if color:
if color == "blue":
print(f"{colored('[*]', 'blue', attrs=['bold'])} {message}")
elif color == "orange":
print(f"{colored('[!]', 'yellow', attrs=['bold'])} {message}")
else:
print(colored(f"{message}", color, attrs=["bold"]))
else:
print(f"{colored('[+]', 'green', attrs=['bold'])} {message}")