Skip to content

Commit 2febbf6

Browse files
author
Aurélien CHALOT
committed
Updates qwinsta
1 parent 991f871 commit 2febbf6

2 files changed

Lines changed: 38 additions & 19 deletions

File tree

nxc/protocols/smb.py

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -991,18 +991,19 @@ def qwinsta(self):
991991
self.enumerate_sessions_info(sessions)
992992

993993
maxSessionNameLen = max(len(sessions[i]["SessionName"]) + 1 for i in sessions)
994-
maxSessionNameLen = maxSessionNameLen if len("SESSIONNAME") < maxSessionNameLen else len("SESSIONNAME") + 1
994+
maxSessionNameLen = max(maxSessionNameLen, len("SESSIONNAME") + 1)
995995
maxUsernameLen = max(len(sessions[i]["Username"] + sessions[i]["Domain"]) + 1 for i in sessions) + 1
996-
maxUsernameLen = maxUsernameLen if len("Username") < maxUsernameLen else len("Username") + 1
996+
maxUsernameLen = max(maxUsernameLen, len("USERNAME") + 1)
997997
maxIdLen = max(len(str(i)) for i in sessions)
998-
maxIdLen = maxIdLen if len("ID") < maxIdLen else len("ID") + 1
998+
maxIdLen = max(maxIdLen, len("ID") + 1)
999999
maxStateLen = max(len(sessions[i]["state"]) + 1 for i in sessions)
1000-
maxStateLen = maxStateLen if len("STATE") < maxStateLen else len("STATE") + 1
1000+
maxStateLen = max(maxStateLen, len("STATE") + 1)
10011001
maxRemoteIp = max(len(sessions[i]["RemoteIp"]) + 1 for i in sessions)
1002-
maxRemoteIp = maxRemoteIp if len("RemoteAddress") < maxRemoteIp else len("RemoteAddress") + 1
1002+
maxRemoteIp = max(maxRemoteIp, len("RemoteAddress") + 1)
10031003
maxClientName = max(len(sessions[i]["ClientName"]) + 1 for i in sessions)
1004-
maxClientName = maxClientName if len("ClientName") < maxClientName else len("ClientName") + 1
1005-
template = ("{SESSIONNAME: <%d} " # noqa: UP031
1004+
maxClientName = max(maxClientName, len("ClientName") + 1)
1005+
1006+
template = ("{SESSIONNAME: <%d} "
10061007
"{USERNAME: <%d} "
10071008
"{ID: <%d} "
10081009
"{IPv4: <16} "
@@ -1011,7 +1012,6 @@ def qwinsta(self):
10111012
"{CONNTIME: <20} "
10121013
"{DISCTIME: <20} ") % (maxSessionNameLen, maxUsernameLen, maxIdLen, maxStateLen)
10131014

1014-
result = []
10151015
header = template.format(
10161016
SESSIONNAME="SESSIONNAME",
10171017
USERNAME="USERNAME",
@@ -1033,30 +1033,49 @@ def qwinsta(self):
10331033
CONNTIME="",
10341034
DISCTIME="",
10351035
)
1036-
result.extend((header, header2))
1036+
1037+
result = [header, header2]
1038+
1039+
found_user = False
10371040

10381041
for i in sessions:
1042+
username = sessions[i]["Username"]
1043+
domain = sessions[i]["Domain"]
1044+
user_full = f"{domain}\\{username}" if username else ""
1045+
1046+
# If args.qwinsta is not True then a username was supplised to look for
1047+
if self.args.qwinsta and self.args.qwinsta is not True:
1048+
if username.lower() != self.args.qwinsta.lower():
1049+
# If the provided username doesn't match, we pass to the next session
1050+
continue
1051+
1052+
# If the username matches or no username was supplied, we activate that falag
1053+
found_user = True
1054+
1055+
# Then we get the connectTime, disconnectTime and format the row to be printed
10391056
connectTime = sessions[i]["ConnectTime"]
10401057
connectTime = connectTime.strftime(r"%Y/%m/%d %H:%M:%S") if connectTime.year > 1601 else "None"
1041-
10421058
disconnectTime = sessions[i]["DisconnectTime"]
10431059
disconnectTime = disconnectTime.strftime(r"%Y/%m/%d %H:%M:%S") if disconnectTime.year > 1601 else "None"
1044-
userName = sessions[i]["Domain"] + "\\" + sessions[i]["Username"] if len(sessions[i]["Username"]) else ""
1045-
1046-
result.append(template.format(
1060+
row = template.format(
10471061
SESSIONNAME=sessions[i]["SessionName"],
1048-
USERNAME=userName,
1062+
USERNAME=user_full,
10491063
ID=i,
10501064
IPv4=sessions[i]["RemoteIp"],
10511065
STATE=sessions[i]["state"],
10521066
DSTATE=desktop_states[sessions[i]["flags"]],
10531067
CONNTIME=connectTime,
10541068
DISCTIME=disconnectTime,
1055-
))
1069+
)
1070+
result.append(row)
10561071

1057-
self.logger.success("Enumerated qwinsta sessions")
1058-
for row in result:
1059-
self.logger.highlight(row)
1072+
# This flag should be on if a username was supplied and found or if no username was supplied
1073+
if found_user:
1074+
self.logger.success("Enumerated qwinsta sessions")
1075+
for row in result:
1076+
self.logger.highlight(row)
1077+
else:
1078+
self.logger.fail(f"No user session found matching '{self.args.qwinsta}'")
10601079

10611080
@requires_admin
10621081
def tasklist(self):

nxc/protocols/smb/proto_args.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def proto_args(parser, parents):
5353
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")
5454
mapping_enum_group.add_argument("--pass-pol", action="store_true", help="dump password policy")
5555
mapping_enum_group.add_argument("--rid-brute", nargs="?", type=int, const=4000, metavar="MAX_RID", help="Enumerate users by bruteforcing RIDs")
56-
mapping_enum_group.add_argument("--qwinsta", action="store_true", help="Enumerate RDP connections")
56+
mapping_enum_group.add_argument("--qwinsta", type=str, nargs="?", const=True, help="Enumerate user sessions. If a username is given, filter for it; if no value is given, list all.")
5757
mapping_enum_group.add_argument("--tasklist", action="store_true", help="Enumerate running processes")
5858

5959
wmi_group = smb_parser.add_argument_group("WMI", "Options for WMI Queries")

0 commit comments

Comments
 (0)