Skip to content

Commit 7a39c4b

Browse files
committed
removed unnecessary lines, editted try&except blocks
1 parent 15376c3 commit 7a39c4b

1 file changed

Lines changed: 78 additions & 51 deletions

File tree

nxc/modules/notepad.py

Lines changed: 78 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@
44
import re
55
import time
66
from nxc.paths import NXC_PATH
7+
from impacket.smbconnection import SessionError
8+
9+
smb_error_status = [
10+
"STATUS_ACCOUNT_DISABLED",
11+
"STATUS_ACCOUNT_EXPIRED",
12+
"STATUS_ACCOUNT_RESTRICTION",
13+
"STATUS_INVALID_LOGON_HOURS",
14+
"STATUS_INVALID_WORKSTATION",
15+
"STATUS_LOGON_TYPE_NOT_GRANTED",
16+
"STATUS_PASSWORD_EXPIRED",
17+
"STATUS_PASSWORD_MUST_CHANGE",
18+
"STATUS_ACCESS_DENIED",
19+
"STATUS_NO_SUCH_FILE",
20+
"KDC_ERR_CLIENT_REVOKED",
21+
"KDC_ERR_PREAUTH_FAILED",
22+
]
723

824

925
class NXCModule:
@@ -92,9 +108,11 @@ def read_and_decode_file(self, connection, context, file_path, user):
92108
buf.seek(0)
93109
binary_data = buf.read()
94110

95-
# Extract meaningful strings
96-
return [(encoding, string) for encoding, string in self.extract_strings(binary_data)
97-
if self.is_meaningful_content(string)]
111+
# Return only the meaningful strings
112+
return [
113+
string for _, string in self.extract_strings(binary_data)
114+
if self.is_meaningful_content(string)
115+
]
98116

99117
def on_admin_login(self, context, connection):
100118
context.log.display("Searching for Notepad cache...")
@@ -106,56 +124,65 @@ def on_admin_login(self, context, connection):
106124
# Path for Windows Notepad tab state files
107125
notepad_dir = f"Users\\{directory.get_longname()}\\AppData\\Local\\Packages\\Microsoft.WindowsNotepad_8wekyb3d8bbwe\\LocalState\\TabState\\"
108126
try:
109-
if not connection.conn.listPath("C$", f"{notepad_dir}\\*"):
110-
continue
111-
try:
112-
for file in connection.conn.listPath("C$", f"{notepad_dir}\\*"):
113-
if file.get_longname() not in self.false_positive and file.get_longname().endswith(".bin"):
114-
file_path = f"{notepad_dir}{file.get_longname()}"
115-
116-
# Read the binary file
117-
meaningful_strings = self.read_and_decode_file(connection, context, file_path, directory.get_longname())
118-
119-
if meaningful_strings:
120-
found += 1
121-
context.log.highlight(f"C:\\{file_path}")
122-
123-
# Output content
124-
content_lines = []
125-
126-
# First loop to handle meaningful strings
127-
for _, string in meaningful_strings:
128-
if bool(re.match(self.FILE_PATH_REGEX, string)): # Only needed if checking locally
129-
# Read the file into a buffer
130-
meaningful_strings = self.read_and_decode_file(connection, context, string[2:], directory.get_longname())
131-
132-
# Second loop to handle content inside the file
133-
for _, string in meaningful_strings:
134-
context.log.highlight(f"\t{string}")
135-
content_lines.append(string) # Store the string value only
136-
else:
137-
context.log.highlight(f"\t{string}")
138-
content_lines.append(string) # Store the string value only
127+
for file in connection.conn.listPath("C$", f"{notepad_dir}\\*"):
128+
if file.get_longname() not in self.false_positive and file.get_longname().endswith(".bin"):
129+
file_path = f"{notepad_dir}{file.get_longname()}"
139130

140-
# Save to file
141-
filename = f"{connection.host}_{directory.get_longname()}_notepad_tabstate_{found}.txt"
142-
export_path = join(NXC_PATH, "modules", "notepad")
143-
path = abspath(join(export_path, filename))
144-
makedirs(export_path, exist_ok=True)
131+
# Read the binary file
132+
meaningful_strings = self.read_and_decode_file(connection, context, file_path, directory.get_longname())
145133

146-
try:
147-
with open(path, "w+") as output_file:
148-
output_file.write(f"Source: C:\\{file_path}\n\n")
149-
output_file.write("\n".join(content_lines)) # Write strings line by line
150-
context.log.highlight(f"Notepad tab state content written to: {path}")
151-
except Exception as e:
152-
context.log.fail(f"Failed to write Notepad tab state to {filename}: {e}")
134+
if meaningful_strings:
135+
found += 1
136+
context.log.highlight(f"C:\\{file_path}")
153137

154-
except Exception as e:
155-
context.log.fail(f"Failed on connection and reading bin files: {e}")
156-
context.log.debug(f"Failed: {e}")
157-
except Exception as e:
158-
context.log.fail(f"{directory.get_longname()} User has no any notepad cache file")
159-
context.log.debug(f"Failed for user {directory.get_longname()}: {e}")
138+
# Output content
139+
content_lines = []
140+
141+
# First loop to handle meaningful strings
142+
for string in meaningful_strings:
143+
if bool(re.match(self.FILE_PATH_REGEX, string)): # Only needed if checking locally
144+
# Read the file into a buffer
145+
meaningful_strings = self.read_and_decode_file(connection, context, string[2:], directory.get_longname())
146+
147+
# Second loop to handle content inside the file
148+
for string in meaningful_strings:
149+
context.log.highlight(f"\t{string}")
150+
content_lines.append(string) # Store the string value only
151+
else:
152+
context.log.highlight(f"\t{string}")
153+
content_lines.append(string) # Store the string value only
154+
155+
# Save to file
156+
filename = f"{connection.host}_{directory.get_longname()}_notepad_tabstate_{found}.txt"
157+
export_path = join(NXC_PATH, "modules", "notepad")
158+
path = abspath(join(export_path, filename))
159+
makedirs(export_path, exist_ok=True)
160+
161+
with open(path, "w+") as output_file:
162+
output_file.write(f"Source: C:\\{file_path}\n\n")
163+
output_file.write("\n".join(content_lines)) # Write strings line by line
164+
context.log.success(f"Notepad tab state content written to: {path}")
165+
except SessionError as e:
166+
error = self.get_error_string(e)
167+
if error == "STATUS_OBJECT_NAME_NOT_FOUND" or error == "STATUS_OBJECT_PATH_NOT_FOUND":
168+
context.log.debug(f"Failed for user {directory.get_longname()}: {e}")
169+
else:
170+
context.log.fail(
171+
f"Error enumerating shares: {error}",
172+
color="magenta" if error in smb_error_status else "red",
173+
)
160174
if found == 0:
161175
context.log.info("No Notepad tab state files with meaningful content found")
176+
177+
def get_error_string(self, exception):
178+
if hasattr(exception, "getErrorString"):
179+
try:
180+
es = exception.getErrorString()
181+
except KeyError:
182+
return f"Could not get nt error code {exception.getErrorCode()} from impacket: {exception}"
183+
if type(es) is tuple:
184+
return es[0]
185+
else:
186+
return es
187+
else:
188+
return str(exception)

0 commit comments

Comments
 (0)