Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions nxc/protocols/smb.py
Original file line number Diff line number Diff line change
Expand Up @@ -1682,13 +1682,23 @@ def groups(self):
self.logger.fail("[REMOVED] Arg moved to the ldap protocol")
return

def _export_lines(self, lines, object_name="entries"):
if not self.args.export:
return

try:
with open(self.args.export, "w", encoding="utf-8") as file:
file.writelines(f"{line}\n" for line in lines)
self.logger.success(f"Exported {len(lines)} {object_name} to {self.args.export}")
except OSError as e:
self.logger.fail(f"Export failed: {e}")

def users(self):
if self.args.users:
self.logger.debug(f"Dumping users: {', '.join(self.args.users)}")
return UserSamrDump(self).dump(requested_users=self.args.users, dump_path=self.args.users_export)

def users_export(self):
self.users()
users = UserSamrDump(self).dump(requested_users=self.args.users)
self._export_lines(users, "users")
return users

def computers(self):
self.logger.fail("[REMOVED] Arg moved to the ldap protocol")
Expand Down Expand Up @@ -1906,6 +1916,8 @@ def rid_brute(self, max_rid=None):
)
so_far += simultaneous
dce.disconnect()
usernames = sorted({entry["username"] for entry in entries if entry["sidtype"] == "SidTypeUser" and not entry["username"].endswith("$")})
self._export_lines(usernames, "users")
return entries

def put_file_single(self, src, dst):
Expand Down
2 changes: 1 addition & 1 deletion nxc/protocols/smb/proto_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ def proto_args(parser, parents):
mapping_enum_group.add_argument("--filter-shares", nargs="+", help="Filter share by access, option 'READ' 'WRITE' or 'READ,WRITE'")
mapping_enum_group.add_argument("--disks", action="store_true", help="Enumerate disks")
mapping_enum_group.add_argument("--users", nargs="*", metavar="USER", help="Enumerate domain users, if a user is specified than only its information is queried.")
mapping_enum_group.add_argument("--users-export", help="Enumerate domain users and export them to the specified file")
mapping_enum_group.add_argument("--groups", nargs="?", const="", metavar="GROUP", help="Enumerate domain groups, if a group is specified than its members are Enumerated")
mapping_enum_group.add_argument("--local-groups", nargs="?", const="", metavar="GROUP", help="Enumerate local groups, if a group is specified then its members are Enumerated")
mapping_enum_group.add_argument("--computers", nargs="?", const="", metavar="COMPUTER", help="Enumerate computer users")
mapping_enum_group.add_argument("--pass-pol", action="store_true", help="dump password policy")
mapping_enum_group.add_argument("--rid-brute", nargs="?", type=int, const=4000, metavar="MAX_RID", help="Enumerate users by bruteforcing RIDs")
mapping_enum_group.add_argument("--export", metavar="FILE", help="Export the result of a supported command to the specified file (supported: --rid-brute, --users)")
mapping_enum_group.add_argument("--smb-sessions", action="store_true", help="Enumerate active smb sessions")
mapping_enum_group.add_argument("--reg-sessions", type=str, nargs="?", const="", help="Enumerate users sessions using the Remote Registry. If a username is given, filter for it. If a file is given, filter for listed usernames. If no value is given, list all.")
mapping_enum_group.add_argument("--loggedon-users", nargs="?", const="", help="Enumerate logged on users, if a user is specified than a regex filter is applied.")
Expand Down
5 changes: 3 additions & 2 deletions nxc/protocols/smb/samruser.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def fetch_users(self, requested_users, dump_path):
names_lookup_resp = samr.hSamrLookupNamesInDomain(self.dce, domain_handle, requested_users)
rids = [r["Data"] for r in names_lookup_resp["RelativeIds"]["Element"]]
self.logger.debug(f"Specific RIDs retrieved: {rids}")
users = self.get_user_info(domain_handle, rids)
users.extend(self.get_user_info(domain_handle, rids))
except DCERPCException as e:
self.logger.debug(f"Exception while requesting users in domain: {e}")
if "STATUS_SOME_NOT_MAPPED" in str(e):
Expand All @@ -129,7 +129,7 @@ def fetch_users(self, requested_users, dump_path):

rids = [r["RelativeId"] for r in enumerate_users_resp["Buffer"]["Buffer"]]
self.logger.debug(f"Full domain RIDs retrieved: {rids}")
users = self.get_user_info(domain_handle, rids)
users.extend(self.get_user_info(domain_handle, rids))

# set these for the while loop
enumerationContext = enumerate_users_resp["EnumerationContext"]
Expand All @@ -140,6 +140,7 @@ def fetch_users(self, requested_users, dump_path):
self.logger.display(f"Writing {len(users)} local users to {dump_path}")
with open(dump_path, "w+") as file:
file.writelines(f"{user}\n" for user in users)
self.users = users
self.dce.disconnect()

def get_user_info(self, domain_handle, user_ids):
Expand Down
4 changes: 3 additions & 1 deletion tests/e2e_commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --disks
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --groups
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --loggedon-users
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --users
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --users-export /tmp/userlistOutputFilename.txt
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --users --export /tmp/userlistOutputFilename.txt
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --computers
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --rid-brute
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --rid-brute --export /tmp/ridBruteExportFilename.txt
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --rid-brute 10000 --export /tmp/ridBruteExportFilenameMaxRid.txt
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --local-groups
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --qwinsta
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS --tasklist
Expand Down
Loading