Class: Msf::Encoder

Inherits:
Module show all
Defined in:
lib/msf/core/encoder.rb

Overview

This class is the base class that all encoders inherit from.

Direct Known Subclasses

Alphanum, NonAlpha, NonUpper, Xor, Rex::Encoder::BloXor

Defined Under Namespace

Modules: Type Classes: Alphanum, NonAlpha, NonUpper, Xor, XorAdditiveFeedback

Instance Attribute Summary

Attributes inherited from Module

#arch, #author, #datastore, #error, #job_id, #license, #module_store, #options, #platform, #privileged, #references, #uuid

Attributes included from Framework::Offspring

#framework

Attributes included from Rex::Ui::Subscriber::Input

#user_input

Attributes included from Rex::Ui::Subscriber::Output

#user_output

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Module

#[], #[]=, #alias, #arch?, #arch_to_s, #author_to_s, #auxiliary?, cached?, #check, #comm, #compat, #compatible?, #debugging?, #description, #disclosure_date, #each_arch, #each_author, #encoder?, #exploit?, #fail_with, #file_path, #framework, #fullname, fullname, #import_defaults, is_usable, #name, #nop?, #orig_cls, #owner, #payload?, #platform?, #platform_to_s, #post?, #print_error, #print_good, #print_line, #print_line_prefix, #print_prefix, #print_status, #print_warning, #privileged?, #rank, rank, #rank_to_h, rank_to_h, #rank_to_s, rank_to_s, #refname, #register_parent, #replicant, #search_filter, #share_datastore, shortname, #shortname, #support_ipv6?, #target_host, #target_port, #validate, #vprint_debug, #vprint_error, #vprint_good, #vprint_line, #vprint_status, #vprint_warning, #workspace

Methods included from Rex::Ui::Subscriber

#copy_ui, #init_ui, #reset_ui

Methods included from Rex::Ui::Subscriber::Input

#gets

Methods included from Rex::Ui::Subscriber::Output

#flush, #print, #print_debug, #print_error, #print_good, #print_line, #print_status, #print_warning

Constructor Details

#initialize(info) ⇒ Encoder

Initializes an encoder module instance using the supplied information hash.


136
137
138
139
140
# File 'lib/msf/core/encoder.rb', line 136

def initialize(info)
  super({
      'Platform' => '' # All platforms by default
    }.update(info))
end

Class Method Details

.typeObject

Returns MODULE_ENCODER to indicate that this is an encoder module.


152
153
154
# File 'lib/msf/core/encoder.rb', line 152

def self.type
  return MODULE_ENCODER
end

Instance Method Details

#decoder_block_sizeObject

Returns the size of each logical encoding block, in bytes. This is typically the same as decoder_key_size.


197
198
199
# File 'lib/msf/core/encoder.rb', line 197

def decoder_block_size
  return decoder_hash['BlockSize']
end

#decoder_hashObject

Returns the module's decoder hash or an empty hash.


212
213
214
# File 'lib/msf/core/encoder.rb', line 212

def decoder_hash
  module_info['Decoder'] || {}
end

#decoder_key_offsetObject

Returns the offset to the key associated with the decoder stub.


182
183
184
# File 'lib/msf/core/encoder.rb', line 182

def decoder_key_offset
  return decoder_hash['KeyOffset']
end

#decoder_key_packObject

Returns the byte-packing character that should be used to encode the key.


205
206
207
# File 'lib/msf/core/encoder.rb', line 205

def decoder_key_pack
  return decoder_hash['KeyPack'] || 'V'
end

#decoder_key_sizeObject

Returns the size of the key, in bytes.


189
190
191
# File 'lib/msf/core/encoder.rb', line 189

def decoder_key_size
  return decoder_hash['KeySize']
end

#decoder_stub(state) ⇒ Object

Returns the decoder stub to use based on the supplied state.


175
176
177
# File 'lib/msf/core/encoder.rb', line 175

def decoder_stub(state)
  return decoder_hash['Stub'] || ''
end

#do_encode(state) ⇒ Object

Performs the actual encoding operation after the encoder state has been initialized and is ready to go.


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
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/msf/core/encoder.rb', line 284

def do_encode(state)

  # Copy the decoder stub since we may need to modify it
  stub = decoder_stub(state).dup

  if (state.key != nil and state.decoder_key_offset)
    # Substitute the decoder key in the copy of the decoder stub with the
    # one that we found
    real_key = state.key

    # If we're using context encoding, the actual value we use for
    # substitution is the context address, not the key we use for
    # encoding
    real_key = state.context_address if (state.context_encoding)

    stub[state.decoder_key_offset,state.decoder_key_size] = [ real_key.to_i ].pack(state.decoder_key_pack)
  else
    stub = encode_finalize_stub(state, stub)
  end

  # Walk the buffer encoding each block along the way
  offset = 0

  if (decoder_block_size)
    while (offset < state.buf.length)
      block = state.buf[offset, decoder_block_size]

      # Append here (String#<<) instead of creating a new string with
      # String#+ because the allocations kill performance with large
      # buffers. This isn't usually noticeable on most shellcode, but
      # when doing stage encoding on meterpreter (~750k bytes) the
      # difference is 2 orders of magnitude.
      state.encoded << encode_block(state,
          block + ("\x00" * (decoder_block_size - block.length)))

      offset += decoder_block_size
    end
  else
    state.encoded = encode_block(state, state.buf)
  end

  # Prefix the decoder stub to the encoded buffer
  state.encoded = stub + state.encoded

  # Last but not least, do one last badchar pass to see if the stub +
  # encoded payload leads to any bad char issues...
  if ((badchar_idx = has_badchars?(state.encoded, state.badchars)) != nil)
    raise BadcharError.new(state.encoded, badchar_idx, stub.length, state.encoded[badchar_idx]),
        "The #{self.name} encoder failed to encode without bad characters.",
        caller
  end

  return true
end

#encode(buf, badchars = nil, state = nil, platform = nil) ⇒ Object

This method generates an encoded version of the supplied buffer in buf using the bad characters as guides. On success, an encoded and functional version of the supplied buffer will be returned. Otherwise, an exception will be thrown if an error is encountered during the encoding process.


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
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/msf/core/encoder.rb', line 229

def encode(buf, badchars = nil, state = nil, platform = nil)

  # Configure platform hints if necessary
  init_platform(platform) if platform

  # Initialize an empty set of bad characters
  badchars = '' if (!badchars)

  # Initialize the encoding state and key as necessary
  if (state == nil)
    state = EncoderState.new
  end

  # Prepend data to the buffer as necessary
  buf = prepend_buf + buf

  init_state(state)

  # Save the buffer in the encoding state
  state.badchars = badchars || ''
  state.buf      = buf

  # If this encoder is key-based and we don't already have a key, find one
  if ((decoder_key_size) and
      (state.key == nil))
    # Find a key that doesn't contain and wont generate any bad
    # characters
    state.init_key(obtain_key(buf, badchars, state))

    if (state.key == nil)
      raise NoKeyError, "A key could not be found for the #{self.name} encoder.", caller
    end
  end

  # Reset the encoded buffer at this point since it may have been changed
  # while finding a key.
  state.encoded = ''

  # Call encode_begin to do any encoder specific pre-processing
  encode_begin(state)

  # Perform the actual encoding operation with the determined state
  do_encode(state)

  # Call encoded_end to do any encoder specific post-processing
  encode_end(state)

  # Return the encoded buffer to the caller
  return state.encoded
end

#encode_begin(state) ⇒ Object

Called when encoding is about to start immediately after the encoding state has been initialized.


363
364
365
# File 'lib/msf/core/encoder.rb', line 363

def encode_begin(state)
  return nil
end

#encode_block(state, block) ⇒ Object

Called once for each block being encoded based on the attributes of the decoder.


386
387
388
# File 'lib/msf/core/encoder.rb', line 386

def encode_block(state, block)
  return block
end

#encode_end(state) ⇒ Object

Called after encoding has completed.


378
379
380
# File 'lib/msf/core/encoder.rb', line 378

def encode_end(state)
  return nil
end

#encode_finalize_stub(state, stub) ⇒ Object

This callback allows a derived class to finalize a stub after a key have been selected. The finalized stub should be returned.


371
372
373
# File 'lib/msf/core/encoder.rb', line 371

def encode_finalize_stub(state, stub)
  stub
end

#encoder_typeObject

Returns the type or types of encoders that this specific module classifies as. If there is more than one type, the values should be separated by whitespace.


168
169
170
# File 'lib/msf/core/encoder.rb', line 168

def encoder_type
  module_info['EncoderType'] || Type::Unspecified
end

#prepend_bufObject

Returns a string that should be prepended to the encoded version of the buffer before returning it to callers.


349
350
351
# File 'lib/msf/core/encoder.rb', line 349

def prepend_buf
  return ''
end

#to_native(buf) ⇒ Object

Provides the encoder with an opportunity to return the native format (as in the format the code will be in when it executes on the target). In general, the same buffer is returned to the caller. However, for things like unicode, the buffer is unicod encoded and then returned.


396
397
398
# File 'lib/msf/core/encoder.rb', line 396

def to_native(buf)
  buf
end

#typeObject

Returns MODULE_ENCODER to indicate that this is an encoder module.


159
160
161
# File 'lib/msf/core/encoder.rb', line 159

def type
  return MODULE_ENCODER
end