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

[enhancement] Add mount command #25

Merged
merged 3 commits into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
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
26 changes: 20 additions & 6 deletions smbclientng/core/CommandCompleter.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,13 @@ class CommandCompleter(object):
],
"subcommands": []
},
"mount": {
"description": [
"Creates a mount point of the remote share on the local machine.",
"Syntax: 'mount <remote_path> <local_mountpoint>'"
],
"subcommands": []
},
"put": {
"description": [
"Put a local file or directory in a remote directory.",
Expand Down Expand Up @@ -250,17 +257,24 @@ class CommandCompleter(object):
],
"subcommands": []
},
"use": {
"tree": {
"description": [
"Use a SMB share.",
"Syntax: 'use <sharename>'"
"Displays a tree view of the remote directories.",
"Syntax: 'tree [directory]'"
],
"subcommands": []
},
"tree": {
"umount": {
"description": [
"Displays a tree view of the remote directories.",
"Syntax: 'tree [directory]'"
"Removes a mount point of the remote share on the local machine.",
"Syntax: 'umount <remote_path>'"
],
"subcommands": []
},
"use": {
"description": [
"Use a SMB share.",
"Syntax: 'use <sharename>'"
],
"subcommands": []
},
Expand Down
44 changes: 44 additions & 0 deletions smbclientng/core/InteractiveShell.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ def process_command(self, command, arguments=[]):
elif command == "module":
self.command_module(arguments, command)

# Creates a mount point of the remote share on the local machine
elif command == "mount":
self.command_mount(arguments, command)

# Reconnects the current SMB session
elif command in ["connect", "reconnect"]:
self.command_reconnect(arguments, command)
Expand Down Expand Up @@ -640,6 +644,31 @@ def command_module(self, arguments, command):
else:
print("[!] Module '%s' does not exist." % module_name)

@command_arguments_required
@active_smb_connection_needed
@smb_share_is_set
def command_mount(self, arguments, command):
# Command arguments required : Yes
# Active SMB connection needed : Yes
# SMB share needed : Yes

if len(arguments) == 2:
remote_path = arguments[0]
if not remote_path.startswith(ntpath.sep):
remote_path = self.smbSession.smb_cwd + ntpath.sep + remote_path

local_mount_point = arguments[1]

if self.config.debug:
print("[debug] Trying to mount remote '%s' onto local '%s'" % (remote_path, local_mount_point))

try:
self.smbSession.mount(local_mount_point, remote_path)
except (impacket.smbconnection.SessionError, impacket.smb3.SessionError) as e:
self.smbSession.umount(local_mount_point)
else:
self.commandCompleterObject.print_help(command=command)

@command_arguments_required
@active_smb_connection_needed
@smb_share_is_set
Expand Down Expand Up @@ -828,6 +857,21 @@ def command_tree(self, arguments, command):
else:
self.smbSession.tree(path=' '.join(arguments))

@command_arguments_required
@active_smb_connection_needed
@smb_share_is_set
def command_umount(self, arguments, command):
# Command arguments required : Yes
# Active SMB connection needed : Yes
# SMB share needed : Yes

local_mount_point = arguments[0]

if self.config.debug:
print("[debug] Trying to unmount local mount point '%s'" % (local_mount_point))

self.smbSession.mount(local_mount_point)

@command_arguments_required
@active_smb_connection_needed
def command_use(self, arguments, command):
Expand Down
49 changes: 49 additions & 0 deletions smbclientng/core/SMBSession.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import ntpath
import os
import re
import sys
import traceback
from smbclientng.core.LocalFileIO import LocalFileIO
from smbclientng.core.utils import b_filesize, STYPE_MASK
Expand Down Expand Up @@ -65,6 +66,7 @@ def __init__(self, address, domain, username, password, lmhash, nthash, use_kerb
self.available_shares = {}
self.smb_share = None
self.smb_cwd = ""
self.smb_tree_id = None

self.list_shares()

Expand Down Expand Up @@ -565,6 +567,32 @@ def mkdir(self, path=None):
else:
pass

def mount(self, local_mount_point, remote_path):

if not os.path.exists(local_mount_point):
pass

if sys.platform.startswith('win'):
remote_path = remote_path.replace('/',ntpath.sep)
command = f"net use {local_mount_point} \\\\{self.address}\\{self.smb_share}\\{remote_path}"

elif sys.platform.startswith('linux'):
remote_path = remote_path.replace(ntpath.sep,'/')
command = f"mount -t cifs //{self.address}/{self.smb_share}/{remote_path} {local_mount_point} -o username={self.username},password={self.password}"

elif sys.platform.startswith('darwin'):
remote_path = remote_path.replace(ntpath.sep,'/')
command = f"mount_smbfs //{self.username}:{self.password}@{self.address}/{self.smb_share}/{remote_path} {local_mount_point}"

else:
command = None
print("[!] Unsupported platform for mounting SMB share.")

if command is not None:
if self.config.debug:
print("[debug] Executing: %s" % command)
os.system(command)

def path_exists(self, path=None):
"""
Checks if the specified path exists on the SMB share.
Expand Down Expand Up @@ -956,6 +984,25 @@ def recurse_action(base_dir="", path=[], prompt=[]):
self.close_smb_session()
self.init_smb_session()

def umount(self, local_mount_point):
if os.path.exists(local_mount_point):
if sys.platform.startswith('win'):
command = f"net use {local_mount_point} /delete"

elif sys.platform.startswith('linux') or sys.platform.startswith('darwin'):
command = f"umount {local_mount_point}"

else:
command = None
print("[!] Unsupported platform for unmounting SMB share.")

if command is not None:
if self.config.debug:
print("[debug] Executing: %s" % command)
os.system(command)
else:
print("[!] Cannot unmount a non existing path.")

# Setter / Getter

def set_share(self, shareName):
Expand All @@ -977,6 +1024,8 @@ def set_share(self, shareName):
if shareName.lower() in self.available_shares.keys():
# Doing this in order to keep the case of the share adevertised by the remote machine
self.smb_share = self.available_shares[shareName.lower()]["name"]
# Connects the tree
self.smb_tree_id = self.smbClient.connectTree(self.smb_share)
else:
print("[!] Could not set share '%s', it does not exist remotely." % shareName)

Expand Down
Loading