Merge pull request #556 from crosscutsaw/dump-computers

new module: ldap > dump-computers
This commit is contained in:
Alex
2025-07-14 13:53:18 +02:00
committed by GitHub
2 changed files with 69 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
from nxc.parsers.ldap_results import parse_result_attributes
class NXCModule:
name = "dump-computers"
description = "Dumps all computers in the domain"
supported_protocols = ["ldap"]
opsec_safe = True
multiple_hosts = False
def options(self, context, module_options):
"""
TYPE Only dump NETBIOS or FQDN instead of 'FQDN (OS Version)'
OUTPUT Output to file in addition to printing to console
Examples
--------
netexec ldap $DC-IP -u $username -p $password -M dump-computers
netexec ldap $DC-IP -u $username -p $password -M dump-computers -o TYPE=netbios
netexec ldap $DC-IP -u $username -p $password -M dump-computers -o TYPE=fqdn
netexec ldap $DC-IP -u $username -p $password -M dump-computers -o TYPE=netbios OUTPUT=<location>
"""
self.output_file = None
self.netbios_only = False
self.fqdn_only = False
if "OUTPUT" in module_options:
self.output_file = module_options["OUTPUT"]
if "TYPE" in module_options:
if module_options["TYPE"].lower() == "netbios":
self.netbios_only = True
elif module_options["TYPE"].lower() == "fqdn":
self.fqdn_only = True
def on_login(self, context, connection):
resp = connection.search(
searchFilter="(objectCategory=computer)",
attributes=["dNSHostName", "operatingSystem"]
)
resp_parsed = parse_result_attributes(resp)
answers = []
context.log.debug(f"Total number of records returned: {len(resp_parsed)}")
for item in resp_parsed:
dns_host_name = item["dNSHostName"]
operating_system = item.get("operatingSystem", "Unknown OS")
if self.netbios_only:
netbios_name = dns_host_name.split(".")[0]
answer = netbios_name
elif self.fqdn_only:
answer = dns_host_name
else:
answer = f"{dns_host_name} ({operating_system})"
answers.append(answer)
context.log.success("Found the following computers:")
for answer in answers:
context.log.highlight(answer)
if self.output_file:
try:
with open(self.output_file, "w") as f:
f.write("\n".join(answers) + "\n")
context.log.success(f"Results saved to {self.output_file}")
except Exception as e:
context.log.error(f"Failed to write to file {self.output_file}: {e}")
+1
View File
@@ -210,6 +210,7 @@ netexec ldap TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M subnets
netexec ldap TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M user-desc
netexec ldap TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M whoami
netexec ldap TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M pso
netexec ldap TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M dump-computers
##### WINRM
netexec winrm TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS # need an extra space after this command due to regex
netexec winrm TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -X ipconfig