Module: Msf::Payload::Stager

Defined in:
lib/msf/core/payload/stager.rb

Overview

Base mixin interface for use by stagers.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#stage_prefixObject

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


232
233
234
# File 'lib/msf/core/payload/stager.rb', line 232

def stage_prefix
  @stage_prefix
end

Instance Method Details

#assemblyString?

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

Returns:

  • (String, nil)

44
45
46
# File 'lib/msf/core/payload/stager.rb', line 44

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

#encode_stage(stg) ⇒ String

Encodes the stage prior to transmission

Returns:

  • (String)

    Encoded version of stg


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/msf/core/payload/stager.rb', line 201

def encode_stage(stg)
  return stg unless encode_stage?

  if datastore["StageEncoder"].nil? or datastore["StageEncoder"].empty?
    stage_enc_mod = nil
  else
    stage_enc_mod = datastore["StageEncoder"]
  end

  # Generate an encoded version of the stage.  We tell the encoding system
  # to save edi to ensure that it does not get clobbered.
  encp = Msf::EncodedPayload.create(
    self,
    'Raw'           => stg,
    'Encoder'       => stage_enc_mod,
    'SaveRegisters' => ['edi'],
    'ForceEncode'   => true)
  print_status("Encoded stage with #{encp.encoder.refname}")

  # If the encoding succeeded, use the encoded buffer.  Otherwise, fall
  # back to using the non-encoded stage
  encp.encoded || stg
end

#encode_stage?Boolean

Whether to use an Encoder on the second stage

Returns:

  • (Boolean)

100
101
102
103
# File 'lib/msf/core/payload/stager.rb', line 100

def encode_stage?
  # Convert to string in case it hasn't been normalized
  !!(datastore['EnableStageEncoding'].to_s == "true")
end

#generate_stageString

Generates the stage payload and substitutes all offsets.

Returns:

  • (String)

    The generated payload stage, as a string.


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/msf/core/payload/stager.rb', line 109

def generate_stage
  # 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.dup
  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.


130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/msf/core/payload/stager.rb', line 130

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?)
    p = generate_stage

    # Encode the stage if stage encoding is enabled
    p = encode_stage(p)

    # 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

  # If the stage implements the handle connection method, sleep before
  # handling it.
  if (derived_implementor?(Msf::Payload::Stager, 'handle_connection_stage'))
    print_status("Sleeping before handling stage...")

    # Sleep before processing the stage
    Rex::ThreadSafe.sleep(1.5)
  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.


187
188
189
# File 'lib/msf/core/payload/stager.rb', line 187

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.


195
196
197
# File 'lib/msf/core/payload/stager.rb', line 195

def handle_intermediate_stage(conn, payload)
  false
end

#initialize(info = {}) ⇒ Object


12
13
14
15
16
17
18
19
20
21
# File 'lib/msf/core/payload/stager.rb', line 12

def initialize(info={})
  super

  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::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)

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

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)

36
37
38
# File 'lib/msf/core/payload/stager.rb', line 36

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

#payload_typeObject

Sets the payload type to a stager.


26
27
28
# File 'lib/msf/core/payload/stager.rb', line 26

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

#stage_assemblyString

Returns the assembly text of the stage payload.

Returns:

  • (String)

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

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

#stage_offsetsHash

Returns variable offsets within the stage payload.

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

Returns:

  • (Hash)

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

def stage_offsets
  return module_info['Stage']['Offsets']
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)

91
92
93
# File 'lib/msf/core/payload/stager.rb', line 91

def stage_over_connection?
  true
end

#stage_payloadString?

Returns the raw stage payload.

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

Returns:

  • (String, nil)

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

def stage_payload
  return module_info['Stage']['Payload']
end