Class: MetasploitPayloads::Mettle

Inherits:
Object
  • Object
show all
Defined in:
lib/metasploit_payloads/mettle.rb,
lib/metasploit_payloads/mettle/error.rb,
lib/metasploit_payloads/mettle/version.rb

Defined Under Namespace

Classes: Error, NotFoundError

Constant Summary collapse

CMDLINE_MAX =
2000
CMDLINE_SIG =
'DEFAULT_OPTS'.freeze
CONFIG_BLOCK_MAX =
8192
CONFIG_BLOCK_SIG =
'CONFIG_BLOCK'.freeze
VERSION =
'1.0.48.pre.2'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(triple, config = {}) ⇒ Mettle

Returns a new instance of Mettle.



30
31
32
33
# File 'lib/metasploit_payloads/mettle.rb', line 30

def initialize(triple, config={})
  @platform = triple.clone
  @config = config.clone
end

Instance Attribute Details

#configObject

Config is a hash. Valid keys are: :uri to connect to :uuid of the payload :debug to enable :log_file to log to places other than stderr



28
29
30
# File 'lib/metasploit_payloads/mettle.rb', line 28

def config
  @config
end

Class Method Details

.available_extensions(platform) ⇒ Object

List extensions which are available for loading



198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/metasploit_payloads/mettle.rb', line 198

def self.available_extensions(platform)
  dir_path = path("#{platform}", 'bin')
  if dir_path.nil?
    full_path = ::File.join([platform, 'bin'])
    raise Mettle::NotFoundError, "#{full_path} not found", caller
  end

  extensions = ::Dir.entries(dir_path)
  extensions.select! { |extension| !extension.end_with?('.bin') }
  # The stdapi extension is baked in
  extensions << 'stdapi'
  # Only return extensions!
  extensions - [ '.', '..', 'mettle' ]
end

.available_platforms(extension) ⇒ Object

List platforms on which the specified extension is available for loading



216
217
218
219
220
# File 'lib/metasploit_payloads/mettle.rb', line 216

def self.available_platforms(extension)
  ::Dir.entries(path).select do |platform|
    !(platform_path = path(platform, 'bin')).nil? && ::File.readable?(platform_path) && available_extensions(platform).include?(extension)
  end
end

.data_directoryObject

Full path to the local gem folder containing the base data



165
166
167
# File 'lib/metasploit_payloads/mettle.rb', line 165

def self.data_directory
  ::File.realpath(::File.join(::File.dirname(__FILE__), '..', '..', 'build'))
end

.expand(root_dir, file_name) ⇒ Object

Expand the given root path and file name into a full file location.



179
180
181
# File 'lib/metasploit_payloads/mettle.rb', line 179

def self.expand(root_dir, file_name)
  ::File.expand_path(::File.join(root_dir, file_name))
end

.load_extension(platform, name, suffix = '') ⇒ Object

Load and return the contents of an extension as an object



225
226
227
228
229
230
231
232
233
# File 'lib/metasploit_payloads/mettle.rb', line 225

def self.load_extension(platform, name, suffix = '')
  if suffix == 'bin'
    format = :process_image
  else
    format = :exec
    name = [name,suffix].join('.') unless suffix.nil? || suffix.strip.empty?
  end
  self.read(platform, format, name)
end

.metasploit_installed?Boolean

Determine if MSF has been installed and is being used.

Returns:

  • (Boolean)


172
173
174
# File 'lib/metasploit_payloads/mettle.rb', line 172

def self.metasploit_installed?
  defined? Msf::Config
end

.path(*path_parts) ⇒ Object

Get the full path to any file packaged in this gem by local path and name.



153
154
155
156
157
158
159
160
# File 'lib/metasploit_payloads/mettle.rb', line 153

def self.path(*path_parts)
  gem_path = expand(data_directory, ::File.join(path_parts))
  msf_path = nil
  if metasploit_installed?
    msf_path = expand(Msf::Config.data_directory, ::File.join('mettle', path_parts))
  end
  readable_path(gem_path, msf_path)
end

.read(triple, format, filename = "mettle") ⇒ Object

Get the contents of any file packaged in this gem by local path and name.



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/metasploit_payloads/mettle.rb', line 127

def self.read(triple, format, filename = "mettle")
  file =
      case format
      when :process_image
        "#{filename}.bin"
      when :dylib
        "#{filename}.dylib"
      when :dylib_sha1
        "#{filename}.sha1.dylib"
      when :exec
        "#{filename}"
      else
        raise Mettle::NotFoundError, "unknown format #{format} for #{filename}", caller
      end
  file_path = path("#{triple}", 'bin', file)
  if file_path.nil?
    full_path = ::File.join([triple, file])
    raise Mettle::NotFoundError, "#{full_path} not found", caller
  end

  ::File.binread(file_path)
end

.readable_path(gem_path, msf_path = nil) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/metasploit_payloads/mettle.rb', line 111

def self.readable_path(gem_path, msf_path=nil)
  # Try the MSF path first to see if the file exists, allowing the MSF data
  # folder to override what is in the gem. This is very helpful for
  # testing/development without having to move the binaries to the gem folder
  # each time. We only do this is MSF is installed.
  if !msf_path.nil? && ::File.readable?(msf_path)
    warn_local_path(msf_path) if ::File.readable? gem_path
    msf_path
  elsif ::File.readable? gem_path
    gem_path
  end
end

.versionObject



6
7
8
# File 'lib/metasploit_payloads/mettle/version.rb', line 6

def self.version
  VERSION
end

.warn_local_path(path) ⇒ Object



185
186
187
188
189
190
191
192
193
# File 'lib/metasploit_payloads/mettle.rb', line 185

def self.warn_local_path(path)
  unless @local_paths.include?(path)
    STDERR.puts("WARNING: Local file #{path} is being used")
    if @local_paths.empty?
      STDERR.puts('WARNING: Local files may be incompatible Metasploit framework')
    end
    @local_paths << path
  end
end

Instance Method Details

#to_binary(format = :process_image) ⇒ Object

Available formats are :process_image, :dylib, :dylib_sha1 and :exec



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/metasploit_payloads/mettle.rb', line 38

def to_binary(format=:process_image)
  bin = self.class.read(@platform, format)
  unless @config.empty?
    if @config[:config_block]
      bin = add_config_block(bin, @config[:config_block])
    end
    params = generate_argv
    bin = add_args(bin, params)
  end
  bin
end