Module: Msf::Payload::Stager

Includes:
TransportConfig
Included in:
Osx::ReverseTcp_x64
Defined in:
lib/msf/core/payload/stager.rb

Overview

Base mixin interface for use by stagers.

Constant Summary

Constants included from Rex::Payloads::Meterpreter::UriChecksum

Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_CONN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_CONN_MAX_LEN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITP, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITW, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INIT_CONN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_MIN_LEN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_MODES, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_UUID_MIN_LEN

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from TransportConfig

#transport_config_bind_named_pipe, #transport_config_bind_tcp, #transport_config_reverse_http, #transport_config_reverse_https, #transport_config_reverse_ipv6_tcp, #transport_config_reverse_named_pipe, #transport_config_reverse_tcp, #transport_config_reverse_udp, #transport_uri_components

Methods included from UUID::Options

#generate_payload_uuid, #generate_uri_uuid_mode, #record_payload_uuid, #record_payload_uuid_url

Methods included from Rex::Payloads::Meterpreter::UriChecksum

#generate_uri_checksum, #generate_uri_uuid, #process_uri_resource, #uri_checksum_lookup

Instance Attribute Details

#stage_archObject

Returns the value of attribute stage_arch.



11
12
13
# File 'lib/msf/core/payload/stager.rb', line 11

def stage_arch
  @stage_arch
end

#stage_platformObject

Returns the value of attribute stage_platform.



12
13
14
# File 'lib/msf/core/payload/stager.rb', line 12

def stage_platform
  @stage_platform
end

#stage_prefixObject

A value that should be prefixed to a stage, such as a tag.



326
327
328
# File 'lib/msf/core/payload/stager.rb', line 326

def stage_prefix
  @stage_prefix
end

Instance Method Details

#assemblyString?

Return the stager payload's assembly text, if any.

Returns:

  • (String, nil)


72
73
74
# File 'lib/msf/core/payload/stager.rb', line 72

def assembly
  return module_info['Stager']['Assembly']
end

#encode_stage(stg) ⇒ String

Encodes the stage prior to transmission

Returns:

  • (String)

    Encoded version of stg



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/msf/core/payload/stager.rb', line 269

def encode_stage(stg)
  return stg unless encode_stage?
  stage_enc_mod = nil

  # Handle StageEncoder if specified by the user
  if datastore['StageEncoder'].to_s.length > 0
    stage_enc_mod = datastore["StageEncoder"]
  end

  # Allow the user to specify additional registers to preserve
  saved_registers =
    datastore['StageEncoderSaveRegisters'].to_s +
    " " +
    encode_stage_preserved_registers
  saved_registers.strip!

  estg = nil
  begin
    # Generate an encoded version of the stage.  We tell the encoding system
    # to save certain registers to ensure that it does not get clobbered.
    encp = Msf::EncodedPayload.create(
      self,
      'Raw'                => stg,
      'Encoder'            => stage_enc_mod,
      'EncoderOptions'     => { 'SaveRegisters' => saved_registers },
      'ForceSaveRegisters' => true,
      'ForceEncode'        => true,
      'Arch'               => self.stage_arch,
      'Platform'           => self.stage_platform)

    if encp.encoder
      if stage_enc_mod
        print_status("Encoded stage with #{stage_enc_mod}")
      else
        print_status("Encoded stage with #{encp.encoder.refname}")
      end
      estg = encp.encoded
    end
  rescue
    if datastore['StageEncodingFallback'] && estg.nil?
      print_warning("StageEncoder failed, falling back to no encoding")
      estg = stg
    else
      raise RuntimeError, "Stage encoding failed and StageEncodingFallback is disabled"
    end
  end

  estg
end

#encode_stage?Boolean

Whether to use an Encoder on the second stage

Returns:

  • (Boolean)


136
137
138
# File 'lib/msf/core/payload/stager.rb', line 136

def encode_stage?
  !!(datastore['EnableStageEncoding'])
end

#encode_stage_preserved_registersObject

Takes an educated guess at the list of registers an encoded stage would need to preserve based on the Convention



261
262
263
264
265
# File 'lib/msf/core/payload/stager.rb', line 261

def encode_stage_preserved_registers
  module_info['Convention'].to_s.scan(/\bsock([a-z]{3,}+)\b/).
    map {|reg| reg.first }.
    join(" ")
end

#format_uuid(uuid_raw) ⇒ Object



164
165
166
167
168
169
170
# File 'lib/msf/core/payload/stager.rb', line 164

def format_uuid(uuid_raw)
  if sends_hex_uuid?
    return uuid_raw
  end

  return Msf::Payload::UUID.new({raw: uuid_raw})
end

#generate_stage(opts = {}) ⇒ String

Generates the stage payload and substitutes all offsets.

Returns:

  • (String)

    The generated payload stage, as a string.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/msf/core/payload/stager.rb', line 144

def generate_stage(opts={})
  # XXX: This is nearly identical to Payload#internal_generate

  # Compile the stage as necessary
  if stage_assembly and !stage_assembly.empty?
    raw = build(stage_assembly, stage_offsets)
  else
    raw = stage_payload(opts)
  end

  # Substitute variables in the stage
  substitute_vars(raw, stage_offsets) if (stage_offsets)

  return raw
end

#handle_connection(conn, opts = {}) ⇒ Object

Transmit the associated stage.



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
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/msf/core/payload/stager.rb', line 177

def handle_connection(conn, opts={})

  # If the stage should be sent over the client connection that is
  # established (which is the default), then go ahead and transmit it.
  if (stage_over_connection?)
    if respond_to? :include_send_uuid
      if include_send_uuid
        uuid_raw = conn.get_once(16, 1)
        if uuid_raw
          opts[:uuid] = format_uuid(uuid_raw)
        end
      end
    end

    # Generate and encode the stage if stage encoding is enabled
    begin
      p = generate_stage(opts)
      p = encode_stage(p)
    rescue ::RuntimeError, ::StandardError => e
      warning_msg = "Failed to stage"
      warning_msg << " (#{conn.peerhost})"  if conn.respond_to? :peerhost
      warning_msg << ": #{e}"
      print_warning warning_msg
      if conn.respond_to? :close && !conn.closed?
        conn.close
      end
      return
    end

    # Give derived classes an opportunity to an intermediate state before
    # the stage is sent.  This gives derived classes an opportunity to
    # augment the stage and the process through which it is read on the
    # remote machine.
    #
    # If we don't use an intermediate stage, then we need to prepend the
    # stage prefix, such as a tag
    if handle_intermediate_stage(conn, p) == false
      p = (self.stage_prefix || '') + p
    end

    sending_msg = "Sending #{encode_stage? ? "encoded ":""}stage"
    sending_msg << " (#{p.length} bytes)"
    # The connection should always have a peerhost (even if it's a
    # tunnel), but if it doesn't, erroring out here means losing the
    # session, so make sure it does, just to be safe.
    if conn.respond_to? :peerhost
      sending_msg << " to #{conn.peerhost}"
    end
    print_status(sending_msg)

    # Send the stage
    conn.put(p)
  end

  # Give the stages a chance to handle the connection
  handle_connection_stage(conn, opts)
end

#handle_connection_stage(conn, opts = {}) ⇒ Object

Allow the stage to process whatever it is it needs to process.

Override to deal with sending the final stage in cases where #generate_stage is not the whole picture, such as when uploading an executable. The default is to simply attempt to create a session on the given conn socket with Handler#create_session.



245
246
247
# File 'lib/msf/core/payload/stager.rb', line 245

def handle_connection_stage(conn, opts={})
  create_session(conn, opts)
end

#handle_intermediate_stage(conn, payload) ⇒ Object

Gives derived classes an opportunity to alter the stage and/or encapsulate its transmission.



253
254
255
# File 'lib/msf/core/payload/stager.rb', line 253

def handle_intermediate_stage(conn, payload)
  false
end

#initialize(info = {}) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/msf/core/payload/stager.rb', line 14

def initialize(info={})
  super

  self.stage_arch = self.arch
  self.stage_platform = self.platform
  register_advanced_options(
    [
      Msf::OptBool.new("EnableStageEncoding", [ false, "Encode the second stage payload", false ]),
      Msf::OptString.new("StageEncoder", [ false, "Encoder to use if EnableStageEncoding is set", nil ]),
      Msf::OptString.new("StageEncoderSaveRegisters", [ false, "Additional registers to preserve in the staged payload if EnableStageEncoding is set", "" ]),
      Msf::OptBool.new("StageEncodingFallback", [ false, "Fallback to no encoding if the selected StageEncoder is not compatible", true ])
    ], Msf::Payload::Stager)

end

#offsetsHash Also known as: stager_offsets

Return the stager payload's offsets.

These will be used for substitutions during stager generation.

Returns:

  • (Hash)


82
83
84
# File 'lib/msf/core/payload/stager.rb', line 82

def offsets
  return module_info['Stager']['Offsets']
end

#payloadString? Also known as: stager_payload

Return the stager payload's raw payload.

Can be nil if the stager is not pre-assembled.

Returns:

  • (String, nil)


64
65
66
# File 'lib/msf/core/payload/stager.rb', line 64

def payload
  return module_info['Stager']['Payload']
end

#payload_typeObject

Sets the payload type to a stager.



54
55
56
# File 'lib/msf/core/payload/stager.rb', line 54

def payload_type
  return Msf::Payload::Type::Stager
end

#sends_hex_uuid?Boolean

Returns:

  • (Boolean)


160
161
162
# File 'lib/msf/core/payload/stager.rb', line 160

def sends_hex_uuid?
  false
end

#stage_assemblyString

Returns the assembly text of the stage payload.

Returns:

  • (String)


103
104
105
106
107
108
# File 'lib/msf/core/payload/stager.rb', line 103

def stage_assembly
  if module_info['Stage']
    return module_info['Stage']['Assembly']
  end
  nil
end

#stage_offsetsHash

Returns variable offsets within the stage payload.

These will be used for substitutions during generation of the final stage.

Returns:

  • (Hash)


117
118
119
120
121
122
# File 'lib/msf/core/payload/stager.rb', line 117

def stage_offsets
  if module_info['Stage']
    return module_info['Stage']['Offsets']
  end
  nil
end

#stage_over_connection?Boolean

Whether or not any stages associated with this stager should be sent over the connection that is established.

Returns:

  • (Boolean)


128
129
130
# File 'lib/msf/core/payload/stager.rb', line 128

def stage_over_connection?
  true
end

#stage_payload(opts = {}) ⇒ String?

Returns the raw stage payload.

Can be nil if the final stage is not pre-assembled.

Returns:

  • (String, nil)


92
93
94
95
96
97
# File 'lib/msf/core/payload/stager.rb', line 92

def stage_payload(opts = {})
  if module_info['Stage']
    return module_info['Stage']['Payload']
  end
  nil
end

#transport_config(opts = {}) ⇒ Object

Perform attempt at detecting the appropriate transport config. Call the determined config with passed options. Override this in stages/stagers to use specific transports



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/msf/core/payload/stager.rb', line 34

def transport_config(opts={})
  if self.refname =~ /reverse_/
      direction = 'reverse'
  else
      direction = 'bind'
  end

  if self.refname =~ /_tcp/
      proto = 'tcp'
  elsif self.refname =~ /_https/
      proto = 'https'
  else
      proto = 'http'
  end
  send("transport_config_#{direction}_#{proto}", opts)
end