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/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/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/pdu_header.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/p_syntax_id_t.rb,
lib/ruby_smb/dcerpc/winreg/regsam.rb,
lib/ruby_smb/dcerpc/drsr/drs_extensions.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/encrypting_file_system.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/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/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/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/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/samr_delete_user_request.rb,
lib/ruby_smb/dcerpc/samr/samr_open_domain_request.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/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/drsr/drs_get_nc_changes_response.rb,
lib/ruby_smb/dcerpc/icpr/cert_server_request_request.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/icpr/cert_server_request_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/dfsnm/netr_dfs_add_std_root_response.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/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_get_alias_membership_request.rb,
lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_response.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/samr/samr_get_alias_membership_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/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/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/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_enumerate_users_in_domain_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/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_enumerate_domains_in_sam_server_request.rb,
lib/ruby_smb/dcerpc/samr/samr_enumerate_domains_in_sam_server_response.rb,
lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_request.rb,
lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_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,
lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_request.rb,
lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_response.rb

Overview

Contains all the DCERPC specific Error classes.

Defined Under Namespace

Modules: Dfsnm, Drsr, EncryptingFileSystem, Epm, Error, Fault, Icpr, Ndr, Netlogon, PTypes, PrintSystem, Samr, Srvsvc, Svcctl, Winreg, Wkssvc Classes: 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, auth_type, auth_level) ⇒ Object

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

Parameters:

  • req (BinData::Record)

    the request to be updated

  • auth (String)

    the authentication data

  • auth_type (Integer)

    the authentication type

  • auth_level (Integer)

    the authentication level



269
270
271
272
273
274
275
276
277
278
279
# File 'lib/ruby_smb/dcerpc.rb', line 269

def add_auth_verifier(req, auth, auth_type, auth_level)
  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

#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

Parameters:

  • options (Hash) (defaults to: {})

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

Returns:

  • (BindAck)

    the BindAck response packet

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)



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/ruby_smb/dcerpc.rb', line 73

def bind(options={})
  @call_id ||= 1
  bind_req = Bind.new(options)
  bind_req.pdu_header.call_id = @call_id

  if options[:auth_level] && options[:auth_level] != RPC_C_AUTHN_LEVEL_NONE
    case options[:auth_type]
    when RPC_C_AUTHN_WINNT, RPC_C_AUTHN_DEFAULT
      @ctx_id            = 0
      @auth_ctx_id_base  = rand(0xFFFFFFFF)
      raise ArgumentError, "NTLM Client not initialized. Username and password must be provided" unless @ntlm_client
      type1_message = @ntlm_client.init_context
      auth = type1_message.serialize
    when RPC_C_AUTHN_GSS_KERBEROS, RPC_C_AUTHN_NETLOGON, RPC_C_AUTHN_GSS_NEGOTIATE
    when RPC_C_AUTHN_GSS_KERBEROS, RPC_C_AUTHN_NETLOGON, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_GSS_SCHANNEL
      # TODO
      raise NotImplementedError
    else
      raise ArgumentError, "Unsupported Auth Type: #{options[:auth_type]}"
    end
    add_auth_verifier(bind_req, auth, options[:auth_type], options[:auth_level])
  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 options[:auth_level] && options[: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://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/d4097450-c62f-484b-872f-ddf59a7a0d36))
    case options[:auth_type]
    when RPC_C_AUTHN_WINNT
      send_auth3(dcerpc_response, options[:auth_type], options[:auth_level])
    when RPC_C_AUTHN_GSS_KERBEROS, RPC_C_AUTHN_NETLOGON, RPC_C_AUTHN_GSS_NEGOTIATE
      # TODO
      raise NotImplementedError
    end
  end

  dcerpc_response
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

Parameters:

  • dcerpc_response (Response)

    the Response packet containing the security context to process

  • opts (Hash)

    the authenticaiton options: :auth_type and :auth_level. To enable errors when signature check fails, set the :raise_signature_error option to true

Raises:

  • (NotImplementedError)

    if :auth_type is not implemented (yet)

  • (Error::CommunicationError)

    if socket-related error occurs



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/ruby_smb/dcerpc.rb', line 222

def handle_integrity_privacy(dcerpc_response, auth_level:, auth_type:, raise_signature_error: false)
  decrypted_stub = ''
  if auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY
    encrypted_stub = dcerpc_response.stub.to_binary_s + dcerpc_response.auth_pad.to_binary_s
    case auth_type
    when RPC_C_AUTHN_NONE
    when RPC_C_AUTHN_WINNT, RPC_C_AUTHN_DEFAULT
      decrypted_stub = @ntlm_client.session.unseal_message(encrypted_stub)
    when RPC_C_AUTHN_NETLOGON, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_GSS_SCHANNEL, RPC_C_AUTHN_GSS_KERBEROS
      # TODO
      raise NotImplementedError
    else
      raise ArgumentError, "Unsupported Auth Type: #{auth_type}"
    end
  end

  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]
  end

  signature = dcerpc_response.auth_value
  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
  unless @ntlm_client.session.verify_signature(signature, data_to_check)
    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



129
130
131
# File 'lib/ruby_smb/dcerpc.rb', line 129

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

#process_ntlm_type2(type2_message) ⇒ Object



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

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

Parameters:

  • struct (Class)

    the structure class to parse the response with



136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/ruby_smb/dcerpc.rb', line 136

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_auth3(response, auth_type, auth_level) ⇒ Object

Send a rpc_auth3 PDU that ends the authentication handshake.

Parameters:

  • response (BindAck)

    the BindAck response packet

  • auth_type (Integer)

    the authentication type

  • auth_level (Integer)

    the authentication level

Raises:

  • (ArgumentError)

    if :auth_type is unknown

  • (NotImplementedError)

    if :auth_type is not implemented (yet)



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/ruby_smb/dcerpc.rb', line 299

def send_auth3(response, auth_type, auth_level)
  case auth_type
  when RPC_C_AUTHN_NONE
  when RPC_C_AUTHN_WINNT, RPC_C_AUTHN_DEFAULT
    auth3 = process_ntlm_type2(response.auth_value)
  when RPC_C_AUTHN_NETLOGON, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_GSS_SCHANNEL, RPC_C_AUTHN_GSS_KERBEROS
    # TODO
    raise NotImplementedError
  else
    raise ArgumentError, "Unsupported Auth Type: #{auth_type}"
  end

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

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

  nil
end

#send_packet(packet) ⇒ Object

Send a packet to the remote host

Parameters:

  • packet (BinData::Record)

    the packet to send

Raises:



154
155
156
157
# File 'lib/ruby_smb/dcerpc.rb', line 154

def send_packet(packet)
  write(data: packet.to_binary_s)
  nil
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).

Parameters:

  • dcerpc_req (Request)

    the Request packet to be updated

  • opts (Hash)

    the authenticaiton options: :auth_type and :auth_level

Raises:

  • (NotImplementedError)

    if :auth_type is not implemented (yet)

  • (ArgumentError)

    if :auth_type is unknown



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/ruby_smb/dcerpc.rb', line 168

def set_integrity_privacy(dcerpc_req, auth_level:, auth_type:)
  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

  data_to_sign = plain_stub = dcerpc_req.stub.to_binary_s + dcerpc_req.auth_pad.to_binary_s
  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

  encrypted_stub = ''
  if auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY
    case auth_type
    when RPC_C_AUTHN_NONE
    when RPC_C_AUTHN_WINNT, RPC_C_AUTHN_DEFAULT
      encrypted_stub = @ntlm_client.session.seal_message(plain_stub)
    when RPC_C_AUTHN_NETLOGON, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_GSS_SCHANNEL, RPC_C_AUTHN_GSS_KERBEROS
      # TODO
      raise NotImplementedError
    else
      raise ArgumentError, "Unsupported Auth Type: #{auth_type}"
    end
  end

  signature = @ntlm_client.session.sign_message(data_to_sign)

  unless encrypted_stub.empty?
    pad_length = dcerpc_req.sec_trailer.auth_pad_length.to_i
    dcerpc_req.enable_encrypted_stub
    dcerpc_req.stub = encrypted_stub[0..-(pad_length + 1)]
    dcerpc_req.auth_pad = encrypted_stub[-(pad_length)..-1]
  end
  dcerpc_req.auth_value = signature
  dcerpc_req.pdu_header.auth_length = signature.size
end