Skip to content

Commit

Permalink
Merge pull request #25 from p0dalirius/add-mount-command
Browse files Browse the repository at this point in the history
[enhancement] Add mount command
  • Loading branch information
p0dalirius authored Jun 8, 2024
2 parents bd0b28b + df348b6 commit b8ffbe8
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 6 deletions.
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

0 comments on commit b8ffbe8

Please sign in to comment.