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/core/exploit/exe.rb
Views: 1904
1
# -*- coding: binary -*-
2
3
###
4
#
5
# This module exposes a simple method to create an payload in an executable.
6
#
7
###
8
9
module Msf
10
module Exploit::EXE
11
12
def initialize(info = {})
13
super
14
15
# NOTE: Any new options here should also be dealt with in
16
# EncodedPayload#encoded_exe in lib/msf/core/encoded_payload.rb
17
register_advanced_options(
18
[
19
OptBool.new('EXE::EICAR', [false, 'Generate an EICAR file instead of regular payload exe']),
20
OptPath.new('EXE::Custom', [false, 'Use custom exe instead of automatically generating a payload exe']),
21
OptPath.new('EXE::Path', [false, 'The directory in which to look for the executable template']),
22
OptPath.new('EXE::Template', [false, 'The executable template file name.']),
23
OptBool.new('EXE::Inject', [false, 'Set to preserve the original EXE function']),
24
OptBool.new('EXE::OldMethod',[false, 'Set to use the substitution EXE generation method.']),
25
OptBool.new('EXE::FallBack', [false, 'Use the default template in case the specified one is missing']),
26
OptBool.new('MSI::EICAR', [false, 'Generate an EICAR file instead of regular payload msi']),
27
OptPath.new('MSI::Custom', [false, 'Use custom msi instead of automatically generating a payload msi']),
28
OptPath.new('MSI::Path', [false, 'The directory in which to look for the msi template']),
29
OptPath.new('MSI::Template', [false, 'The msi template file name']),
30
OptBool.new('MSI::UAC', [false, 'Create an MSI with a UAC prompt (elevation to SYSTEM if accepted)'])
31
], self.class)
32
end
33
34
# Avoid stating the string directly, don't want to get caught by local
35
# antivirus!
36
def get_eicar_exe
37
obfus_eicar = ["x5o!p%@ap[4\\pzx54(p^)7cc)7}$eicar", "standard", "antivirus", "test", "file!$h+h*"]
38
obfus_eicar.join("-").upcase
39
end
40
41
def get_custom_exe(path = nil)
42
path ||= datastore['EXE::Custom']
43
print_status("Using custom payload #{path}, no handler will be created!")
44
datastore['DisablePayloadHandler'] = true
45
exe = nil
46
::File.open(path,'rb') {|f| exe = f.read(f.stat.size)}
47
exe
48
end
49
50
51
# Returns an executable.
52
#
53
# @param opts [Hash]
54
# @option opts [String] :code Payload
55
# @option opts [Array] :arch Architecture
56
# @option opts [Msf::Module::PlatformList] :platform
57
# @raise [Msf::NoCompatiblePayloadError] When #genereate_payload_exe fails to generate a payload.
58
# @return [String]
59
def generate_payload_exe(opts = {})
60
return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty?
61
return get_eicar_exe if datastore['EXE::EICAR']
62
63
exe_init_options(opts)
64
65
pl = opts[:code]
66
pl ||= payload.encoded
67
68
# Fall back to x86...
69
opts[:arch] = [ARCH_X86] if !opts[:arch] || opts[:arch].length < 1
70
71
# Ensure we have an array
72
opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array
73
74
# Transform the PlatformList
75
if opts[:platform].kind_of? Msf::Module::PlatformList
76
opts[:platform] = opts[:platform].platforms
77
end
78
79
exe = Msf::Util::EXE.to_executable(framework, opts[:arch], opts[:platform], pl, opts)
80
81
unless exe
82
raise Msf::NoCompatiblePayloadError, "Failed to generate an executable payload due to an invalid platform or arch."
83
end
84
85
exe_post_generation(opts)
86
exe
87
end
88
89
def generate_payload_exe_service(opts = {})
90
return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty?
91
return get_eicar_exe if datastore['EXE::EICAR']
92
93
exe_init_options(opts)
94
95
# NOTE: Only Windows is supported here.
96
pl = opts[:code]
97
pl ||= payload.encoded
98
99
#Ensure opts[:arch] is an array
100
opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array
101
102
if opts[:arch] && opts[:arch].index(ARCH_X64)
103
exe = Msf::Util::EXE.to_win64pe_service(framework, pl, opts)
104
else
105
exe = Msf::Util::EXE.to_win32pe_service(framework, pl, opts)
106
end
107
108
exe_post_generation(opts)
109
exe
110
end
111
112
def generate_payload_dll(opts = {})
113
return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty?
114
return get_eicar_exe if datastore['EXE::EICAR']
115
116
exe_init_options(opts)
117
plat = opts[:platform]
118
pl = opts[:code]
119
pl ||= payload.encoded
120
121
#Ensure opts[:arch] is an array
122
opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array
123
124
# NOTE: Only x86_64 linux is supported here.
125
if plat.index(Msf::Module::Platform::Linux)
126
if opts[:arch] && opts[:arch].index(ARCH_X64)
127
dll = Msf::Util::EXE.to_linux_x64_elf_dll(framework, pl,opts)
128
elsif opts[:arch] && opts[:arch].index(ARCH_AARCH64)
129
dll = Msf::Util::EXE.to_linux_aarch64_elf_dll(framework, pl,opts)
130
end
131
elsif plat.index(Msf::Module::Platform::Windows)
132
if opts[:arch] && opts[:arch].index(ARCH_X64)
133
dll = Msf::Util::EXE.to_win64pe_dll(framework, pl, opts)
134
else
135
dll = Msf::Util::EXE.to_win32pe_dll(framework, pl, opts)
136
end
137
end
138
139
exe_post_generation(opts)
140
dll
141
end
142
143
def generate_payload_dccw_gdiplus_dll(opts = {})
144
return get_custom_exe unless datastore['EXE::Custom'].to_s.strip.empty?
145
return get_eicar_exe if datastore['EXE::EICAR']
146
147
exe_init_options(opts)
148
plat = opts[:platform]
149
pl = opts[:code]
150
151
pl ||= payload.encoded
152
153
#Ensure opts[:arch] is an array
154
opts[:arch] = [opts[:arch]] unless opts[:arch].kind_of? Array
155
if opts[:arch] && opts[:arch].index(ARCH_X64)
156
dll = Msf::Util::EXE.to_win64pe_dccw_gdiplus_dll(framework, pl, opts)
157
else
158
dll = Msf::Util::EXE.to_win32pe_dccw_gdiplus_dll(framework, pl, opts)
159
end
160
161
exe_post_generation(opts)
162
dll
163
end
164
165
def generate_payload_msi(opts = {})
166
return get_custom_exe(datastore['MSI::Custom']) unless datastore['MSI::Custom'].to_s.strip.empty?
167
return get_eicar_exe if datastore['MSI::EICAR']
168
169
exe = generate_payload_exe(opts)
170
171
opts.merge! ({
172
:msi_template => datastore['MSI::Template'],
173
:msi_template_path => datastore['MSI::Path'],
174
:uac => datastore['MSI::UAC']
175
})
176
177
Msf::Util::EXE.to_exe_msi(framework, exe, opts)
178
end
179
180
protected
181
def exe_init_options(opts)
182
opts.merge!(
183
{
184
:template_path => datastore['EXE::Path'],
185
:template => datastore['EXE::Template'],
186
:inject => datastore['EXE::Inject'],
187
:fallback => datastore['EXE::FallBack'],
188
:sub_method => datastore['EXE::OldMethod']
189
})
190
191
# NOTE: If code and platform/arch are supplied, we use those values and skip initialization.
192
#
193
# This part is kind of tricky so we need to explain the logic behind the following load order.
194
# First off, platform can be seen from different sources:
195
#
196
# 1. From the opts argument. For example: When you are using generate_payload_exe, and you want
197
# to set a specific platform. This is the most explicit. So we check first.
198
#
199
# 2. From the metadata of a payload module. Normally, a payload module should include the platform
200
# information, with the exception of some generic payloads. For example: generic/shell_reverse_tcp.
201
# This is the most trusted source.
202
#
203
# 3. From the exploit module's target.
204
#
205
# 4. From the exploit module's metadata.
206
#
207
# Architecture shares the same load order.
208
209
unless opts[:code] && opts[:platform]
210
if self.respond_to?(:payload_instance) && payload_instance.platform.platforms != [Msf::Module::Platform]
211
opts[:platform] = payload_instance.platform
212
elsif self.respond_to? :target_platform
213
opts[:platform] = target_platform
214
elsif self.respond_to? :platform
215
opts[:platform] = platform
216
end
217
end
218
219
unless opts[:code] && opts[:arch]
220
if self.respond_to? :payload_instance
221
opts[:arch] = payload_instance.arch
222
elsif self.respond_to? :target_arch
223
opts[:arch] = target_arch
224
elsif self.respond_to? :arch
225
opts[:arch] = arch
226
end
227
end
228
end
229
230
def exe_post_generation(opts)
231
if opts[:fellback]
232
print_status("Warning: Falling back to default template: #{opts[:fellback]}")
233
end
234
end
235
236
end
237
end
238
239