Add a proper rex-based service for the SMB server

This commit is contained in:
Spencer McIntyre
2024-01-08 15:21:08 -05:00
parent b10e8d566b
commit 024bdaec6d
6 changed files with 40 additions and 35 deletions
+3
View File
@@ -52,3 +52,6 @@ group :test do
# Manipulate Time.now in specs
gem 'timecop'
end
# remove after https://github.com/rapid7/ruby_smb/pull/260 is landed
gem 'ruby_smb', git: 'https://github.com/zeroSteiner/ruby_smb', branch: 'feat/server/remove-share'
+13 -6
View File
@@ -1,3 +1,15 @@
GIT
remote: https://github.com/zeroSteiner/ruby_smb
revision: feba8f6592c33c252c6b4e5dd576f2722ada6bf2
branch: feat/server/remove-share
specs:
ruby_smb (3.3.2)
bindata
openssl-ccm
openssl-cmac
rubyntlm
windows_error (>= 0.1.4)
PATH
remote: .
specs:
@@ -473,12 +485,6 @@ GEM
ruby-progressbar (1.13.0)
ruby-rc4 (0.1.5)
ruby2_keywords (0.0.5)
ruby_smb (3.3.1)
bindata
openssl-ccm
openssl-cmac
rubyntlm
windows_error (>= 0.1.4)
rubyntlm (0.6.3)
rubyzip (2.3.2)
sawyer (0.9.2)
@@ -565,6 +571,7 @@ DEPENDENCIES
rspec-rerun
rubocop
ruby-prof (= 1.4.2)
ruby_smb!
simplecov (= 0.18.2)
test-prof
timecop
-13
View File
@@ -45,19 +45,6 @@ module Msf
def on_client_connect(client)
vprint_status("Received SMB connection from #{client.peerhost}")
end
def cleanup_service
if service
begin
self.service.stop
self.service.wait
true
rescue ::Exception => e
print_error(e.message)
false
end
end
end
end
end
end
+22 -10
View File
@@ -28,9 +28,9 @@ module Msf
register_options(
[
OptPort.new('SRVPORT', [ true, 'The local port to listen on.', 445 ]),
OptString.new('SHARE', [ false, 'Share (Default Random)']),
OptString.new('FILE_NAME', [ false, 'File name to share (Default Random)']),
OptString.new('FOLDER_NAME', [ false, 'Folder name to share (Default none)'])
OptString.new('SHARE', [ false, 'Share (Default: random); cannot contain spaces or slashes'], regex: /^[^\s\/\\]*$/),
OptString.new('FILE_NAME', [ false, 'File name to share (Default: random)']),
OptString.new('FOLDER_NAME', [ false, 'Folder name to share (Default: none)'])
], Msf::Exploit::Remote::SMB::Server::Share)
register_advanced_options(
[
@@ -58,12 +58,18 @@ module Msf
super(opts)
virtual_disk = RubySMB::Server::Share::Provider::VirtualDisk.new(@share)
# the virtual disk expects the path to use the native File::SEPARATOR so normalize on that here
virtual_disk.add_dynamic_file("#{@folder_name}#{File::SEPARATOR}#{@file_name}".gsub(/\/|\\/, File::SEPARATOR)) do |client, _smb_session|
get_file_contents(client: client)
if share.present?
if service.shares.key?(share)
fail_with(Msf::Module::Failure::BadConfig, "The specified SMB share '#{share}' already exists.")
end
virtual_disk = RubySMB::Server::Share::Provider::VirtualDisk.new(share)
# the virtual disk expects the path to use the native File::SEPARATOR so normalize on that here
virtual_disk.add_dynamic_file("#{@folder_name}#{File::SEPARATOR}#{@file_name}".gsub(/\/|\\/, File::SEPARATOR)) do |client, _smb_session|
get_file_contents(client: client)
end
service.add_share(virtual_disk)
end
service.add_share(virtual_disk)
end
# Setups the server configuration.
@@ -71,8 +77,8 @@ module Msf
super
self.folder_name = datastore['FOLDER_NAME']
self.share = datastore['SHARE'] || Rex::Text.rand_text_alpha(4 + rand(3))
self.file_name = datastore['FILE_NAME'] || Rex::Text.rand_text_alpha(4 + rand(3))
self.share = datastore['SHARE'].present? ? datastore['SHARE'] : Rex::Text.rand_text_alpha(4 + rand(3))
self.file_name = datastore['FILE_NAME'].present? ? datastore['FILE_NAME'] : Rex::Text.rand_text_alpha(4 + rand(3))
end
# Builds the UNC Name for the shared file
@@ -92,6 +98,12 @@ module Msf
def get_file_contents(client:)
file_contents
end
def cleanup
self.service.remove_share(share) if share.present?
super
end
end
end
end
+1 -5
View File
@@ -18,7 +18,7 @@ class Server
include Proto
extend Forwardable
def_delegators :@rubysmb_server, :add_share, :dialects, :guid, :shares
def_delegators :@rubysmb_server, :dialects, :guid, :shares, :add_share, :remove_share
def initialize(port = 445, listen_host = '0.0.0.0', context = {}, comm = nil, gss_provider: nil, logger: nil)
self.listen_host = listen_host
@@ -99,10 +99,6 @@ class Server
@listener_thread.join if @listener_thread
end
def add_share(share_provider, *arg)
end
attr_accessor :context, :comm, :listener, :listen_host, :listen_port, :on_client_connect_proc
end
+1 -1
View File
@@ -59,7 +59,7 @@ class ServiceManager < Hash
return inst
end
inst = klass.new(*args)
inst = klass.new(*args, **kwargs)
als = inst.alias
# Find an alias that isn't taken.