CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/core/module/compatibility.rb
Views: 11784
1
module Msf::Module::Compatibility
2
#
3
# Returns the hash that describes this module's compatibilities.
4
#
5
def compat
6
module_info['Compat'] || {}
7
end
8
9
#
10
# Returns whether or not this module is compatible with the supplied
11
# module.
12
#
13
def compatible?(mod)
14
ch = nil
15
16
# Invalid module? Shoot, we can't compare that.
17
return true if (mod == nil)
18
19
# Determine which hash to used based on the supplied module type
20
if (mod.type == Msf::MODULE_ENCODER)
21
ch = self.compat['Encoder']
22
elsif (mod.type == Msf::MODULE_NOP)
23
ch = self.compat['Nop']
24
elsif (mod.type == Msf::MODULE_PAYLOAD)
25
ch = self.compat['Payload']
26
if self.respond_to?("target") and self.target and self.target['Payload'] and self.target['Payload']['Compat']
27
ch = ch.merge(self.target['Payload']['Compat'])
28
end
29
else
30
return true
31
end
32
33
# Enumerate each compatibility item in our hash to find out
34
# if we're compatible with this sucker.
35
ch.each_pair do |k,v|
36
37
# Get the value of the current key from the module, such as
38
# the ConnectionType for a stager (ws2ord, for instance).
39
mval = mod.module_info[k]
40
41
# Reject a filled compat item on one side, but not the other
42
if (v and not mval)
43
dlog("Module #{mod.refname} is incompatible with #{self.refname} for #{k}: limiter was #{v}")
44
return false
45
end
46
47
# Track how many of our values matched the module
48
mcnt = 0
49
50
# Values are whitespace separated
51
sv = v.split(/\s+/)
52
mv = mval.split(/\s+/)
53
54
sv.each do |x|
55
56
dlog("Checking compat [#{mod.refname} with #{self.refname}]: #{x} to #{mv.join(", ")}", 'core', LEV_3)
57
58
# Verify that any negate values are not matched
59
if (x[0,1] == '-' and mv.include?(x[1, x.length-1]))
60
dlog("Module #{mod.refname} is incompatible with #{self.refname} for #{k}: limiter was #{x}, value was #{mval}", 'core', LEV_1)
61
return false
62
end
63
64
mcnt += 1 if mv.include?(x)
65
end
66
67
# No values matched, reject this module
68
if (mcnt == 0)
69
dlog("Module #{mod.refname} is incompatible with #{self.refname} for #{k}: limiter was #{v}, value was #{mval}", 'core', LEV_1)
70
return false
71
end
72
73
end
74
75
dlog("Module #{mod.refname} is compatible with #{self.refname}", "core", LEV_1)
76
77
78
# If we get here, we're compatible.
79
return true
80
end
81
82
protected
83
84
#
85
# This method initializes the module's compatibility hashes by normalizing
86
# them into one single hash. As it stands, modules can define
87
# compatibility in their supplied info hash through:
88
#
89
# Compat:: direct compat definitions
90
# PayloadCompat:: payload compatibilities
91
# EncoderCompat:: encoder compatibilities
92
# NopCompat:: nop compatibilities
93
# MeterpreterCompat:: meterpreter compatibilities
94
#
95
# In the end, the module specific compatibilities are merged as sub-hashes
96
# of the primary Compat hash key to make checks more uniform.
97
#
98
def init_compat
99
c = module_info['Compat']
100
101
if (c == nil)
102
c = module_info['Compat'] = Hash.new
103
end
104
105
106
%w{ Encoder Meterpreter Nop Payload }.each do |key|
107
# Initialize the module sub compatibilities
108
c[key] = Hash.new if c[key].nil?
109
# Update the compat-derived module specific compatibilities from
110
# the specific ones to make a uniform view of compatibilities
111
c[key].update(module_info["#{key}Compat"] || {})
112
end
113
end
114
end
115
116