Module: Msf::Module::Compatibility

Included in:
Msf::Module
Defined in:
lib/msf/core/module/compatibility.rb

Instance Method Summary collapse

Instance Method Details

#compatObject

Returns the hash that describes this module's compatibilities.



5
6
7
# File 'lib/msf/core/module/compatibility.rb', line 5

def compat
  module_info['Compat'] || {}
end

#compatible?(mod) ⇒ Boolean

Returns whether or not this module is compatible with the supplied module.

Returns:

  • (Boolean)


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/msf/core/module/compatibility.rb', line 13

def compatible?(mod)
  ch = nil

  # Invalid module?  Shoot, we can't compare that.
  return true if (mod == nil)

  # Determine which hash to used based on the supplied module type
  if (mod.type == Msf::MODULE_ENCODER)
    ch = self.compat['Encoder']
  elsif (mod.type == Msf::MODULE_NOP)
    ch = self.compat['Nop']
  elsif (mod.type == Msf::MODULE_PAYLOAD)
    ch = self.compat['Payload']
    if self.respond_to?("target") and self.target and self.target['Payload'] and self.target['Payload']['Compat']
      ch = ch.merge(self.target['Payload']['Compat'])
    end
  else
    return true
  end

  # Enumerate each compatibility item in our hash to find out
  # if we're compatible with this sucker.
  ch.each_pair do |k,v|

    # Get the value of the current key from the module, such as
    # the ConnectionType for a stager (ws2ord, for instance).
    mval = mod.module_info[k]

    # Reject a filled compat item on one side, but not the other
    if (v and not mval)
      dlog("Module #{mod.refname} is incompatible with #{self.refname} for #{k}: limiter was #{v}")
      return false
    end

    # Track how many of our values matched the module
    mcnt = 0

    # Values are whitespace separated
    sv = v.split(/\s+/)
    mv = mval.split(/\s+/)

    sv.each do |x|

      dlog("Checking compat [#{mod.refname} with #{self.refname}]: #{x} to #{mv.join(", ")}", 'core', LEV_3)

      # Verify that any negate values are not matched
      if (x[0,1] == '-' and mv.include?(x[1, x.length-1]))
        dlog("Module #{mod.refname} is incompatible with #{self.refname} for #{k}: limiter was #{x}, value was #{mval}", 'core', LEV_1)
        return false
      end

      mcnt += 1 if mv.include?(x)
    end

    # No values matched, reject this module
    if (mcnt == 0)
      dlog("Module #{mod.refname} is incompatible with #{self.refname} for #{k}: limiter was #{v}, value was #{mval}", 'core', LEV_1)
      return false
    end

  end

  dlog("Module #{mod.refname} is compatible with #{self.refname}", "core", LEV_1)


  # If we get here, we're compatible.
  return true
end

#init_compatObject (protected)

This method initializes the module's compatibility hashes by normalizing them into one single hash. As it stands, modules can define compatibility in their supplied info hash through:

Compat

direct compat definitions

PayloadCompat

payload compatibilities

EncoderCompat

encoder compatibilities

NopCompat

nop compatibilities

MeterpreterCompat

meterpreter compatibilities

In the end, the module specific compatibilities are merged as sub-hashes of the primary Compat hash key to make checks more uniform.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/msf/core/module/compatibility.rb', line 98

def init_compat
  c = module_info['Compat']

  if (c == nil)
    c = module_info['Compat'] = Hash.new
  end


  %w{ Encoder Meterpreter Nop Payload }.each do |key|
    # Initialize the module sub compatibilities
    c[key] = Hash.new if c[key].nil?
    # Update the compat-derived module specific compatibilities from
    # the specific ones to make a uniform view of compatibilities
    c[key].update(module_info["#{key}Compat"] || {})
  end
end