Skip to content

Commit

Permalink
Refactor smb_lookupsid module to use RubySMB
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanusz-r7 committed May 8, 2024
1 parent 1b9f242 commit 8e616e0
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 326 deletions.
24 changes: 1 addition & 23 deletions lib/msf/core/exploit/remote/ms_icpr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ module Msf

module Exploit::Remote::MsIcpr

include Msf::Exploit::Remote::SMB::Client::Authenticated
include Msf::Exploit::Remote::MsIpc
include Msf::Exploit::Remote::DCERPC
include Msf::Auxiliary::Report

# [2.2.2.7.7.4 szOID_NTDS_CA_SECURITY_EXT](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wcce/e563cff8-1af6-4e6f-a655-7571ca482e71)
OID_NTDS_CA_SECURITY_EXT = '1.3.6.1.4.1.311.25.2'.freeze
Expand Down Expand Up @@ -109,27 +108,6 @@ def request_certificate(opts = {})

module_function

def connect_ipc
begin
connect
rescue Rex::ConnectionError => e
raise MsIcprConnectionError, e.message
end

begin
smb_login
rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError => e
raise MsIcprAuthenticationError, "Unable to authenticate ([#{e.class}] #{e})."
end
report_service(icpr_service_data)

begin
simple.client.tree_connect("\\\\#{sock.peerhost}\\IPC$")
rescue RubySMB::Error::RubySMBError => e
raise MsIcprConnectionError, "Unable to connect to the remote IPC$ share ([#{e.class}] #{e})."
end
end

def connect_icpr(tree)
vprint_status('Connecting to ICertPassage (ICPR) Remote Protocol')
icpr = tree.open_file(filename: 'cert', write: true, read: true)
Expand Down
54 changes: 54 additions & 0 deletions lib/msf/core/exploit/remote/ms_ipc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
###
#
# This mixin provides a method to connect to an IPC share on the remote SMB server.
#
# -*- coding: binary -*-

module Msf

module Exploit::Remote::MsIpc

include Msf::Exploit::Remote::SMB::Client::Authenticated
include Msf::Auxiliary::Report

class MsIpcError < StandardError; end
class MsIpcConnectionError < MsIpcError; end
class MsIpcAuthenticationError < MsIpcError; end

module_function

def connect_ipc
begin
if session
self.simple = session.simple_client
ipc_tree = simple.client.tree_connect("\\\\#{simple.peerhost}\\IPC$")
else
connect
# smb_login does a tree_connect to the IPC share already.
ipc_tree = smb_login
end
rescue Rex::ConnectionError => e
raise MsIpcConnectionError, e.message
rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError => e
raise MsIpcAuthenticationError, "Unable to authenticate ([#{e.class}] #{e})."
end

report_service(
host: simple.peerhost,
port: simple.peerport,
host_name: simple.client.default_name,
proto: 'tcp',
name: 'smb',
info: "Module: #{fullname}, last negotiated version: SMBv#{simple.client.negotiated_smb_version} (dialect = #{simple.client.dialect})"
)

ipc_tree
end

def disconnect_ipc(ipc_tree)
ipc_tree.disconnect! if ipc_tree
end

end

end
136 changes: 136 additions & 0 deletions lib/msf/core/exploit/remote/ms_lsarpc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
###
#
# This mixin provides methods to open, and close policy handles, and to query policy info on the remote SMB server.
#
# -*- coding: binary -*-

module Msf

module Exploit::Remote::MsLsarpc

include Msf::Exploit::Remote::MsIpc

class MsLsarpcError < StandardError; end
class MsLsarpcConnectionError < MsLsarpcError; end
class MsLsarpcAuthenticationError < MsLsarpcError; end
class MsLsarpcUnexpectedReplyError < MsLsarpcError; end

LSA_UUID = '12345778-1234-abcd-ef00-0123456789ab'.freeze
LSA_VERS = '0.0'.freeze
LSARPC_ENDPOINT = RubySMB::Dcerpc::Lsarpc.freeze

# The currently connected LSARPC pipe
attr_reader :lsarpc_pipe

def map_security_principal_to_string(security_principal)
case security_principal
when 1
'User'
when 2
'Group'
when 3
'Domain'
when 4
'Alias'
when 5
'Well-Known Group'
when 6
'Deleted Account'
when 7
'Invalid'
when 8
'Unknown'
when '9'
'Computer'
when 10
'Label'
else
'Unknown - Not a valid Security Principal'
end
end

def open_policy_2(impersonation_level, security_context_tracking_mode, access_mask)
object_attributes = LSARPC_ENDPOINT::LsaprObjectAttributes.new(
{
len: 24,
root_directory: nil,
object_name: nil,
attributes: 0,
security_descriptor: nil,
security_quality_of_service: {
len: 12,
impersonation_level: impersonation_level,
security_context_tracking_mode: security_context_tracking_mode,
effective_only: 0
}
}
)

self.lsarpc_pipe.lsar_open_policy_2(
system_name: simple.peerhost,
object_attributes: object_attributes,
access_mask: access_mask
)
end

def query_information_policy(policy_handle, information_class)
self.lsarpc_pipe.lsar_query_information_policy(
policy_handle: policy_handle,
information_class: information_class
)
end

def lookup_sids(policy_handle, sids_buffer, lookup_level)
self.lsarpc_pipe.lsar_lookup_sids(
policy_handle: policy_handle,
sid_enum_buffer: {
num_entries: sids_buffer.count,
sid_info: sids_buffer
},
lookup_level: lookup_level
)
end

def close_policy(policy_handle)
self.lsarpc_pipe.lsar_close_handle(
policy_handle: policy_handle
) if (self.lsarpc_pipe && policy_handle)
end

def disconnect_lsarpc
begin
self.lsarpc_pipe.close if self.lsarpc_pipe&.is_connected?
rescue RubySMB::Error::UnexpectedStatusCode => _e
# noop - Encountered when trying to close LSARPC pipe vs. Samba
end
end

module_function

def connect_lsarpc(tree)
begin
vprint_status('Connecting to LSARPC')
self.lsarpc_pipe = tree.open_file(filename: 'LSARPC', write: true, read: true)

raise MsLsarpcConnectionError.new('Could not open LSARPC pipe on remote SMB server.') unless lsarpc_pipe

self.lsarpc_pipe.extend(LSARPC_ENDPOINT) unless lsarpc_pipe.is_a?(LSARPC_ENDPOINT)

vprint_status('Binding to \\LSARPC...')
self.lsarpc_pipe.bind(endpoint: LSARPC_ENDPOINT)
vprint_good('Bound to \\LSARPC')

self.lsarpc_pipe
rescue RubySMB::Dcerpc::Error::FaultError => e
elog(e.message, error: e)
raise MsLsarpcUnexpectedReplyError, "Connection failed (DCERPC fault: #{e.status_name})"
end
end

protected

attr_writer :lsarpc_pipe

end

end
30 changes: 1 addition & 29 deletions lib/msf/core/exploit/remote/ms_samr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Msf

module Exploit::Remote::MsSamr

include Msf::Exploit::Remote::SMB::Client::Authenticated
include Msf::Exploit::Remote::MsIpc

class MsSamrError < StandardError; end
class MsSamrConnectionError < MsSamrError; end
Expand All @@ -22,34 +22,6 @@ class MsSamrBadConfigError < MsSamrError; end

module_function

def connect_ipc
begin
connect
rescue Rex::ConnectionError => e
raise MsSamrConnectionError, e.message
end

begin
smb_login
rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError => e
raise MsSamrAuthenticationError, "Unable to authenticate ([#{e.class}] #{e})."
end
report_service(
host: rhost,
port: rport,
host_name: simple.client.default_name,
proto: 'tcp',
name: 'smb',
info: "Module: #{fullname}, last negotiated version: SMBv#{simple.client.negotiated_smb_version} (dialect = #{simple.client.dialect})"
)

begin
simple.client.tree_connect("\\\\#{sock.peerhost}\\IPC$")
rescue RubySMB::Error::RubySMBError => e
raise MsSamrConnectionError, "Unable to connect to the remote IPC$ share ([#{e.class}] #{e})."
end
end

def connect_samr(tree)
begin
vprint_status('Connecting to Security Account Manager (SAM) Remote Protocol')
Expand Down
4 changes: 2 additions & 2 deletions lib/msf/core/exploit/remote/smb/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,10 @@ def smb_login(simple_client = self.simple)
datastore['NTLM::SendNTLM'],
datastore['SMB::Native_OS'],
datastore['SMB::Native_LM'],
{:use_spn => datastore['NTLM::SendSPN'], :name => self.rhost}
{ :use_spn => datastore['NTLM::SendSPN'], :name => simple_client.peerhost }
)
# XXX: Any reason to connect to the IPC$ share in this method?
simple_client.connect("\\\\#{datastore['RHOST']}\\IPC$")
simple_client.client.tree_connect("\\\\#{simple_client.peerhost}\\IPC$")
end

# This method returns the native operating system of the peer
Expand Down
Loading

0 comments on commit 8e616e0

Please sign in to comment.