Module: RubySMB::Dcerpc

Included in:
Client, SMB1::Pipe, SMB2::Pipe
Defined in:
lib/ruby_smb/dcerpc/error.rb,
lib/ruby_smb/dcerpc.rb,
lib/ruby_smb/dcerpc/epm.rb,
lib/ruby_smb/dcerpc/bind.rb,
lib/ruby_smb/dcerpc/drsr.rb,
lib/ruby_smb/dcerpc/gkdi.rb,
lib/ruby_smb/dcerpc/icpr.rb,
lib/ruby_smb/dcerpc/samr.rb,
lib/ruby_smb/dcerpc/uuid.rb,
lib/ruby_smb/dcerpc/dfsnm.rb,
lib/ruby_smb/dcerpc/client.rb,
lib/ruby_smb/dcerpc/efsrpc.rb,
lib/ruby_smb/dcerpc/lsarpc.rb,
lib/ruby_smb/dcerpc/ptypes.rb,
lib/ruby_smb/dcerpc/srvsvc.rb,
lib/ruby_smb/dcerpc/svcctl.rb,
lib/ruby_smb/dcerpc/winreg.rb,
lib/ruby_smb/dcerpc/wkssvc.rb,
lib/ruby_smb/dcerpc/request.rb,
lib/ruby_smb/dcerpc/bind_ack.rb,
lib/ruby_smb/dcerpc/netlogon.rb,
lib/ruby_smb/dcerpc/response.rb,
lib/ruby_smb/dcerpc/rpc_auth3.rb,
lib/ruby_smb/dcerpc/p_result_t.rb,
lib/ruby_smb/dcerpc/pdu_header.rb,
lib/ruby_smb/dcerpc/port_any_t.rb,
lib/ruby_smb/dcerpc/sec_trailer.rb,
lib/ruby_smb/dcerpc/epm/epm_twrt.rb,
lib/ruby_smb/dcerpc/print_system.rb,
lib/ruby_smb/dcerpc/samr/rpc_sid.rb,
lib/ruby_smb/dcerpc/alter_context.rb,
lib/ruby_smb/dcerpc/p_cont_list_t.rb,
lib/ruby_smb/dcerpc/p_syntax_id_t.rb,
lib/ruby_smb/dcerpc/winreg/regsam.rb,
lib/ruby_smb/dcerpc/p_result_list_t.rb,
lib/ruby_smb/dcerpc/alter_context_resp.rb,
lib/ruby_smb/dcerpc/drsr/drs_extensions.rb,
lib/ruby_smb/dcerpc/gkdi/gkdi_ffc_dh_key.rb,
lib/ruby_smb/dcerpc/drsr/drs_bind_request.rb,
lib/ruby_smb/dcerpc/svcctl/service_status.rb,
lib/ruby_smb/dcerpc/drsr/drs_bind_response.rb,
lib/ruby_smb/dcerpc/rrp_rpc_unicode_string.rb,
lib/ruby_smb/dcerpc/drsr/drs_unbind_request.rb,
lib/ruby_smb/dcerpc/epm/epm_ept_map_request.rb,
lib/ruby_smb/dcerpc/rpc_security_attributes.rb,
lib/ruby_smb/dcerpc/winreg/enum_key_request.rb,
lib/ruby_smb/dcerpc/winreg/open_key_request.rb,
lib/ruby_smb/dcerpc/winreg/save_key_request.rb,
lib/ruby_smb/dcerpc/drsr/drs_unbind_response.rb,
lib/ruby_smb/dcerpc/epm/epm_ept_map_response.rb,
lib/ruby_smb/dcerpc/winreg/close_key_request.rb,
lib/ruby_smb/dcerpc/winreg/enum_key_response.rb,
lib/ruby_smb/dcerpc/winreg/open_key_response.rb,
lib/ruby_smb/dcerpc/winreg/save_key_response.rb,
lib/ruby_smb/dcerpc/gkdi/gkdi_get_key_request.rb,
lib/ruby_smb/dcerpc/samr/samr_connect_request.rb,
lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb,
lib/ruby_smb/dcerpc/winreg/close_key_response.rb,
lib/ruby_smb/dcerpc/winreg/create_key_request.rb,
lib/ruby_smb/dcerpc/winreg/enum_value_request.rb,
lib/ruby_smb/dcerpc/gkdi/gkdi_get_key_response.rb,
lib/ruby_smb/dcerpc/samr/samr_connect_response.rb,
lib/ruby_smb/dcerpc/winreg/create_key_response.rb,
lib/ruby_smb/dcerpc/winreg/enum_value_response.rb,
lib/ruby_smb/dcerpc/winreg/query_value_request.rb,
lib/ruby_smb/dcerpc/gkdi/gkdi_ffc_dh_parameters.rb,
lib/ruby_smb/dcerpc/samr/samr_open_user_request.rb,
lib/ruby_smb/dcerpc/winreg/query_value_response.rb,
lib/ruby_smb/dcerpc/drsr/drs_crack_names_request.rb,
lib/ruby_smb/dcerpc/gkdi/gkdi_group_key_envelope.rb,
lib/ruby_smb/dcerpc/samr/samr_open_group_request.rb,
lib/ruby_smb/dcerpc/samr/samr_open_user_response.rb,
lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request.rb,
lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb,
lib/ruby_smb/dcerpc/drsr/drs_crack_names_response.rb,
lib/ruby_smb/dcerpc/samr/sampr_domain_info_buffer.rb,
lib/ruby_smb/dcerpc/samr/samr_delete_user_request.rb,
lib/ruby_smb/dcerpc/samr/samr_open_domain_request.rb,
lib/ruby_smb/dcerpc/samr/samr_open_group_response.rb,
lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response.rb,
lib/ruby_smb/dcerpc/svcctl/delete_service_request.rb,
lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb,
lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb,
lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb,
lib/ruby_smb/dcerpc/samr/samr_close_handle_request.rb,
lib/ruby_smb/dcerpc/samr/samr_delete_user_response.rb,
lib/ruby_smb/dcerpc/samr/samr_open_domain_response.rb,
lib/ruby_smb/dcerpc/svcctl/control_service_request.rb,
lib/ruby_smb/dcerpc/svcctl/delete_service_response.rb,
lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb,
lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb,
lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb,
lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_request.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_lookup_sids_request.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_open_policy_request.rb,
lib/ruby_smb/dcerpc/samr/samr_close_handle_response.rb,
lib/ruby_smb/dcerpc/svcctl/control_service_response.rb,
lib/ruby_smb/dcerpc/svcctl/create_service_w_request.rb,
lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb,
lib/ruby_smb/dcerpc/winreg/get_key_security_request.rb,
lib/ruby_smb/dcerpc/winreg/set_key_security_request.rb,
lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_response.rb,
lib/ruby_smb/dcerpc/icpr/cert_server_request_request.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_close_handle_request.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_lookup_sids_response.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_open_policy2_request.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_open_policy_response.rb,
lib/ruby_smb/dcerpc/netlogon/domain_controller_infow.rb,
lib/ruby_smb/dcerpc/svcctl/create_service_w_response.rb,
lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb,
lib/ruby_smb/dcerpc/winreg/get_key_security_response.rb,
lib/ruby_smb/dcerpc/winreg/set_key_security_response.rb,
lib/ruby_smb/dcerpc/icpr/cert_server_request_response.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_close_handle_response.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_open_policy2_response.rb,
lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb,
lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request.rb,
lib/ruby_smb/dcerpc/dfsnm/netr_dfs_add_std_root_request.rb,
lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb,
lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb,
lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response.rb,
lib/ruby_smb/dcerpc/wkssvc/netr_wksta_user_enum_request.rb,
lib/ruby_smb/dcerpc/dfsnm/netr_dfs_add_std_root_response.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_open_file_raw_request.rb,
lib/ruby_smb/dcerpc/netlogon/dsr_get_dc_name_ex2_request.rb,
lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb,
lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb,
lib/ruby_smb/dcerpc/wkssvc/netr_wksta_user_enum_response.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_open_file_raw_response.rb,
lib/ruby_smb/dcerpc/netlogon/dsr_get_dc_name_ex2_response.rb,
lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_request.rb,
lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb,
lib/ruby_smb/dcerpc/dfsnm/netr_dfs_remove_std_root_request.rb,
lib/ruby_smb/dcerpc/samr/samr_change_password_user_request.rb,
lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_request.rb,
lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_response.rb,
lib/ruby_smb/dcerpc/samr/samr_get_members_in_group_request.rb,
lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb,
lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb,
lib/ruby_smb/dcerpc/dfsnm/netr_dfs_remove_std_root_response.rb,
lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_request.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_decrypt_file_srv_request.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_encrypt_file_srv_request.rb,
lib/ruby_smb/dcerpc/samr/samr_change_password_user_response.rb,
lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_response.rb,
lib/ruby_smb/dcerpc/samr/samr_get_members_in_group_response.rb,
lib/ruby_smb/dcerpc/samr/samr_set_information_user2_request.rb,
lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb,
lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_response.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_decrypt_file_srv_response.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_encrypt_file_srv_response.rb,
lib/ruby_smb/dcerpc/samr/samr_create_user2_in_domain_request.rb,
lib/ruby_smb/dcerpc/samr/samr_lookup_names_in_domain_request.rb,
lib/ruby_smb/dcerpc/samr/samr_set_information_user2_response.rb,
lib/ruby_smb/dcerpc/samr/samr_create_user2_in_domain_response.rb,
lib/ruby_smb/dcerpc/samr/samr_lookup_names_in_domain_response.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_query_users_on_file_request.rb,
lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb,
lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb,
lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb,
lib/ruby_smb/dcerpc/samr/samr_query_information_domain_request.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_query_users_on_file_response.rb,
lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb,
lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb,
lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb,
lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request.rb,
lib/ruby_smb/dcerpc/samr/samr_query_information_domain_response.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_query_recovery_agents_request.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_query_information_policy_request.rb,
lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response.rb,
lib/ruby_smb/dcerpc/efsrpc/efs_rpc_query_recovery_agents_response.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_query_information_policy2_request.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_query_information_policy_response.rb,
lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_request.rb,
lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request.rb,
lib/ruby_smb/dcerpc/lsarpc/lsar_query_information_policy2_response.rb,
lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_request.rb,
lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_response.rb,
lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response.rb,
lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_response.rb,
lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_request.rb,
lib/ruby_smb/dcerpc/samr/samr_unicode_change_password_user2_response.rb,
lib/ruby_smb/dcerpc/samr/samr_enumerate_domains_in_sam_server_request.rb,
lib/ruby_smb/dcerpc/samr/samr_enumerate_domains_in_sam_server_response.rb,
lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_request.rb,
lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_response.rb

Overview

Contains all the DCERPC specific Error classes.

Defined Under Namespace

Modules: Dfsnm, Drsr, Efsrpc, Epm, Error, Fault, Gkdi, Icpr, Lsarpc, Ndr, Netlogon, PTypes, PrintSystem, Samr, Srvsvc, Svcctl, Winreg, Wkssvc Classes: AlterContext, AlterContextResp, Bind, BindAck, Client, PContElemT, PContListT, PDUHeader, PResultListT, PResultT, PSyntaxIdT, PortAnyT, PrpcSecurityAttributes, PrpcUnicodeString, PrrpUnicodeString, Request, Response, RpcAuth3, RpcSecurityAttributes, RpcSecurityDescriptor, RpcUnicodeString, RpcUnicodeStringConfVarArray, RrpUnicodeString, SecTrailer, Uuid

Constant Summary collapse

MAX_XMIT_FRAG =
4280
MAX_RECV_FRAG =
4280
RPC_C_AUTHN_LEVEL_DEFAULT =
0
RPC_C_AUTHN_LEVEL_NONE =
1
RPC_C_AUTHN_LEVEL_CONNECT =
2
RPC_C_AUTHN_LEVEL_CALL =
3
RPC_C_AUTHN_LEVEL_PKT =
4
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY =
5
RPC_C_AUTHN_LEVEL_PKT_PRIVACY =
6
RPC_C_AUTHN_NONE =
0x00
RPC_C_AUTHN_GSS_NEGOTIATE =
0x09
RPC_C_AUTHN_WINNT =
0x0A
RPC_C_AUTHN_GSS_SCHANNEL =
0x0E
RPC_C_AUTHN_GSS_KERBEROS =
0x10
RPC_C_AUTHN_NETLOGON =
0x44
RPC_C_AUTHN_DEFAULT =
0xFF
DCE_C_AUTHZ_NAME =
1
DCE_C_AUTHZ_DCE =
2

Instance Method Summary collapse

Instance Method Details

#add_auth_verifier(req, auth) ⇒ Object

Add the authentication verifier to the packet. This includes a sec trailer and the actual authentication data.



355
356
357
358
359
360
361
362
363
364
365
# File 'lib/ruby_smb/dcerpc.rb', line 355

def add_auth_verifier(req, auth)
  req.sec_trailer = {
    auth_type: @auth_type,
    auth_level: @auth_level,
    auth_context_id: @ctx_id + @auth_ctx_id_base
  }
  req.auth_value = auth
  req.pdu_header.auth_length = auth.length

  nil
end

#auth_provider_complete_handshake(response, options) ⇒ Object

Send a rpc_auth3 PDU that ends the authentication handshake. This function should be overriden for other providers (e.g. Kerberos, etc.)



158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/ruby_smb/dcerpc.rb', line 158

def auth_provider_complete_handshake(response, options)
  auth3 = process_ntlm_type2(response.auth_value)

  rpc_auth3 = RpcAuth3.new
  add_auth_verifier(rpc_auth3, auth3)
  rpc_auth3.pdu_header.call_id = @call_id

  # The server should not respond
  send_packet(rpc_auth3)
  @call_id += 1

  nil
end

#auth_provider_decrypt_and_verify(dcerpc_response) ⇒ Boolean

Decrypt the value in dcerpc_req.stub, and validate its signature. This function modifies the request object in-place, and returns whether the signature was valid. This function should be overriden for other providers (e.g. Kerberos, etc.)

Raises:

  • ArgumentError If the auth type is not NTLM



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/ruby_smb/dcerpc.rb', line 118

def auth_provider_decrypt_and_verify(dcerpc_response)
  auth_type = dcerpc_response.sec_trailer.auth_type
  auth_level = dcerpc_response.sec_trailer.auth_level
  unless [RPC_C_AUTHN_WINNT, RPC_C_AUTHN_DEFAULT].include?(auth_type)
    raise ArgumentError, "Unsupported Auth Type: #{auth_type}"
  end
  signature = dcerpc_response.auth_value
  if auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY
    encrypted_stub = get_response_full_stub(dcerpc_response)
    plaintext = @ntlm_client.session.unseal_message(encrypted_stub)
    set_decrypted_packet(dcerpc_response, plaintext)
  end
  data_to_check = dcerpc_response.stub.to_binary_s
  if @ntlm_client.flags & NTLM::NEGOTIATE_FLAGS[:EXTENDED_SECURITY] != 0
    data_to_check = dcerpc_response.to_binary_s[0..-(dcerpc_response.pdu_header.auth_length + 1)]
  end

  @ntlm_client.session.verify_signature(signature, data_to_check)
end

#auth_provider_encrypt_and_sign(dcerpc_req) ⇒ Object

Encrypt the value in dcerpc_req.stub, and add a valid signature to the request. This function modifies the request object in-place, and does not return anything. This function should be overriden for other providers (e.g. Kerberos, etc.)



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/ruby_smb/dcerpc.rb', line 81

def auth_provider_encrypt_and_sign(dcerpc_req)
  auth_type = dcerpc_req.sec_trailer.auth_type
  auth_level = dcerpc_req.sec_trailer.auth_level
  unless [RPC_C_AUTHN_WINNT, RPC_C_AUTHN_DEFAULT].include?(auth_type)
    raise ArgumentError, "Unsupported Auth Type: #{auth_type}"
  end
  plaintext = dcerpc_req.stub.to_binary_s
  pad_length = get_auth_padding_length(plaintext.length)
  dcerpc_req.auth_pad = "\x00" * pad_length
  data_to_sign = plain_stub_with_padding = dcerpc_req.stub.to_binary_s + dcerpc_req.auth_pad.to_binary_s
  dcerpc_req.sec_trailer.auth_pad_length = pad_length
  if @ntlm_client.flags & NTLM::NEGOTIATE_FLAGS[:EXTENDED_SECURITY] != 0
    data_to_sign = dcerpc_req.to_binary_s[0..-(dcerpc_req.pdu_header.auth_length + 1)]
  end

  if auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY
    encrypted = @ntlm_client.session.seal_message(plain_stub_with_padding)
    set_encrypted_packet(dcerpc_req, encrypted, pad_length)
  end
  signature = @ntlm_client.session.sign_message(data_to_sign)

  set_signature_on_packet(dcerpc_req, signature)
end

#auth_provider_initObject

Initialize the auth provider using NTLM. This function should be overriden for other providers (e.g. Kerberos, etc.)

Raises:

  • ArgumentError If @ntlm_client isn't initialized with a username and password.



70
71
72
73
74
75
# File 'lib/ruby_smb/dcerpc.rb', line 70

def auth_provider_init
  raise ArgumentError, "NTLM Client not initialized. Username and password must be provided" unless @ntlm_client
  type1_message = @ntlm_client.init_context

  type1_message.serialize
end

#bind(options = {}) ⇒ BindAck

Bind to the remote server interface endpoint. It takes care of adding the necessary authentication verifier if :auth_level is set to anything different than RPC_C_AUTHN_LEVEL_NONE

Options Hash (options):

  • :endpoint (Module)

    the endpoint to bind to. This must be a Dcerpc class with UUID, VER_MAJOR and VER_MINOR constants defined.

  • :auth_level (Integer)

    the authentication level

  • :auth_type (Integer)

    the authentication type

Raises:

  • (Error::InvalidPacket)

    if an invalid packet is received

  • (Error::BindError)

    if the response is not a BindAck packet or if the Bind result code is not ACCEPTANCE

  • (ArgumentError)

    if :auth_type is unknown

  • (NotImplementedError)

    if :auth_type is not implemented (yet)



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/ruby_smb/dcerpc.rb', line 192

def bind(options={})
  @call_id ||= 1
  bind_req = Bind.new(options)
  bind_req.pdu_header.call_id = @call_id
  auth_type = options.fetch(:auth_type) { RPC_C_AUTHN_WINNT }
  auth_level = options.fetch(:auth_level) { RPC_C_AUTHN_LEVEL_NONE }

  force_set_auth_params(auth_type, auth_level)

  if @auth_level != RPC_C_AUTHN_LEVEL_NONE
    @ctx_id            = 0
    @auth_ctx_id_base  = rand(0xFFFFFFFF)
    auth = auth_provider_init
    add_auth_verifier(bind_req, auth)
  end

  send_packet(bind_req)
  begin
    dcerpc_response = recv_struct(BindAck)
  rescue Error::InvalidPacket
    raise Error::BindError # raise the more context-specific BindError
  end
  # TODO: see if BindNack response should be handled too

  res_list = dcerpc_response.p_result_list
  if res_list.n_results == 0 ||
     res_list.p_results[0].result != BindAck::ACCEPTANCE
    raise Error::BindError,
      "Bind Failed (Result: #{res_list.p_results[0].result}, Reason: #{res_list.p_results[0].reason})"
  end
  self.max_buffer_size = dcerpc_response.max_xmit_frag
  @call_id = dcerpc_response.pdu_header.call_id

  if auth_level != RPC_C_AUTHN_LEVEL_NONE
    # The number of legs needed to build the security context is defined
    # by the security provider
    # (see [2.2.1.1.7 Security Providers](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/d4097450-c62f-484b-872f-ddf59a7a0d36))
    auth_provider_complete_handshake(dcerpc_response, options)
  end

  dcerpc_response
end

#force_set_auth_params(auth_type, auth_level) ⇒ Object



172
173
174
175
# File 'lib/ruby_smb/dcerpc.rb', line 172

def force_set_auth_params(auth_type, auth_level)
  @auth_type = auth_type
  @auth_level = auth_level
end

#get_auth_padding_length(plaintext_len) ⇒ Object



265
266
267
# File 'lib/ruby_smb/dcerpc.rb', line 265

def get_auth_padding_length(plaintext_len)
  (16 - (plaintext_len % 16)) % 16
end

#get_response_full_stub(dcerpc_response) ⇒ String

Get the response's full stub value (which will include the auth-pad)



108
109
110
# File 'lib/ruby_smb/dcerpc.rb', line 108

def get_response_full_stub(dcerpc_response)
  dcerpc_response.stub.to_binary_s + dcerpc_response.auth_pad.to_binary_s
end

#handle_integrity_privacy(dcerpc_response, auth_level:, auth_type:, raise_signature_error: false) ⇒ Object

Process the security context received in a response. It decrypts the encrypted stub if :auth_level is set to anything different than RPC_C_AUTHN_LEVEL_PKT_PRIVACY. It also checks the packet signature and raises an InvalidPacket error if it fails. Note that the exception is disabled by default and can be enabled with the :raise_signature_error option

Raises:

  • (NotImplementedError)

    if :auth_type is not implemented (yet)

  • (Error::CommunicationError)

    if socket-related error occurs



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/ruby_smb/dcerpc.rb', line 331

def handle_integrity_privacy(dcerpc_response, auth_level:, auth_type:, raise_signature_error: false)
  unless [RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_PKT_PRIVACY].include?(auth_level)
    raise ArgumentError, "Unsupported Auth Type: #{auth_type}"
  end
  signature_valid = auth_provider_decrypt_and_verify(dcerpc_response)

  unless signature_valid
    if raise_signature_error
      raise Error::InvalidPacket.new(
        "Wrong packet signature received (set `raise_signature_error` to false to ignore)"
      )
    end
  end

  @call_id += 1

  nil
end

#max_buffer_size=(value) ⇒ Object



235
236
237
# File 'lib/ruby_smb/dcerpc.rb', line 235

def max_buffer_size=(value)
  @tree.client.max_buffer_size = value
end

#process_ntlm_type2(type2_message) ⇒ String

Completes local initialisation of @ntlm_client using the server's response



142
143
144
145
146
147
148
149
150
151
# File 'lib/ruby_smb/dcerpc.rb', line 142

def process_ntlm_type2(type2_message)
  ntlmssp_offset = type2_message.index('NTLMSSP')
  type2_blob = type2_message.slice(ntlmssp_offset..-1)
  type2_b64_message = [type2_blob].pack('m')
  type3_message = @ntlm_client.init_context(type2_b64_message)
  auth3 = type3_message.serialize

  @session_key = @ntlm_client.session_key
  auth3
end

#recv_struct(struct) ⇒ Object

Receive a packet from the remote host and parse it according to struct



242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/ruby_smb/dcerpc.rb', line 242

def recv_struct(struct)
  raw_response = read
  begin
    response = struct.read(raw_response)
  rescue IOError
    raise Error::InvalidPacket, "Error reading the #{struct} response"
  end
  unless response.pdu_header.ptype == struct::PTYPE
    raise Error::InvalidPacket, "Not a #{struct} packet"
  end

  response
end

#send_packet(packet) ⇒ Object

Send a packet to the remote host

Raises:



260
261
262
263
# File 'lib/ruby_smb/dcerpc.rb', line 260

def send_packet(packet)
  write(data: packet.to_binary_s)
  nil
end

#set_decrypted_packet(dcerpc_response, decrypted_stub) ⇒ Object



309
310
311
312
313
314
315
# File 'lib/ruby_smb/dcerpc.rb', line 309

def set_decrypted_packet(dcerpc_response, decrypted_stub)
  unless decrypted_stub.empty?
    pad_length = dcerpc_response.sec_trailer.auth_pad_length.to_i
    dcerpc_response.stub = decrypted_stub[0..-(pad_length + 1)]
    dcerpc_response.auth_pad = decrypted_stub[-(pad_length + 1)..-1]
  end
end

#set_encrypted_packet(dcerpc_req, encrypted_stub, pad_length) ⇒ Object



299
300
301
302
303
304
305
306
307
# File 'lib/ruby_smb/dcerpc.rb', line 299

def set_encrypted_packet(dcerpc_req, encrypted_stub, pad_length)
  unless encrypted_stub.empty?
    dcerpc_req.enable_encrypted_stub
    dcerpc_req.stub = encrypted_stub[0..-(pad_length+1)]
    if pad_length != 0
      dcerpc_req.auth_pad = encrypted_stub[-(pad_length)..-1]
    end
  end
end

#set_integrity_privacy(dcerpc_req, auth_level:, auth_type:) ⇒ Object

Add the authentication verifier to a Request packet. This includes a sec trailer and the signature of the packet. This also encrypts the Request stub if privacy is required (:auth_level option is RPC_C_AUTHN_LEVEL_PKT_PRIVACY).

Raises:

  • (NotImplementedError)

    if :auth_type is not implemented (yet)

  • (ArgumentError)

    if :auth_type is unknown



278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/ruby_smb/dcerpc.rb', line 278

def set_integrity_privacy(dcerpc_req, auth_level:, auth_type:)
  unless [RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_LEVEL_PKT_PRIVACY].include?(auth_level)
    raise ArgumentError, "Unsupported Auth Type: #{auth_type}"
  end

  dcerpc_req.sec_trailer = {
    auth_type: auth_type,
    auth_level: auth_level,
    auth_context_id: @ctx_id + @auth_ctx_id_base
  }
  dcerpc_req.auth_value = ' ' * 16
  dcerpc_req.pdu_header.auth_length = 16

  auth_provider_encrypt_and_sign(dcerpc_req)
end

#set_signature_on_packet(dcerpc_req, signature) ⇒ Object



294
295
296
297
# File 'lib/ruby_smb/dcerpc.rb', line 294

def set_signature_on_packet(dcerpc_req, signature)
  dcerpc_req.auth_value = signature
  dcerpc_req.pdu_header.auth_length = signature.size
end