CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/util/payload_cached_size.rb
Views: 1904
1
# -*- coding: binary -*-
2
###
3
#
4
#
5
###
6
7
module Msf
8
module Util
9
10
#
11
# The class provides helper methods for verifying and updating the embedded CachedSize
12
# constant within payload modules.
13
#
14
15
class PayloadCachedSize
16
17
OPTS = {
18
'Format' => 'raw',
19
'Options' => {
20
'CPORT' => 4444,
21
'LPORT' => 4444,
22
'CMD' => '/bin/sh',
23
'URL' => 'http://a.com',
24
'PATH' => '/',
25
'BUNDLE' => 'data/isight.bundle',
26
'DLL' => 'external/source/byakugan/bin/XPSP2/detoured.dll',
27
'RC4PASSWORD' => 'Metasploit',
28
'DNSZONE' => 'corelan.eu',
29
'PEXEC' => '/bin/sh',
30
'HttpUserAgent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0',
31
'StagerURILength' => 5
32
},
33
'Encoder' => nil,
34
'DisableNops' => true
35
}
36
37
OPTS_ARCH_X64 = {
38
'DLL' => 'data/vncdll.x64.dll',
39
'PE' => 'data/vncdll.x64.dll'
40
}.freeze
41
42
OPTS_ARCH_X86 = {
43
'DLL' => 'data/vncdll.x86.dll',
44
'PE' => 'data/vncdll.x86.dll'
45
}.freeze
46
47
OPTS_IPV4 = {
48
'LHOST' => '255.255.255.255',
49
'KHOST' => '255.255.255.255',
50
'AHOST' => '255.255.255.255'
51
}.freeze
52
53
OPTS_IPV6 = {
54
'LHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
55
'KHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
56
'AHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'
57
}.freeze
58
59
# Insert a new CachedSize value into the text of a payload module
60
#
61
# @param data [String] The source code of a payload module
62
# @param cached_size [String] The new value for cached_size, which
63
# which should be either numeric or the string :dynamic
64
# @return [String]
65
def self.update_cache_constant(data, cached_size)
66
data.
67
gsub(/^\s*CachedSize\s*=\s*(\d+|:dynamic).*/, '').
68
gsub(/^(module MetasploitModule)\s*\n/) do |m|
69
"#{m.strip}\n\n CachedSize = #{cached_size}\n\n"
70
end
71
end
72
73
# Insert a new CachedSize value into a payload module file
74
#
75
# @param mod [Msf::Payload] The class of the payload module to update
76
# @param cached_size [String] The new value for cached_size, which
77
# which should be either numeric or the string :dynamic
78
# @return [void]
79
def self.update_cached_size(mod, cached_size)
80
mod_data = ""
81
82
::File.open(mod.file_path, 'rb') do |fd|
83
mod_data = fd.read(fd.stat.size)
84
end
85
86
::File.open(mod.file_path, 'wb') do |fd|
87
fd.write update_cache_constant(mod_data, cached_size)
88
end
89
end
90
91
# Updates the payload module specified with the current CachedSize
92
#
93
# @param mod [Msf::Payload] The class of the payload module to update
94
# @return [void]
95
def self.update_module_cached_size(mod)
96
update_cached_size(mod, compute_cached_size(mod))
97
end
98
99
# Calculates the CachedSize value for a payload module
100
#
101
# @param mod [Msf::Payload] The class of the payload module to update
102
# @return [Integer]
103
def self.compute_cached_size(mod)
104
return ":dynamic" if is_dynamic?(mod)
105
106
mod.generate_simple(module_options(mod)).size
107
end
108
109
# Determines whether a payload generates a static sized output
110
#
111
# @param mod [Msf::Payload] The class of the payload module to update
112
# @param generation_count [Integer] The number of iterations to use to
113
# verify that the size is static.
114
# @return [Integer]
115
def self.is_dynamic?(mod, generation_count=5)
116
opts = module_options(mod)
117
[*(1..generation_count)].map do |x|
118
mod.generate_simple(opts).size
119
end.uniq.length != 1
120
end
121
122
# Determines whether a payload's CachedSize is up to date
123
#
124
# @param mod [Msf::Payload] The class of the payload module to update
125
# @return [Boolean]
126
def self.is_cached_size_accurate?(mod)
127
return true if mod.dynamic_size? && is_dynamic?(mod)
128
return false if mod.cached_size.nil?
129
130
mod.cached_size == mod.generate_simple(module_options(mod)).size
131
end
132
133
# Get a set of sane default options for the module so it can generate a
134
# payload for size analysis.
135
#
136
# @param mod [Msf::Payload] The class of the payload module to get options for
137
# @return [Hash]
138
def self.module_options(mod)
139
opts = OPTS.clone
140
# Assign this way to overwrite the Options key of the newly cloned hash
141
opts['Options'] = opts['Options'].merge(mod.shortname =~ /6/ ? OPTS_IPV6 : OPTS_IPV4)
142
# Extract the AdaptedArch for adaptor payloads, note `mod.adapted_arch` is not part of the public API
143
# at this time, but could be in the future. The use of send is safe for now as it is an internal tool
144
# with automated tests if the API were to change in the future
145
adapted_arch = mod.send(:module_info)['AdaptedArch']
146
if adapted_arch == ARCH_X64 || mod.arch_to_s == ARCH_X64
147
opts['Options'].merge!(OPTS_ARCH_X64)
148
elsif adapted_arch == ARCH_X86 || mod.arch_to_s == ARCH_X86
149
opts['Options'].merge!(OPTS_ARCH_X86)
150
end
151
opts
152
end
153
end
154
155
end
156
end
157
158