Skip to content

Commit 2e86a0e

Browse files
committed
Functionalize admin enumeration
1 parent 4f2a611 commit 2e86a0e

1 file changed

Lines changed: 68 additions & 61 deletions

File tree

nxc/modules/presence.py

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,30 @@ def options(self, context, module_options):
2121
"""There are no module options."""
2222

2323
def on_admin_login(self, context, connection):
24-
admin_users = []
25-
2624
try:
27-
string_binding = fr"ncacn_np:{connection.kdcHost}[\pipe\samr]"
28-
context.log.debug(f"Using string binding: {string_binding}")
25+
admin_users = self.enumerate_admin_users(context, connection)
26+
if not admin_users:
27+
context.log.fail("No admin users found.")
28+
return
29+
30+
# Update user objects to check if they are in tasklist or users directory
31+
self.check_users_directory(context, connection, admin_users)
32+
self.check_tasklist(context, connection, admin_users)
33+
34+
# print grouped/logged results nicely
35+
self.print_grouped_results(context, admin_users)
36+
except Exception as e:
37+
context.log.fail(str(e))
38+
context.log.debug(traceback.format_exc())
39+
40+
def enumerate_admin_users(self, context, connection):
41+
admin_users = []
42+
string_binding = fr"ncacn_np:{connection.kdcHost}[\pipe\samr]"
43+
context.log.debug(f"Using string binding: {string_binding}")
2944

30-
rpctransport = transport.DCERPCTransportFactory(string_binding)
31-
rpctransport.setRemoteHost(connection.kdcHost)
32-
rpctransport.set_credentials(
45+
rpctransport = transport.DCERPCTransportFactory(string_binding)
46+
rpctransport.setRemoteHost(connection.kdcHost)
47+
rpctransport.set_credentials(
3348
connection.username,
3449
connection.password,
3550
connection.domain,
@@ -38,68 +53,60 @@ def on_admin_login(self, context, connection):
3853
aesKey=connection.aesKey,
3954
)
4055

41-
dce = rpctransport.get_dce_rpc()
42-
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
43-
dce.connect()
44-
dce.bind(samr.MSRPC_UUID_SAMR)
56+
dce = rpctransport.get_dce_rpc()
57+
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
58+
dce.connect()
59+
dce.bind(samr.MSRPC_UUID_SAMR)
4560

46-
try:
47-
server_handle = samr.hSamrConnect2(dce)["ServerHandle"]
48-
domain = samr.hSamrEnumerateDomainsInSamServer(dce, server_handle)["Buffer"]["Buffer"][0]["Name"]
49-
resp = samr.hSamrLookupDomainInSamServer(dce, server_handle, domain)
50-
domain_sid = resp["DomainId"].formatCanonical()
51-
domain_handle = samr.hSamrOpenDomain(dce, server_handle, samr.DOMAIN_LOOKUP | samr.DOMAIN_LIST_ACCOUNTS, resp["DomainId"])["DomainHandle"]
52-
context.log.debug(f"Resolved domain SID for {domain}: {domain_sid}")
53-
except Exception as e:
54-
context.log.fail(f"Failed to open domain {domain}: {e!s}")
55-
context.log.debug(traceback.format_exc())
56-
return
61+
try:
62+
server_handle = samr.hSamrConnect2(dce)["ServerHandle"]
63+
domain = samr.hSamrEnumerateDomainsInSamServer(dce, server_handle)["Buffer"]["Buffer"][0]["Name"]
64+
resp = samr.hSamrLookupDomainInSamServer(dce, server_handle, domain)
65+
domain_sid = resp["DomainId"].formatCanonical()
66+
domain_handle = samr.hSamrOpenDomain(dce, server_handle, samr.DOMAIN_LOOKUP | samr.DOMAIN_LIST_ACCOUNTS, resp["DomainId"])["DomainHandle"]
67+
context.log.debug(f"Resolved domain SID for {domain}: {domain_sid}")
68+
except Exception as e:
69+
context.log.fail(f"Failed to open domain {domain}: {e!s}")
70+
context.log.debug(traceback.format_exc())
71+
return []
5772

58-
admin_rids = {
73+
admin_rids = {
5974
"Domain Admins": 512,
6075
"Enterprise Admins": 519,
6176
}
6277

63-
# Enumerate admin groups and their members
64-
for group_name, group_rid in admin_rids.items():
65-
context.log.debug(f"Looking up group: {group_name} with RID {group_rid}")
66-
67-
try:
68-
group_handle = samr.hSamrOpenGroup(dce, domain_handle, samr.GROUP_LIST_MEMBERS, group_rid)["GroupHandle"]
69-
resp = samr.hSamrGetMembersInGroup(dce, group_handle)
70-
for member in resp["Members"]["Members"]:
71-
rid = int.from_bytes(member.getData(), byteorder="little")
72-
try:
73-
user_handle = samr.hSamrOpenUser(dce, domain_handle, samr.MAXIMUM_ALLOWED, rid)["UserHandle"]
74-
username = samr.hSamrQueryInformationUser2(dce, user_handle, samr.USER_INFORMATION_CLASS.UserAllInformation)["Buffer"]["All"]["UserName"]
75-
76-
# If user already exists, append group name
77-
if any(u["sid"] == f"{domain_sid}-{rid}" for u in admin_users):
78-
user = next(u for u in admin_users if u["sid"] == f"{domain_sid}-{rid}")
79-
user["group"].append(group_name)
80-
else:
81-
admin_users.append({"username": username, "sid": f"{domain_sid}-{rid}", "domain": domain, "group": [group_name], "in_tasks": False, "in_directory": False})
82-
context.log.debug(f"Found user: {username} with RID {rid} in group {group_name}")
83-
except Exception as e:
84-
context.log.debug(f"Failed to get user info for RID {rid}: {e!s}")
85-
finally:
86-
with suppress(Exception):
87-
samr.hSamrCloseHandle(dce, user_handle)
88-
except Exception as e:
89-
context.log.debug(f"Failed to get members of group {group_name}: {e!s}")
90-
finally:
91-
with suppress(Exception):
92-
samr.hSamrCloseHandle(dce, group_handle)
78+
# Enumerate admin groups and their members
79+
for group_name, group_rid in admin_rids.items():
80+
context.log.debug(f"Looking up group: {group_name} with RID {group_rid}")
9381

94-
# Update user objects to check if they are in tasklist or users directory
95-
self.check_users_directory(context, connection, admin_users)
96-
self.check_tasklist(context, connection, admin_users)
82+
try:
83+
group_handle = samr.hSamrOpenGroup(dce, domain_handle, samr.GROUP_LIST_MEMBERS, group_rid)["GroupHandle"]
84+
resp = samr.hSamrGetMembersInGroup(dce, group_handle)
85+
for member in resp["Members"]["Members"]:
86+
rid = int.from_bytes(member.getData(), byteorder="little")
87+
try:
88+
user_handle = samr.hSamrOpenUser(dce, domain_handle, samr.MAXIMUM_ALLOWED, rid)["UserHandle"]
89+
username = samr.hSamrQueryInformationUser2(dce, user_handle, samr.USER_INFORMATION_CLASS.UserAllInformation)["Buffer"]["All"]["UserName"]
90+
91+
# If user already exists, append group name
92+
if any(u["sid"] == f"{domain_sid}-{rid}" for u in admin_users):
93+
user = next(u for u in admin_users if u["sid"] == f"{domain_sid}-{rid}")
94+
user["group"].append(group_name)
95+
else:
96+
admin_users.append({"username": username, "sid": f"{domain_sid}-{rid}", "domain": domain, "group": [group_name], "in_tasks": False, "in_directory": False})
97+
context.log.debug(f"Found user: {username} with RID {rid} in group {group_name}")
98+
except Exception as e:
99+
context.log.debug(f"Failed to get user info for RID {rid}: {e!s}")
100+
finally:
101+
with suppress(Exception):
102+
samr.hSamrCloseHandle(dce, user_handle)
103+
except Exception as e:
104+
context.log.debug(f"Failed to get members of group {group_name}: {e!s}")
105+
finally:
106+
with suppress(Exception):
107+
samr.hSamrCloseHandle(dce, group_handle)
97108

98-
# print grouped/logged results nicely
99-
self.print_grouped_results(context, admin_users)
100-
except Exception as e:
101-
context.log.fail(str(e))
102-
context.log.debug(traceback.format_exc())
109+
return admin_users
103110

104111
def check_users_directory(self, context, connection, admin_users):
105112
dirs_found = set()

0 commit comments

Comments
 (0)