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