Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception handling for spider_plus #569

Merged
merged 4 commits into from
Feb 19, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions nxc/modules/spider_plus.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
from os.path import abspath, join, split, exists, splitext, getsize, sep
from os import makedirs, remove, stat
import time
from nxc.paths import TMP_PATH
from nxc.paths import NXC_PATH
from nxc.protocols.smb.remotefile import RemoteFile
from impacket.smb3structs import FILE_READ_DATA
from impacket.smbconnection import SessionError
from impacket.nmb import NetBIOSTimeout


CHUNK_SIZE = 4096
Expand Down Expand Up @@ -116,18 +117,16 @@ def list_path(self, share, subfolder):
filelist = self.smb.conn.listPath(share, subfolder + "*")

except SessionError as e:
self.logger.debug(f'Failed listing files on share "{share}" in folder "{subfolder}".')
self.logger.debug(str(e))
self.logger.debug(f'Failed listing files on share "{share}" in folder "{subfolder}": {e!s}')

if "STATUS_ACCESS_DENIED" in str(e):
self.logger.debug(f'Cannot list files in folder "{subfolder}".')

elif "STATUS_OBJECT_PATH_NOT_FOUND" in str(e):
self.logger.debug(f"The folder {subfolder} does not exist.")

elif self.reconnect():
filelist = self.list_path(share, subfolder)

except NetBIOSTimeout as e:
self.logger.debug(f'Failed listing files on share "{share}" in folder "{subfolder}": {e!s}')
return filelist

def get_remote_file(self, share, path):
Expand Down Expand Up @@ -166,7 +165,7 @@ def read_chunk(self, remote_file, chunk_size=CHUNK_SIZE):

def get_file_save_path(self, remote_file):
r"""Processes the remote file path to extract the filename and the folder path where the file should be saved locally.

It converts forward slashes (/) and backslashes (\) in the remote file path to the appropriate path separator for the local file system.
The folder path and filename are then obtained separately.
"""
Expand Down Expand Up @@ -213,9 +212,9 @@ def spider_shares(self):
# Start the spider at the root of the share folder
self.results[share_name] = {}
self.spider_folder(share_name, "")
except SessionError as e:
except (SessionError, NetBIOSTimeout) as e:
self.logger.exception(e)
self.logger.fail("Got a session error while spidering.")
self.logger.fail(f"Got a session or NetBIOSTimeout error while spidering share: {share_name}")
self.reconnect()

except Exception as e:
Expand Down Expand Up @@ -374,7 +373,7 @@ def save_file(self, remote_file, share_name):

def dump_folder_metadata(self, results):
"""Takes the metadata results as input and writes them to a JSON file in the `self.output_folder`.

The results are formatted with indentation and sorted keys before being written to the file.
"""
metadata_path = join(self.output_folder, f"{self.host}.json")
Expand Down Expand Up @@ -486,7 +485,7 @@ def options(self, context, module_options):
EXCLUDE_EXTS Case-insensitive extension filter to exclude (Default: ico,lnk)
EXCLUDE_FILTER Case-insensitive filter to exclude folders/files (Default: print$,ipc$)
MAX_FILE_SIZE Max file size to download (Default: 51200)
OUTPUT_FOLDER Path of the local folder to save files (Default: /tmp/nxc_spider_plus)
OUTPUT_FOLDER Path of the local folder to save files (Default: ~/.nxc/nxc_spider_plus)
"""
self.download_flag = False
if any("DOWNLOAD" in key for key in module_options):
Expand All @@ -499,7 +498,7 @@ def options(self, context, module_options):
self.exclude_filter = get_list_from_option(module_options.get("EXCLUDE_FILTER", "print$,ipc$"))
self.exclude_filter = [d.lower() for d in self.exclude_filter] # force case-insensitive
self.max_file_size = int(module_options.get("MAX_FILE_SIZE", 50 * 1024))
self.output_folder = module_options.get("OUTPUT_FOLDER", abspath(join(TMP_PATH, "nxc_spider_plus")))
self.output_folder = module_options.get("OUTPUT_FOLDER", abspath(join(NXC_PATH, "modules/nxc_spider_plus")))

def on_login(self, context, connection):
context.log.display("Started module spidering_plus with the following options:")
Expand Down
Loading