Skip to content

Commit 2ec56d1

Browse files
committed
Make sure we continue with other users when one user fails
1 parent 6c68d41 commit 2ec56d1

1 file changed

Lines changed: 62 additions & 54 deletions

File tree

nxc/modules/recyclebin.py

Lines changed: 62 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -28,70 +28,78 @@ def on_admin_login(self, context, connection):
2828
remote_ops.enableRegistry()
2929

3030
for sid_directory in connection.conn.listPath("C$", "$Recycle.Bin\\*"):
31-
if sid_directory.get_longname() and sid_directory.get_longname() not in self.false_positive:
31+
try:
32+
if sid_directory.get_longname() and sid_directory.get_longname() not in self.false_positive:
3233

33-
# Extracts the username from the SID
34-
reg_handle = rrp.hOpenLocalMachine(remote_ops._RemoteOperations__rrp)["phKey"]
35-
key_handle = rrp.hBaseRegOpenKey(remote_ops._RemoteOperations__rrp, reg_handle, f"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\{sid_directory.get_longname()}")["phkResult"]
36-
username = profileimagepath = None
37-
try:
38-
_, profileimagepath = rrp.hBaseRegQueryValue(remote_ops._RemoteOperations__rrp, key_handle, "ProfileImagePath\x00")
39-
# Get username and remove embedded null byte
40-
username = profileimagepath.split("\\")[-1].replace("\x00", "")
41-
except rrp.DCERPCSessionError as e:
42-
context.log.debug(f"Couldn't get username from SID {e} on host {connection.host}")
34+
# Extracts the username from the SID
35+
reg_handle = rrp.hOpenLocalMachine(remote_ops._RemoteOperations__rrp)["phKey"]
36+
key_handle = rrp.hBaseRegOpenKey(remote_ops._RemoteOperations__rrp, reg_handle, f"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\{sid_directory.get_longname()}")["phkResult"]
37+
username = profileimagepath = None
38+
try:
39+
_, profileimagepath = rrp.hBaseRegQueryValue(remote_ops._RemoteOperations__rrp, key_handle, "ProfileImagePath\x00")
40+
# Get username and remove embedded null byte
41+
username = profileimagepath.split("\\")[-1].replace("\x00", "")
42+
except rrp.DCERPCSessionError as e:
43+
context.log.debug(f"Couldn't get username from SID {e} on host {connection.host}")
4344

44-
# Lists for any file or directory in the recycle bin
45-
spider_folder = f"$Recycle.Bin\\{sid_directory.get_longname()}\\"
46-
paths = connection.spider(
47-
"C$",
48-
folder=spider_folder,
49-
regex=[r"(.*)"],
50-
no_print_results=True
51-
)
45+
# Lists for any file or directory in the recycle bin
46+
spider_folder = f"$Recycle.Bin\\{sid_directory.get_longname()}\\"
47+
paths = connection.spider(
48+
"C$",
49+
folder=spider_folder,
50+
regex=[r"(.*)"],
51+
no_print_results=True
52+
)
5253

53-
false_positiv = (".", "..", "desktop.ini")
54-
filtered_file_paths = [path for path in paths if not path.endswith(false_positiv)]
55-
if filtered_file_paths:
56-
if username is not None:
57-
context.log.highlight(f"CONTENT FOUND {sid_directory.get_longname()} ({username})")
58-
else:
59-
context.log.highlight(f"CONTENT FOUND {sid_directory.get_longname()}")
54+
false_positiv = (".", "..", "desktop.ini")
55+
filtered_file_paths = [path for path in paths if not path.endswith(false_positiv)]
56+
if filtered_file_paths:
57+
if username is not None:
58+
context.log.highlight(f"CONTENT FOUND {sid_directory.get_longname()} ({username})")
59+
else:
60+
context.log.highlight(f"CONTENT FOUND {sid_directory.get_longname()}")
6061

61-
for path in filtered_file_paths:
62-
# Returned path look like:
63-
# $Recycle.Bin\S-1-5-21-4140170355-2927207985-2497279808-500\/$I87021Q.txt
64-
# Or
65-
# $Recycle.Bin\S-1-5-21-4140170355-2927207985-2497279808-500\/$R87021Q.txt
66-
# $I files are metadata while $R are actual files so we split the path from the SID
67-
# And check that the filename contains $R only to prevent downloading useless stuff
62+
for path in filtered_file_paths:
63+
# Returned path look like:
64+
# $Recycle.Bin\S-1-5-21-4140170355-2927207985-2497279808-500\/$I87021Q.txt
65+
# Or
66+
# $Recycle.Bin\S-1-5-21-4140170355-2927207985-2497279808-500\/$R87021Q.txt
67+
# $I files are metadata while $R are actual files so we split the path from the SID
68+
# And check that the filename contains $R only to prevent downloading useless stuff
6869

69-
if "$R" in path.split(sid_directory.get_longname())[1] and not path.endswith(false_positiv):
70-
try:
71-
buf = BytesIO()
72-
connection.conn.getFile("C$", path, buf.write)
73-
context.log.highlight(f"\t{path}")
74-
found += 1
75-
buf.seek(0)
76-
file_path = path.split("$")[-1].replace("/", "_")
77-
if username: # noqa: SIM108
78-
filename = f"{connection.host}_{username}_recyclebin_{file_path}"
79-
else:
80-
filename = f"{connection.host}_{sid_directory.get_longname()}_recyclebin_{file_path}"
81-
export_path = join(NXC_PATH, "modules", "recyclebin")
82-
path = abspath(join(export_path, filename))
83-
makedirs(export_path, exist_ok=True)
70+
if "$R" in path.split(sid_directory.get_longname())[1] and not path.endswith(false_positiv):
8471
try:
85-
with open(path, "w+") as file:
86-
file.write(buf.read().decode("utf-8", errors="ignore"))
72+
buf = BytesIO()
73+
connection.conn.getFile("C$", path, buf.write)
74+
context.log.highlight(f"\t{path}")
75+
found += 1
76+
buf.seek(0)
77+
file_path = path.split("$")[-1].replace("/", "_")
78+
if username: # noqa: SIM108
79+
filename = f"{connection.host}_{username}_recyclebin_{file_path}"
80+
else:
81+
filename = f"{connection.host}_{sid_directory.get_longname()}_recyclebin_{file_path}"
82+
export_path = join(NXC_PATH, "modules", "recyclebin")
83+
path = abspath(join(export_path, filename))
84+
makedirs(export_path, exist_ok=True)
85+
try:
86+
with open(path, "w+") as file:
87+
file.write(buf.read().decode("utf-8", errors="ignore"))
88+
except Exception as e:
89+
context.log.fail(f"Failed to write recyclebin file to {filename}: {e}")
8790
except Exception as e:
88-
context.log.fail(f"Failed to write recyclebin file to {filename}: {e}")
89-
except Exception as e:
90-
# Probably trying to getFile a directory which won't work
91-
context.log.debug(f"Couldn't open {path} because of {e}")
91+
# Probably trying to getFile a directory which won't work
92+
context.log.debug(f"Couldn't open {path} because of {e}")
93+
except DCERPCSessionError as e:
94+
if "ERROR_FILE_NOT_FOUND" in str(e):
95+
continue
96+
else:
97+
context.log.fail(f"Error opening {sid_directory.get_longname()} on host {connection.host} because of {e}")
98+
continue
9299
if found > 0:
93100
context.log.highlight(f"Recycle bin's content downloaded to {export_path}")
94101
except DCERPCSessionError as e:
102+
context.log.exception(e)
95103
context.log.fail(f"Error connecting to RemoteRegistry {e} on host {connection.host}")
96104
finally:
97105
remote_ops.finish()

0 commit comments

Comments
 (0)