Class: Msf::Util::PayloadCachedSize

Inherits:
Object
  • Object
show all
Defined in:
lib/msf/util/payload_cached_size.rb

Overview

The class provides helper methods for verifying and updating the embedded CachedSize constant within payload modules.

Constant Summary collapse

OPTS =
{
  'Format'      => 'raw',
  'Options'     => {
    'CPORT' => 4444,
    'LPORT' => 4444,
    'CMD' => '/bin/sh',
    'URL' => 'http://a.com',
    'PATH' => '/',
    'BUNDLE' => 'data/isight.bundle',
    'DLL' => 'external/source/byakugan/bin/XPSP2/detoured.dll',
    'RC4PASSWORD' => 'Metasploit',
    'DNSZONE' => 'corelan.eu',
    'PEXEC' => '/bin/sh',
    'HttpUserAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0',
    'StagerURILength' => 5
  },
  'Encoder'     => nil,
  'DisableNops' => true
}
OPTS_ARCH_X64 =
{
  'DLL' => 'data/vncdll.x64.dll',
  'PE' => 'data/vncdll.x64.dll'
}.freeze
OPTS_ARCH_X86 =
{
  'DLL' => 'data/vncdll.x86.dll',
  'PE' => 'data/vncdll.x86.dll'
}.freeze
OPTS_IPV4 =
{
  'LHOST' => '255.255.255.255',
  'KHOST' => '255.255.255.255',
  'AHOST' => '255.255.255.255'
}.freeze
OPTS_IPV6 =
{
  'LHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
  'KHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
  'AHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'
}.freeze

Class Method Summary collapse

Class Method Details

.compute_cached_size(mod) ⇒ Integer

Calculates the CachedSize value for a payload module

Parameters:

  • mod (Msf::Payload)

    The class of the payload module to update

Returns:

  • (Integer)


103
104
105
106
107
# File 'lib/msf/util/payload_cached_size.rb', line 103

def self.compute_cached_size(mod)
  return ":dynamic" if is_dynamic?(mod)

  mod.generate_simple(module_options(mod)).size
end

.is_cached_size_accurate?(mod) ⇒ Boolean

Determines whether a payload’s CachedSize is up to date

Parameters:

  • mod (Msf::Payload)

    The class of the payload module to update

Returns:

  • (Boolean)


126
127
128
129
130
131
# File 'lib/msf/util/payload_cached_size.rb', line 126

def self.is_cached_size_accurate?(mod)
  return true if mod.dynamic_size? && is_dynamic?(mod)
  return false if mod.cached_size.nil?

  mod.cached_size == mod.generate_simple(module_options(mod)).size
end

.is_dynamic?(mod, generation_count = 5) ⇒ Integer

Determines whether a payload generates a static sized output

Parameters:

  • mod (Msf::Payload)

    The class of the payload module to update

  • generation_count (Integer) (defaults to: 5)

    The number of iterations to use to verify that the size is static.

Returns:

  • (Integer)


115
116
117
118
119
120
# File 'lib/msf/util/payload_cached_size.rb', line 115

def self.is_dynamic?(mod, generation_count=5)
  opts = module_options(mod)
  [*(1..generation_count)].map do |x|
    mod.generate_simple(opts).size
  end.uniq.length != 1
end

.module_options(mod) ⇒ Hash

Get a set of sane default options for the module so it can generate a payload for size analysis.

Parameters:

  • mod (Msf::Payload)

    The class of the payload module to get options for

Returns:

  • (Hash)


138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/msf/util/payload_cached_size.rb', line 138

def self.module_options(mod)
  opts = OPTS.clone
  # Assign this way to overwrite the Options key of the newly cloned hash
  opts['Options'] = opts['Options'].merge(mod.shortname =~ /6/ ? OPTS_IPV6 : OPTS_IPV4)
  # Extract the AdaptedArch for adaptor payloads, note `mod.adapted_arch` is not part of the public API
  # at this time, but could be in the future. The use of send is safe for now as it is an internal tool
  # with automated tests if the API were to change in the future
  adapted_arch = mod.send(:module_info)['AdaptedArch']
  if adapted_arch == ARCH_X64 || mod.arch_to_s == ARCH_X64
    opts['Options'].merge!(OPTS_ARCH_X64)
  elsif adapted_arch == ARCH_X86 || mod.arch_to_s == ARCH_X86
    opts['Options'].merge!(OPTS_ARCH_X86)
  end
  opts
end

.update_cache_constant(data, cached_size) ⇒ String

Insert a new CachedSize value into the text of a payload module

Parameters:

  • data (String)

    The source code of a payload module

  • cached_size (String)

    The new value for cached_size, which which should be either numeric or the string :dynamic

Returns:

  • (String)


65
66
67
68
69
70
71
# File 'lib/msf/util/payload_cached_size.rb', line 65

def self.update_cache_constant(data, cached_size)
  data.
    gsub(/^\s*CachedSize\s*=\s*(\d+|:dynamic).*/, '').
    gsub(/^(module MetasploitModule)\s*\n/) do |m|
      "#{m.strip}\n\n  CachedSize = #{cached_size}\n\n"
    end
end

.update_cached_size(mod, cached_size) ⇒ void

This method returns an undefined value.

Insert a new CachedSize value into a payload module file

Parameters:

  • mod (Msf::Payload)

    The class of the payload module to update

  • cached_size (String)

    The new value for cached_size, which which should be either numeric or the string :dynamic



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/msf/util/payload_cached_size.rb', line 79

def self.update_cached_size(mod, cached_size)
  mod_data = ""

  ::File.open(mod.file_path, 'rb') do |fd|
    mod_data = fd.read(fd.stat.size)
  end

  ::File.open(mod.file_path, 'wb') do |fd|
    fd.write update_cache_constant(mod_data, cached_size)
  end
end

.update_module_cached_size(mod) ⇒ void

This method returns an undefined value.

Updates the payload module specified with the current CachedSize

Parameters:

  • mod (Msf::Payload)

    The class of the payload module to update



95
96
97
# File 'lib/msf/util/payload_cached_size.rb', line 95

def self.update_module_cached_size(mod)
  update_cached_size(mod, compute_cached_size(mod))
end